Apache Kudu 学习总结

Apache Kudu 学习秘籍

个人公众号
大数据理论及实战
大数据理论及实战
image-20210626211313350

​ A new addition to the open source Apache Hadoop ecosystem, Apache Kudu completes Hadoop’s storage layer to enable fast analytics on fast data.

Apache Kudu 概述

产生背景

​ Cloudera公司研发工程师 Todd Lipcon在开发初,本来对hbase改造、支持大数据量更新,但是由于改动源码太大,所以kudu这时候产生了。

​ kudu是2015年开源的,开发语言是C++,截止目前为止,已经更新到1.10 版本,近些年发展十分迅速,在阿里、小米、网易、京东、浪潮等公司的大数据架构(离线、实时、元数据管理、数据质量、存储和成本管理)中,kudu都有着不可替代的地位。
在 Kudu 之前,大数据主要以两种方式存储:

第一种是静态数据: 以 HDFS 引擎作为存储引擎,其是一种仅支持追加写的文件系统,适用于顺序扫描大规模的大数据分析场景。这类存储的局限性是数据无法进行随机的读写和批量的更新操作。

第二种是动态数据: 以 HBase作为存储引擎,适用于大数据在线、实时、高并发、随机读写或短扫描的场景,这类存储的局限性是批量读取吞吐量远不如 HDFS、不适用于批量数据分析的场景。业界主要用于构建实时仓库等。

Kudu、HDFS、HBase对比图

而Kudu在 HDFS 和 HBase 这两个中平衡了随机读写和批量分析的性能,既支持了SQL实时查询,也支持了数据更新插入操作。并且完美的和impala集成,统一了hdfs数据源和kudu数据源,从而使得开发人员能够高效的进行数据分析。

应用场景:

  • 适合于在线实时分析的应用

    在数据分析中,一个常见的挑战是新数据快速且不断地到达,并且需要在接近实时的情况下提供相同的数据,以便进行读取、扫描和更新。Kudu提供了快速插入和更新的强大组合,以及高效的柱状扫描,从而在单个存储层上支持实时分析用例。

  • 适合大数据量更新操作的应用

  • 适合将mysql的数据同步到kudu,减轻备库mysql查询的压力

  • 适合存储ADS数据,包含用户标签、各类指标数据等

  • 适合于存储结构化数据

  • 适合于和Impala继承,SQL分析数据

  • 适合于和HDFS一起使用,聚合数据源

  • 实时预测模型的应用,支持根据所有历史数据周期地更新模型

Apache Kudu 体系结构概述

Kudu网络体系结构图

下图显示了一个Kudu集群,其中有三个主机和多个 tablet servers,每个tablet server 都服务于多个tablet

Kudu 的特点

  • 特点一:主从架构 主为master,从为 tablet server,通常为三主多从
  • 特点二:高可用性(High availability)Tablet server 和 Master 使用 Raft Consensus Algorithm 来保证节点的高可用,确保只要有一半以上的副本可用,该 tablet 便可用于读写。例如,如果3个副本中有2个或5个副本中的3个可用,则该tablet可用。即使在 leader tablet 出现故障的情况下,读取功能也可以通过 read-only(只读的)follower tablets来进行服务,或者是leader宕掉的情况下,会根据raft机制重新选举leader
  • 特点三:水平可扩展
  • 特点四:OLAP 工作的快速处理。
  • 特点五:与 MapReduce,Spark ,Impala和其他 Hadoop 生态系统组件集成
  • 特点六:使用 Cloudera Manager 轻松维护和管理
  • 特点七:底层存储完全是列式结构,每一列都可以自定义压缩
  • 特点八:查询出来的数据是结构化模型,支持sql操

