Kudu和Impala均是Cloudera贡献给Apache基金会的顶级项目。Kudu作为底层存储,在支持高并发低延迟kv查询的同时,还保持良好的Scan性能,该特性使得其理论上能够同时兼顾OLTP类和OLAP类查询。Impala作为老牌的SQL解析引擎,其面对即席查询(Ad-Hoc Query)类请求的稳定性和速度在工业界得到过广泛的验证,Impala并没有自己的存储引擎,其负责解析SQL,并连接其底层的存储引擎。在发布之初Impala主要支持HDFS,Kudu发布之后,Impala和Kudu更是做了深度集成。
在众多大数据框架中,Impala定位类似Hive,不过Impala更关注即席查询SQL的快速解析,对于执行时间过长的SQL,仍旧是Hive更合适。对于GroupBy等SQL查询,Impala进行的是内存计算,因而Impala对机器配置要求较高,官方建议内存128G以上,此类问题Hive底层对应的是传统的MapReduce计算框架,虽然执行效率低,但是稳定性好,对机器配置要求也低。
执行效率是Impala的最大优势,对于存储在HDFS中的数据,Impala的解析速度本来就远快于Hive,有了Kudu加成之后,更是如虎添翼,部分查询执行速度差别可达百倍。
值得注意的是,Kudu和Impala的英文原意是来自非洲的两个不同品种的羚羊,Cloudera这个公司非常喜欢用跑的快的动物来作为其产品的命名。
OLTP与OLAP
OLTP(On-line Transaction Processing) 面向的是高并发低延时的增删改查(INSERT, DELETE, UPDATE, SELECT, etc..)。
OLAP(On-line Analytical Processing) 面向的是BI分析型数据请求,其对延时有较高的容忍度,处理数据量相较OLTP要大很多。
传统意义上与OLTP对应的是MySQL等关系型数据库,与OLAP相对应的则是数据仓库。OLTP与OLAP所面向的数据存储查询引擎是不同的,其处理的请求不一样,所需要的架构也大不相同。这个特点意味着数据需要储存在至少两个地方,需要定期或者实时的同步,同时还需要保持一致性,该特点对数据开发工程师造成了极大的困扰,浪费了同学们大量的时间在数据的同步和校验上。Kudu+Impala的出现,虽然不能完美的解决这个问题,但不可否认,其缓解了这个矛盾。
在此需要注意的是OLTP并没有严格要求其事务处理满足ACID四个条件。事实上,OLTP是比ACID更早出现的概念。在本文中,OLTP和OLAP的概念关注在数据量、并发量、延时要求等方面,不关注事务。
Kudu 来由
Kudu最早是Cloudera公司开发,并与2015年12月3日贡献给Apache基金会,2016年7月25日正式宣布毕业,升级为 Apache 顶级项目。值得注意的是Kudu在开发之中得到了中国公司小米的大力支持,小米深度参与到了Kudu的开发之中,拥有一位Kudu的Committer。
从Kudu毕业时间可以看出,Kudu还很年轻,有不少细节需要完善,也有一些重大特性待开发(如事务)。不过Kudu+Impala的组合正在得到越来越多公司的实践,目前也是Cloudera公司主推的新式大数据解决方案。
其他名词解释
Kudu是围绕Hadoop生态圈建立存储引擎,Kudu拥有和Hadoop生态圈共同的设计理念,它运行在普通的服务器上、可分布式规模化部署、并且满足工业界的高可用要求。其设计理念为fast analytics on fast data.。Kudu的大部分场景和Hbase类似,其设计降低了随机读写性能,提高了扫描性能,在大部分场景下,Kudu在拥有接近Hbase的随机读写性能的同时,还有远超Hbase的扫描性能。
区别于Hbase等存储引擎,Kudu有如下优势:
流式实时计算场景
流式计算场景通常有持续不断地大量写入,与此同时这些数据还要支持近乎实时的读、写以及更新操作。Kudu的设计能够很好的处理此场景。
时间序列存储引擎(TSDB)
Kudu的hash分片设计能够很好地避免TSDB类请求的局部热点问题。同时高效的Scan性能让Kudu能够比Hbase更好的支持查询操作。
机器学习&数据挖掘
机器学习和数据挖掘的中间结果往往需要高吞吐量的批量写入和读取,同时会有少量的随机读写操作。Kudu的设计可以很好地满足这些中间结果的存储需求。
与历史遗产数据共存
在工业界实际生产环境中,往往有大量的历史遗产数据。Impala可以同时支持HDFS、Kudu等多个底层存储引擎,这个特性使得在使用的Kudu的同时,不必把所有的数据都迁移到Kudu。
列式存储
毫无疑问,Kudu是一个纯粹的列式存储引擎,相比Hbase只是按列存放数据,Kudu的列式存储更接近于Parquet,在支持更高效Scan操作的同时,还占用更小的存储空间。列式存储有如此优势,主要因为两点:1. 通常意义下的OLAP查询只访问部分列数据,列存储引擎在这种情况下支持按需访问,而行存储引擎则必须检索一行中的所有数据。2. 数据按列放一起一般意义来讲会拥有更高的压缩比,这是因为列相同的数据往往拥有更高的相似性。
Table
Kudu中所有的数据均存储在Table之中,每张表有其对应的表结构和主键,数据按主键有序存储。因为Kudu设计为支持超大规模数据量,Table之中的数据会被分割成为片段,称之为Tablet。
Tablet
一个Tablet把相邻的数据放在一起,跟其他分布式存储服务类似,一个Tablet会有多个副本放置在不同的服务器上面,在同一时刻,仅有一个Tablet作为leader存在,每个副本均可单独提供读操作,写操作则需要一致性同步写入。
Tablet Server
Tablet服务顾名思义,对Tablet的读写操作会通过该服务完成。对于一个给定的tablet,有一个作为leader,其他的作为follower,leader选举和灾备原则遵循Raft一致性算法,该算法在后文中有介绍。需要注意的是一个Tablet服务所能承载的Tablet数量有限,这也要求的Kudu表结构的设计需要合理的设置Partition数量,太少会导致性能降低,太多会造成过多的Tablet,给Tablet服务造成压力。
Master
master存储了其他服务的所有元信息,在同一时刻,最多有一个master作为leader提供服务,leader宕机之后会按照Raft一致性算法进行重新选举。
master会协调client传来的元信息读写操作。比如当创建一个新表的时候,client发送请求给master,master会转发请求给catelog、 tablet等服务。
master本身并不存储数据,数据存储在一个tablet之中,并且会按照正常的tablet进行副本备份。
Tablet服务会每秒钟跟master进行心跳连接。
Raft Consensus Algorithm
Kudu 使用Raft一致性算法,该算法将节点分为follower、candidate、leader三种角色,当leader节点宕机时,follower会成为candidate并且通过多数选举原则成为一个新的leader,因为有多数选举原则,所以在任意时刻,最多有一个leader角色。leader接收client上传的数据修改指令并且分发给follower,当多数follower写入时,leader会认为写入成功并告知client。
Catalog Table
Catelog表存储了Kudu的一些元数据,包括Tables和Tablets。
从下图可以看出有三台Master,其中一个是leader,另外两个是follower。
有四台Tablet server,n个tablets及其副本均匀分布在这四台机器上。每个tablet有一个leader,两个follower。每个表会按照分片的数量分成多个tablet。
Impala是建立在Hadoop生态圈的交互式SQL解析引擎,Impala的SQL语法与Hive高度兼容,并且提供标准的ODBC和JDBC接口。Impala本身不提供数据的存储服务,其底层数据可来自HDFS、Kudu、Hbase甚至亚马逊S3。
Impapa最早由Cloudera公司开发,于15年12月贡献给Apache基金会,目前其正式名字为Apache Impala(incubating)
Impala本身并不是Hive的完全替代品,对于一些大吞吐量长时间执行的请求,Hive仍然是最稳定最佳的选择,哪怕是SparkSQL,其稳定性也无法跟Hive媲美。
稳定性方面Impala不如Hive,但是在执行效率方面,Impala毫无疑问可以秒杀Hive。Impala采用内存计算模型,对于分布式Shuffle,可以尽可能的利用现代计算机的内存和CPU资源。同时,Impala也有预处理和分析技术,表数据插入之后可以用COMPUTE STATS指令来让Impala对行列数据深度分析。
Impala高度兼容Hive,不过有部分Hive的SQL特性在Impala中并不支持,其中包括:
select v1.c1 result1, v2.c1 result2 from (select count(distinct col1) as c1 from t1) v1 cross join (select count(distinct col2) as c1 from t1) v2;
Impala和Hive的兼容不仅仅体现在语法上,在架构上Impala和Hive也保持着相当程度上的兼容性,Impala直接采用Hive的元数据库,对于公司而言,已经在Hive中的表结构无需迁移,Impala可以直接使用。
Kudu+Impala为实时数据仓库存储提供了良好的解决方案。这套架构在支持随机读写的同时还能保持良好的Scan性能,同时其对Spark等流式计算框架有官方的客户端支持。这些特性意味着数据可以从Spark实时计算中实时的写入Kudu,上层的Impala提供BI分析SQL查询,对于数据挖掘和算法等需求可以在Spark迭代计算框架上直接操作Kudu底层数据。
不支持。虽然Impala设计为BI-即席查询平台,但是其单个SQL执行代价较高,不支持低延时、高并发场景。
不能,Impala设计为内存计算模型,其执行效率高,但是稳定性不如Hive,对于长时间执行的SQL请求,Hive仍然是第一选择。
类似于Spark,Impala会把数据尽可能的放入内存之中进行计算,虽然内存不够时,Impala会借助磁盘进行计算,但是毫无疑问,内存的大小决定了Impala的执行效率和稳定性。Impala官方建议内存要至少128G以上,并且把80%内存分配给Impala
Impala不会对表数据Cache,Impala仅仅会Cache一些表结构等元数据。虽然在实际情况下,同样的query第二次跑可能会更快,但这不是Impala的Cache,这是Linux系统或者底层存储的Cache。
可以。Impala1.2版本支持的UDFs,不过Impala的UDF添加要比Hive复杂一些。
Impala为速度而生,其在执行效率细节上做了很多优化。在大的方面,相比Hive,Impala并没有采用MapReduce作为计算模型,MapReduce是个伟大的发明,解决了很多分布式计算问题,但是很遗憾,MapReduce并不是为SQL而设计的。SQL在转换成MapReduce计算原语时,往往需要多层迭代,数据需要较多的落地次数,造成了极大地浪费。
同时Impala现代化的计算框架,能够更好的利用现代的高性能服务器。
Kudu在某些特性上和Hbase很相似,难免会放在一起比较。然而Kudu和Hbase有如下两点本质不同。
Kudu不是纯内存数据库,Kudu的数据块分MemRowSet和DiskRowSet,大部分数据存储在磁盘上。
Kudu的内存存储采用的是行存储,磁盘存储是列存储,其格式和Parquet很相似,部分不相同的部分是为了支持随机读写请求。
compactions被设计为Kudu自动后台执行,并且是缓慢分块执行,当前不支持手动操作。
不支持。Hbase支持该特性。
现代的分布式存储设计往往会把数据按主键进行有序存储。这样会造成一些局部的热点访问,比如把时间作为主键的日志实时存储模型中,日志的写入总是在时间排序的最后,这在Hbase中会造成严重的局部热点。Kudu也有同样的问题,但是比Hbase好很多,Kudu支持hash分片,数据的写入会先按照hash找到对应的tablet,再按主键有序的写入。
和Hbase一样,Kudu是CAP中的CP。只要一个客户端写入数据成功,其他客户端读到的数据都是一致的,如果发生宕机,数据的写入会有一定的延时。
不支持,Kudu只支持Primary Key一个索引,但是可以把Primary Key设置为包含多列。自动增加的索引、多索引支持、外键等传统数据库支持的特性Kudu正在设计和开发中。
Kudu不支持多行的事务操作,不支持回滚事务,不过Kudu可以保证单行操作的原子性。