Kudu:支持快速分析的新型Hadoop存储系统

MadFlemming 8年前
   <p>Kudu 是 Cloudera 开源的新型列式存储系统,是 Apache Hadoop 生态圈的新成员之一( incubating ),专门为了对快速变化的数据进行快速的分析,填补了以往 Hadoop 存储层的空缺。本文主要对 Kudu 的动机、背景,以及架构进行简单介绍。</p>    <h2>背景——功能上的空白</h2>    <p>        Hadoop 生态系统有很多组件,每一个组件有不同的功能。在现实场景中,用户往往需要同时部署很多 Hadoop 工具来解决同一个问题,这种架构称为 混合架构 (hybrid architecture) 。 比如,用户需要利用 Hbase 的快速插入、快读 random access 的特性来导入数据, HBase 也允许用户对数据进行修改, HBase 对于大量小规模查询也非常迅速。同时,用户使用 HDFS/Parquet + Impala/Hive 来对超大的数据集进行查询分析,对于这类场景, Parquet 这种列式存储文件格式具有极大的优势。</p>    <p>        很多公司都成功地部署了 HDFS/Parquet + HBase 混合架构,然而这种架构较为复杂,而且在维护上也十分困难。首先,用户用 Flume 或 Kafka 等数据 Ingest 工具将数据导入 HBase ,用户可能在 HBase 上对数据做一些修改。然后每隔一段时间 ( 每天或每周 ) 将数据从 Hbase 中导入到 Parquet 文件,作为一个新的 partition 放在 HDFS 上,最后使用 Impala 等计算引擎进行查询,生成最终报表。</p>    <p><img src="https://simg.open-open.com/show/3ab9506c0803d214c7f82ab09ac1c565.png"></p>    <p>这样一条工具链繁琐而复杂,而且还存在很多问题,比如:</p>    <ul>     <li>Ÿ   <em> 如何处理某一过程出现失败? </em></li>     <li>Ÿ   <em> 从 HBase </em> <em> 将数据导出到文件,多久的频率比较合适? </em></li>     <li>Ÿ   <em> 当生成最终报表时,最近的数据并无法体现在最终查询结果上。 </em></li>     <li>Ÿ   <em> 维护集群时,如何保证关键任务不失败? </em></li>     <li>Ÿ   <em> Parquet </em> <em> 是 immutable </em> <em> ,因此当 HBase </em> <em> 中删改某些历史数据时,往往需要人工干预进行同步。 </em></li>    </ul>    <p>        这时候,用户就希望能够有一种优雅的存储解决方案,来应付不同类型的工作流,并保持高性能的计算能力。 Cloudera 很早就意识到这个问题,在 2012 年就开始计划开发 Kudu 这个存储系统,终于在 2015 年发布并开源出来。 Kudu 是对 HDFS 和 HBase 功能上的补充,能提供快速的分析和实时计算能力,并且充分利用 CPU 和 I/O 资源,支持数据原地修改,支持简单的、可扩展的数据模型。</p>    <h2>背景——新的硬件设备</h2>    <p>        RAM 的技术发展非常快,它变得越来越便宜,容量也越来越大。 Cloudera 的客户数据显示,他们的客户所部署的服务器, 2012 年每个节点仅有 32GB RAM ,现如今增长到每个节点有 128GB 或 256GB RAM 。存储设备上更新也非常快, 在很多普通服务器中部署 SSD 也是屡见不鲜。 HBase 、 HDFS 、以及其他的 Hadoop 工具都在不断自我完善,从而适应硬件上的升级换代。然而,从根本上, HDFS 基于 03 年 GFS , HBase 基于 05 年 BigTable ,在当时系统瓶颈主要取决于底层磁盘速度。当磁盘速度较慢时, CPU 利用率不足的根本原因是磁盘速度导致的瓶颈,当磁盘速度提高了之后, CPU 利用率提高,这时候 CPU 往往成为系统的瓶颈。 HBase 、 HDFS 由于年代久远,已经很难从基本架构上进行修改,而 Kudu 是基于全新的设计,因此可以更充分地利用 RAM 、 I/O 资源,并优化 CPU 利用率。我们可以理解为, Kudu 相比与以往的系统, CPU 使用降低了, I/O 的使用提高了, RAM 的利用更充分了。</p>    <h2>简介</h2>    <p>        Kudu 设计之初,是为了解决一下问题:</p>    <ul>     <li>Ÿ   <em> 对数据扫描 (scan) </em> <em> 和随机访问 (random access) </em> <em> 同时具有高性能,简化用户复杂的混合架构 </em></li>     <li>Ÿ   <em> 高 CPU </em> <em> 效率,使用户购买的先进处理器的的花费得到最大回报 </em></li>     <li>Ÿ   <em> 高 IO </em> <em> 性能,充分利用先进存储介质 </em></li>     <li>Ÿ   <em> 支持数据的原地更新,避免额外的数据处理、数据移动 </em></li>     <li>Ÿ   <em> 支持跨数据中心 replication </em></li>    </ul>    <p>        Kudu 的很多特性跟 HBase 很像,它支持索引键的查询和修改。 Cloudera 曾经想过基于 Hbase 进行修改,然而结论是对 HBase 的改动非常大, Kudu 的数据模型和磁盘存储都与 Hbase 不同。 HBase 本身成功的适用于大量的其它场景,因此修改 HBase 很可能吃力不讨好。最后 Cloudera 决定开发一个全新的存储系统。</p>    <p><img src="https://simg.open-open.com/show/29d294d9089e525ab3caf35a0fe3b744.png"></p>    <p>        Kudu 的定位是提供 ”fast analytics on fast data” ,也就是在快速更新的数据上进行快速的查询。它定位 OLAP 和少量的 OLTP 工作流,如果有大量的 random accesses ,官方建议还是使用 HBase 最为合适。</p>    <h2>架构与设计</h2>    <p>1. 基本框架</p>    <p>        Kudu 是用于存储结构化( structured )的表( Table )。表有预定义的带类型的列( Columns ),每张表有一个主键( primary key )。主键带有唯一性( uniqueness )限制,可作为索引用来支持快速的 random access 。</p>    <p>类似于 BigTable , Kudu 的表是由很多数据子集构成的,表被水平拆分成多个 Tablets. Kudu 用以每个 tablet 为一个单元来实现数据的 durability 。 Tablet 有多个副本,同时在多个节点上进行持久化。</p>    <p>        Kudu 有两种类型的组件, Master Server 和 Tablet Server 。 Master 负责管理元数据。这些元数据包括 talbet 的基本信息,位置信息。 Master 还作为负载均衡服务器,监听 Tablet Server 的健康状态。对于副本数过低的 Tablet , Master 会在起 replication 任务来提高其副本数。 Master 的所有信息都在内存中 cache ,因此速度非常快。每次查询都在百毫秒级别。 Kudu 支持多个 Master ,不过只有一个 active Master ,其余只是作为灾备,不提供服务。</p>    <p>        Tablet Server 上存了 10~100 个 Tablets ,每个 Tablet 有 3 (或 5 )个副本存放在不同的 Tablet Server 上,每个 Tablet 同时只有一个 leader 副本,这个副本对用户提供修改操作,然后将修改结果同步给 follower 。 Follower 只提供读服务,不提供修改服务。副本之间使用 raft 协议来实现 High Availability ,当 leader 所在的节点发生故障时, followers 会重新选举 leader 。根据官方的数据,其 MTTR 约为 5 秒,对 client 端几乎没有影响。 Raft 协议的另一个作用是实现 Consistency 。 Client 对 leader 的修改操作,需要同步到 N/2+1 个节点上,该操作才算成功。</p>    <p><img src="https://simg.open-open.com/show/507d844746f76d809d14cfac4bd6fd9b.jpg"></p>    <p>        Kudu 采用了类似 log-structured 存储系统的方式,增删改操作都放在内存中的 buffer ,然后才 merge 到持久化的列式存储中。 Kudu 还是用了 WALs 来对内存中的 buffer 进行灾备。</p>    <p>2. 列式存储</p>    <p>        持久化的列式存储存储,与 HBase 完全不同,而是使用了类似 Parquet 的方式,同一个列在磁盘上是作为一个连续的块进行存放的。例如,图中左边是 推ter 保存推文的一张表,而图中的右边表示了表在磁盘中的的存储方式,也就是将同一个列放在一起存放。这样做的第一个好处是,对于一些聚合和 join 语句,我们可以尽可能地减少磁盘的访问。例如,我们要用户名为 newsycbot</p>    <p>的推文数量,使用查询语句:</p>    <pre>  SELECT COUNT(*) FROM tweets WHERE user_name = ‘newsycbot’;</pre>    <p><img src="https://simg.open-open.com/show/0541a9546f091d9a4ea704b1615f64c4.jpg"></p>    <p>        我们只需要查询 User_name 这个 block 即可。同一个列的数据是集中的,而且是相同格式的, Kudu 可以对数据进行编码,例如字典编码,行长编码, bitshuffle 等。通过这种方式可以很大的减少数据在磁盘上的大小,提高吞吐率。除此之外,用户可以选择使用通用的压缩格式对数据进行压缩,如 LZ4, gzip, 或 bzip2 。这是可选的,用户可以根据业务场景,在数据大小和 CPU 效率上进行权衡。这一部分的实现上, Kudu 很大部分借鉴了 Parquet 的代码。</p>    <p><img src="https://simg.open-open.com/show/bd4d72ba5e660b5b50e327865acb915c.jpg"></p>    <p>        HBase 支持 snappy 存储,然而因为它的 LSM 的数据存储方式,使得它很难对数据进行特殊编码,这也是 Kudu 声称具有很快的 scan 速度的一个很重要的原因。不过,因为列式编码后的数据很难再进行修改,因此当这写数据写入磁盘后,是不可变的,这部分数据称之为 base 数据。 Kudu 用 MVCC (多版本并发控制)来实现数据的删改功能。更新、删除操作需要记录到特殊的数据结构里,保存在内存中的 DeltaMemStore 或磁盘上的 DeltaFIle 里面。 DeltaMemStore 是 B-Tree 实现的,因此速度快,而且可修改。磁盘上的 DeltaFIle 是二进制的列式的块,和 base 数据一样都是不可修改的。因此当数据频繁删改的时候,磁盘上会有大量的 DeltaFiles 文件, Kudu 借鉴了 Hbase 的方式,会定期对这些文件进行合并。</p>    <p>3. 对外接口</p>    <p>        Kudu 提供 C++ 和 JAVA API ,可以进行单条或批量的数据读写, schema 的创建修改。除此之外, Kudu 还将与 hadoop 生态圈的其它工具进行整合。目前, kudu beta 版本对 Impala 支持较为完善,支持用 Impala 进行创建表、删改数据等大部分操作。 Kudu 还实现了 KuduTableInputFormat 和 KuduTableOutputFormat ,从而支持 Mapreduce 的读写操作。同时支持数据的 locality 。目前对 spark 的支持还不够完善, spark 只能进行数据的读操作。</p>    <h2>使用案例——小米</h2>    <p>小米是 Hbase 的重度用户,他们每天有约 50 亿条用户记录。小米目前使用的也是 HDFS + HBase 这样的混合架构。可见该流水线相对比较复杂,其数据存储分为 SequenceFile , Hbase 和 Parquet 。</p>    <p><img src="https://simg.open-open.com/show/1d6710db9e2e6bf07c5392a9b37086f0.jpg"></p>    <p>在使用 Kudu 以后, Kudu 作为统一的数据仓库,可以同时支持离线分析和实时交互分析。</p>    <p><img src="https://simg.open-open.com/show/b6b4403b0503194ba009e17579befbad.jpg"></p>    <h2>性能测试</h2>    <p>1. 和 parquet 的比较</p>    <p><img src="https://simg.open-open.com/show/95e4325812029819332b0724569d38d9.jpg"></p>    <p>        图是官方给出的用 Impala 跑 TPC-H 的测试,对比 Parquet 和 Kudu 的计算速度。从图中我们可以发现, Kudu 的速度和 parquet 的速度差距不大,甚至有些 Query 比 parquet 还快。然而,由于这些数据都是在内存缓存过的,因此该测试结果不具备参考价值。</p>    <p>2. 和 Hbase 的比较</p>    <p><img src="https://simg.open-open.com/show/68ccb374b100faa8454580fab3cb608e.jpg"></p>    <p>        图是官方给出的另一组测试结果,从图中我们可以看出,在 scan 和 range 查询上, kudu 和 parquet 比 HBase 快很多,而 random access 则比 HBase 稍慢。然而数据集只有 60 亿行数据,所以很可能这些数据也是可以全部缓存在内存的。对于从内存查询,除了 random access 比 HBase 慢之外, kudu 的速度基本要优于 HBase 。</p>    <p>3. 超大数据集的查询性能</p>    <p>        Kudu 的定位不是 in-memory database 。因为它希望 HDFS/Parquet 这种存储,因此大量的数据都是存储在磁盘上。如果我们想要拿它代替 HDFS/Parquet + HBase ,那么超大数据集的查询性能就至关重要,这也是 Kudu 的最初目的。然而,官方没有给出这方面的相关数据。由于条件限制,网易暂时未能完成该测试。下一步,我们将计划搭建 10 台 Kudu + Impala 服务器,并用 tpc-ds 生成超大数据,来完成该对比测验。</p>    <p> </p>    <p>来自:http://www.bitstech.net/2016/08/11/kudu支持快速分析的新型hadoop存储系统/</p>    <p> </p>