Kudu 的概念和术语

  • 开发语言 C++
  • Columnar Data Store(列式数据存储)

  • Read Efficiency(高效读取)对于分析查询,允许读取单个列或该列的一部分同时忽略其他列

  • Data Compression(数据压缩)于给定的列只包含一种类型的数据,所以基于此模式的压缩会比压缩混合数据类型(在基于行的解决案中使用)时更有效几个数量级。结合从列读取数据的效率,压缩允许从磁盘读取更少的块时完成查询

  • Table(表)一张table是数据存储在 Kudu 的位置。表具有schema和全局有序的primary key(主键)。table被分成很多段,也就是称为tablets

  • Tablet(段)一个tablet是一张table连续的segment,与其它数据存储引擎或关系型数据库partition(分区)相似。在一定的时间范围内,tablet的副本冗余到多个tserver服务器上,其中一个副本被认为是leader tablet。任何副本都可以对读取进行服务,并且写入时需要为tablet服务的一组tablet server之间达成一致性。一张表分成多个tablet,分布在不同的tablet server中,最大并行化操作,Tablet在Kudu中被切分为更小的单元,叫做RowSets,RowSets分为两种MemRowSets和DiskRowSet,MemRowSets每生成32M,就溢写到磁盘中,也就是DiskRowSet

  • Tablet Server tablet server是存储tablet和为tablet向client提供服务。对于给定的tablet,一个tablet server充当 leader,其他tablet server充当该tablet的follower副本。只有leader为每一个服务提供写请求,leader和followers为每个服务提供读请求。leader使用Raft协议来进行选举 。一个tablet server可以服务多个tablets,并且一个 tablet 可以被多个tablet servers服务着。

  • Master 保持跟踪所有的tablets、tablet servers、catalog tables和其它与集群相关的metadata。在给定的时间点,只能有一个起作用的master(也就是 leader)。如果当前的leader消失,则选举出一个新的master,使用Raft协议来进行选举。master还协调客户端的metadata operations(元数据操作)。例如,当创建新表时,客户端内部将请求发送给master。 master将新表的元数据写入catalog table,并协调在tablet server上创建tablet的过程。所有master的元数据都存储在一个tablet中,可以复制到所有其他候选的master。tablet server以设定的间隔向master发出心跳(默认值为每秒一次)。master是以文件的形式存储在磁盘中。

  • Raft Consensus Algorithm Kudu 使用 Raft consensus algorithm 作为确保常规 tablet 和 master 数据的容错性和一致性的手段。通过 Raft协议,tablet 的多个副本选举出 leader,它负责接受请求和复制数据写入到其他follower副本。一旦写入的数据在大多数副本中持久化后,就会向客户确认。给定的一组N副本(通常为 3 或 5 个)能够接受最多(N - 1)/2 错误的副本的写入。

  • Catalog Table(目录表) catalog table是Kudu 的 metadata(元数据中)的中心位置。它存储有关tables和tablets的信息。该catalog table(目录表)可能不会被直接读取或写入。相反,它只能通过客户端 API中公开的元数据操作访问。catalog tables存储以下两类元数据。

  • Tables table schemas, locations, and states(表结构,位置和状态)

  • Tablets 现有tablet 的列表,每个 tablet 的副本所在哪些tablet server,tablet的当前状态以及开始和结束的keys(键)

  • Logical Replication Kudu复制操作,而不是磁盘上的数据。这称为逻辑复制,而不是物理复制。这有几个优点:

  1. 虽然插入和更新确实通过网络传输数据,但是删除不需要移动任何数据。删除操作被发送到每个tablet服务器,该服务器在本地执行删除操作。
  2. 物理操作(如压缩)不需要通过Kudu中的网络传输数据。这与使用HDFS的存储系统不同,HDFS需要通过网络传输块,以满足所需的副本数量。
  3. Tablets不需要在同一时间或同一时间表上执行压缩,或者在物理存储层上保持同步。这减少了所有 tablet servers 同时经历高延迟的机会,因为压缩或写负载过重。

Kudu的底层存储原理

Kudu底层存储架构图

Kudu底层存储架构图

架构图剖析
  • 1个Table包含多个Tablet,其中Tablet的数量是根据hash或者是range进行设置的(在创建表是否分区时决定)。
  • 1个Tablet中包含一个MetaData信息和多个RowSet信息,其中MetaData中的信息是:block和block在data中的位置。
  • 1个 RowSet 包含一个 MemRowSet 和多个 DiskRowSet,其中 MemRowSet 用于存储 insert 数据和 update 后的数据,写满后会刷新到磁盘中也就是多个 DiskRowSet 中,默认是1G刷新一次或者是2分钟。
  • 1个DiskRowSet用于老数据的mutation,比如说数据的更新操作,后台定期对DiskRowSet进行合并操作,删除历史数据和没有的数据,减少查询过程中的IO开销。1个DiskRowSet包含BloomFilter、Ad_hoc Index、UndoFile、RedoFile、BaseData、DeltaMem
  • BloomFile:根据DiskRowSet中key生成一个bloomfilter,用于快速模糊的定位某一个key是否在DiskRowSet中。
  • Ad_hoc Index:是主键的索引,用于定位key在DiskRowSet中具体哪个偏移位置。
  • BaseData:是MemRowSet flush下来的数据,按照列存储,按照主键有序。
  • UndoFile:是BaseData之前的历史数据。
  • RedoFile:是BaseData之后的mutation记录,可以获得较新的数据。
  • DeltaMem:用于在内存中存储mutation记录,先写到内存中,然后写满后flush到磁盘,形成deltafile。
MemRowSet 剖析 :
  • 实现方式:B+Tree
DiskRowSet剖析:
  • 实现方式:二叉平衡树

  • 内部数据组织: DeltaMem和MemRowSet在存在中的组织方式是一致的,都是B+Tree,在磁盘上的存储都是放在CFile文件中的,下图为CFile的文件格式

    CFile文件格式图

    Cfile:包含Header,Data,Index,Footer四块,Index有两种,posidx index是根据rowId找到Data中的偏移,validx index是根据key的值找到data中的偏移,validx只针对只有一个column为key的情况下,这个时候DiskRowSet是没有Ad_hoc索引的,使用validx来代替。这两个index内部实现了B-Tree,index不一定是联系的,在达到一定长度后就会刷盘,Footer是记录CFile的元数据,包括posidx_index,validx_index两棵树根节点所在位置,数据条目、编码、压缩方式等

  • **压缩:**对于ad_hoc文件使用的prefix,delta fle使用的是plain,bloomfile使用的是plain

  • 由上图知: 磁盘上每一个DiskRowSet有若*.metadata和*.data文件,metadata文件记录的是DiskRowSet的元信息,主要包括哪些block和block在data中的位置,上图为block和DiskRowSet中各部分的映射关系,在写磁盘时是通过container来写入,每个container可以写很大的一块连续的磁盘空间,用于给某一个CFile写数据,当一个CFile写完后会将container归还给BlockManager,这时container就可以用于下一个CFile写数据了,当BlockManager中没有container可用时会创建一个新的container给新的CFile使用。

  • 对应新建block先看看是否有container可用,若没有,目前默认的是在所在的配置中的data_dir中随机选取一个dir建一个新的metadata和data文件。先写data,block落盘后再写metadata

MVCC:
  • 表的主键排序,受益于MVCC(Multi-VersionConcurrency Control) 多版本并发控制,一旦数据写入到 MemRowSet,后续的reader能立马查询到
Compaction:
  • minor compaction:
    多个deltafile进行合并。默认是1000个deltafile进行合并一次

  • major compaction:
    deltafile文件的大小和basedata的文件的比例为0.1的时候,会进行合并操作

Kudu 读写流程原理

Teblet 架构图

Teblet 架构图详解

​ Kudu中的Tablet是负责Table表的一部分的读写工作,Tablet是有多个或一个Rowset组成的,其中一个Rowset处于内存中,叫做MemRowSet,MemRowSet主要是负责处理新的数据写入请求。DiskRowSet是MemRowSet达到1G刷新一次或者是时间超过2分钟后刷新到磁盘后生成的,实际底层存储是Base Data(一个CFile文件)、多个Delta file(Undo data、Redo data组成)的和Delta MemStore,其中位于磁盘中的Base data、Undo data、Redo data是不可修改的,Delta Memstore达到一定程度后会刷新到磁盘中的生成Redo data,其中kudu后台有一个类似HBase的compaction线程策略进行合并处理:

  • Minor Compaction:多个DeltaFile进行合并生成一个大的DeltaFile。默认是1000个DeltaFile进行合并一次

  • Major Compaction:DeltaFile文件的大小和Base data的文件的比例为0.1的时候,会进行合并操作,生成Undo data

  • 将多个DiskRowSet进行合并,减少DiskRowSet的数量

Base Data:是MemRowSet flush下来的数据,按照列存储,按照主键有序

Undo Data:是BaseData之前的数据历史数据

Redo Data:是BaseData之后的mutation记录,可以获得较新的数据

Delta Memstore:用于在内存中存储更新为磁盘中数据的mutation记录,先写到内存中,然后写满后flush到磁盘,形成DeltaFile。

读写流程

当创建Kudu客户端时,其会从主master上获取tablet位置信息,然后直接与服务于该tablet的服务器进行交谈。为了优化读取和写入路径,客户端将保留该信息的本地缓存,以防止他们在每个请求时需要查询主机的tablet位置信息。随着时间的推移,客户端的缓存可能会变得过时,并且当写入被发送到不是领导者的tablet服务器时,则将被拒绝。然后,客户端将通过查询主服务器发现新领导者的位置来更新其缓存。

读流程
  1. 客户端连接TMaster获取表的相关信息,包括分区信息,表中所有tablet的信息
  2. 客户端找到需要读取的数据的tablet所在的TServer,Kudu接受读请求,并记录timestamp信息,如果没有显式指定,那么表示使用当前时间
  3. 从内存中读取数据,也就是MemRowSet和DeltaRowSet中读取数据,根据timestamp来找到对应的mutation链表
  4. 从磁盘中读取数据,从metadata文件中使用boom filter快速模糊的判断所有候选RowSet是否含有此key。然后从DiskRowSet中读取数据,实际是根据B+树,判断key在那些DiskRowSet的range范围内,然后从metadata文件中,获取index来判断rowId在Data中的偏移,或者是利用validex来判断数据的偏移(只有一个key),根据读操作中包含的timestamp信息判断是否需要将base data进行回滚操作从而获取数据
写流程
  1. 客户端连接TMaster获取表的相关信息,包括分区信息,表中所有tablet的信息

  2. 客户端找到负责处理读写请求的tablet所负责维护的TServer。Kudu接受客户端的请求,检查请求是否符合要求(表结构)

  3. Kudu在Tablet中的所有rowset(memrowset,diskrowset)中进行查找(如何查找),看是否存在与待插入数据相同主键的数据,如果存在就返回错误,否则继续

  4. 写入操作先被提交到tablet的预写日志(WAL),并根据Raft一致性算法取得追随节点的同意,然后才会被添加到其中一个tablet的内存中,插入会被添加到tablet的MemRowSet中。为了在MemRowSet中支持多版本并发控制(MVCC),对最近插入的行(即尚未刷新到磁盘的新的行)的更新和删除操作将被追加到MemRowSet中的原始行之后以生成REDO记录的列表

  5. Kudu在MemRowSet中写入一行新数据,在MemRowset(1G或者是120s)数据达到一定大小时,MemRowSet将数据落盘,并生成一个DiskRowSet用于持久化数据,还生成一个MemRowSet继续接收新数据的请求

    补充:

    在步骤3中我们说Kudu在插入和更行操作时首先要确定这一行是保存在当前的MemRowSet中,还是在某个DiskRowSet中。就update来说,Kudu会寻找第一个包含此行的DiskRowSet,在此过程中会使用布隆过滤器(bloom filter)来减少I/O的操作。当确认正确的目的DiskRowSet之后,更新后的列会保存在这个DiskRowSet特有的DeltaMemStore中,随着时间的推移,这个DeltaMemStore可能会变大,并且被刷新为DeltaRoset中的一个RedoDeltaFile。

    我们对以上部分概念重新详细解释:

    1、基线数据(base data)的块文件,表中每一个列都对应一个块,以单个文件的形式存储

    2、RedoDeltaFile,每次DeltaMemStore做刷新操作时都会生成一个RedoDeltaFile,分开保存。

    当一个客户端发起对某行的一次get操作时,Kudu需要读取基线数据文件中的数据,然后读取RedoDeltaFile中更新操作的记录并执行这些操作,得到一行最新的版本。RedoDeltaFile越多,读取操作就越慢,为了避免此情况的影响,Kudu会执行major REDO delta compaction的操作,为了减少随后对这些文件的读取以提高性能,这个操作会对基线数据文件执行 存储在RedoDeltaFile中的更新操作。

    虽然读取所有RedoDeltaFile来执行读取操作是有成本的,但合并和重写所有的数据也是有成本的,为了确保最佳的性能,Kudu不会将所有的RedoDeltaFile合并到现有的数据文件中。如果只有几行数据需要更新,重写整个数据文件来合并这些行,将会在系统中产生大量的I/O操作,而且最后也只能微小地提高操的作性能。所以,当执行compaction时,Kudu会生成以下3组数据:

    1、更新过的基线数据:当某个特定的列需要进行大量的更行操做时,Kudu会把基线数据和这些更新合并起来,重新生成一个新的基线数据,通过这种方式来执行更新。

    2、UNDO增量(UNDO deltas):在对基线数据执行增量修改时,Kudu会跟踪所有的更新操作,并且把它们保存为UNDO增量文件,这个文件被Kudu用来实现获取过去“某个时间点”的值的功能。 默认情况下,Kudu将这个文件包村15分钟,因此,可以在Kudu中查找15分钟以内的某个列的确切内容,15分钟以后,在下一次compaction迭代中,那些超过15分钟的数据会过期,该文件会被删除。

    3、未合并的REDO增量(unmerged REDO deltas):正如前面所说,并不是所有的增量修改都会被执行,当这种修改太小而不能为合并带来好处时(Kudu是如何判断的 ?),它会被保留等待进行后续的compaction,未合并的REDO增量文件包含所有没有被执行到数据文件中的更新。

    由于重新建一行需要读取的数据和文件更少,对Kudu做完compaction之后,后续的读操作性能得到提升,对磁盘的访问也减少了。

Kudu对原有数据的更新
  1. 客户端连接TMaster获取表的相关信息,包括分区信息,表中所有tablet的信息
  2. Kudu接受请求,检查请求是否符合要求
  3. 因为待更新数数据可能位于memrowset中,也可能已经flush到磁盘上,形成diskrowset。因 此根据待更新数据所处位置不同,kudu有不同的做法
    • 当待更新数据位于memrowset时,找到待更新数据所在行,然后将更新操作记录在所在行中一个mutation链表中;在memrowset将数据落盘时,Kudu会将更新合并到base data,并生成UNDO records用于查看历史版本的数据,REDO records实际上也是以DeltaFile的形式存放
    • 当待更新数据位于DiskRowset时,找到待更新数据所在的DiskRowset,每个DiskRowset都会在内存中设置一个DeltaMemStore,将更新操作记录在DeltaMemStore中,在DeltaMemStore达到一定大小时,flush在磁盘,形成DeltaFile中。

实际上Kudu提交更新时会使用Raft协议将更新同步到其他replica上去,当然如果在memrowset和diskrowset中都没有找到这条数据,那么返回错误给客户端;另外当DiskRowset中的deltafile太多时,Kudu会采用一定的策略对一组deltafile进行合并。

补充:

wal日志的作用是如果我们在做真正的操作之前,先将这件事记录下来,持久化到可靠存储中(因为日志一般很小,并且是顺序写,效率很高),然后再去执行真正的操作。这样执行真正操作的时候也就不需要等待执行结果flush到磁盘再执行下一步,因为无论在哪一步出错,我们都能够根据备忘录重做一遍,得到正确的结果。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值