分布式存储系统Kudu(一)、核心原理

目录

简介

架构

存储机制

读写原理

工作模式

读流程

写流程

更新删除流程


简介

在前面的篇章中我们介绍了分布式文件系统HDFS 以及列式存储HBase,HDFS提供了可以横向扩展的存储引擎,适合离线分析场景,不适合于随机读写。HBase适合于随机读写,但由于Scan消耗性能,因此不适合于离线分析场景。因此既可以实现数据的快速插入与实时更新,又能实现对数据的快速分析的Kudu出现了。

Apache Kudu 是由Cloudera 开源的存储引擎,可以同时提供低延迟的随机读写和高效的数据分析能力。它是一个融合 HDFS 和 HBase 的功能的新组件,具备介于两者之间的新存储组件。Kudu 支持水平扩展,并且与 Cloudera Impala 和 Apache Spark 等当前流行的大数据查询和分析工具结合紧密。Kudu的定位不是取代HBase或HDFS,而是牺牲了写性能,提高了批量读的性能,使其能够实现快速在线分析,在功能上介于HBase和HDFS之间。

官方文档https://kudu.apache.org/docs/

架构

Kudu也是主从结构,由多个Master节点互为主备负责接收客户端请求以及元数据管理,从节点负责处理数据读写和存储。上图显示的就是一个三台Master节点以及4个Tablet server节点,每个tablet server节点维护着n个tablet,其中每个tablet都有三个副本,每个tablet的三个副本中有一个作为Leader,两个作为Follower。

  • Table:表具有schema和全局有序的primary key。表被分成很多tablet(段)。
  • Tablet:tablet 是 table 连续的segment(段),与其它数据存储引擎(Hbase中的的Region)或关系型数据库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向客户端提供服务。对于给定的tablet,一个tablet server充当 leader,其他tablet server充当该tablet的follower副本(通过Raft机制)。leade负责处理写请求,leader和followers同时处理读请求。
  • Master Server:维护所有的tablets、tablet servers、catalog tables(目录表)等元数据信息。
    • 同时只能有一个活跃的master(也就是 leader)。如果当前的leader消失,则会通过Raft机制选举出一个新的master。
    • master还负责协调客户端的metadata operations(元数据操作)。如:当创建新表时,客户端内部将请求发送给master。 master将新表的元数据写入catalog table(目录表),并协调在tablet server上创建tablet的过程。
    • 所有master的元数据都存储在一个tablet中,可以复制到所有其他候选的master。tablet server以设定的间隔向master发出心跳(默认值为每秒一次)。
  • Catalog Table(目录表):catalog table存储Kudu 的元数据,负责存储Table和Tablet的元数据信息,只能通过客户端 API进行访问。包含下面的内容:
    • Tables元数据:table schema(表结构),location(位置),state(状态);
    • Tablets元数据:tablet 列表,每个 tablet 的副本所在的tablet server,tablet的当前状态以及start_key和end_key。
  • Raft机制:Kudu使用Raft算法 保证 tablet 和 master 数据的容错性和一致性。通过 Raft协议,tablet 的多个副本选举出 leader,它负责接受请求和复制数据写入到其他follower副本。一旦写入的数据在大多数副本中持久化后,就会向客户确认。给定的一组N副本(通常为 3 或 5 个)能够接受最多(N - 1)/2 错误的副本的写入。

存储机制

Kudu并没有采用HDFS作为底层数据文件存储,而是自行开发了一套可基于 Table/Tablet/Replica 视图级别的底层存储系统。
设计目标

  • 可提供快速的列式查询
  • 可支持快速的随机更新
  • 可提供更为稳定的查询性能保障 

  1. 每个Table包含多个Tablet,其中Tablet的数量是根据建表时指定的分区方式:hash或者是range进行设置的。
  2. 每个Tablet中包含MetaData信息和多个RowSet信息,其中MetaData信息是block及block在data中的位置。
  3. 每个RowSet包含一个MemRowSet和多个DiskRowSet,其中MemRowSet用于存储新数据的insert和对已在MemRowSet中的数据update,写满后按照一定策略进行flush刷写到磁盘(若干个DiskRowSet)中,默认是1G或者120秒进行刷写。
  4. 每个DiskRowSet用于对旧数据的更新和删除,比如说已持久化到磁盘的数据的更新操作。每个DiskRowSet占用32MB,后台定期对DiskRowSet进行合并操作,删除历史数据和没有的数据,减少查询过程中的IO开销。
  5. 每个DiskRowSet包含BloomFilter、Ad_hoc Index、UndoFile、RedoFile、BaseData、DeltaMem。
    1. BloomFile:根据DiskRowSet中key生成一个bloom filter,用于快速模糊的定位某一个key是否在DiskRowSet中。(详细请参考:布隆过滤器(Bloom Filter)
    2. Ad_hoc Index:主键的索引,用于定位主键在DiskRowSet的偏移位置。
    3. BaseData:是MemRowSet flush之后的数据,按照列存储,按照主键有序。
    4. UndoFile:是BaseData之前时间(上次flush之前)的数据历史数据,可以获得历史数据,类似mysql中的回滚日志。
    5. RedoFile:是BaseData之后时间(上次flush之后)的更新记录,可以获得较新的数据,类似mysql中的重做日志。
    6. DeltaMem:在内存中存储DiskRowSet中数据的更新,写满后flush到磁盘,形成deltafile。

这里有两个在内存中处理的数据集,区别如下:

MemRowSet:存储新增的数据,对该内存数据集中还未flush的数据的更新;

DeltaMem:对已flush到磁盘内的数据的更新;

MemRowSet、DeltaMem按照行存储的,并且以B+树 进行排序,而DiskRowSet 按列进行存储以二叉平衡树进行排序,当进行flush刷写或DiskRowSet Merge Compaction时会重新生成新的树。DiskRowSet在磁盘上具体存储为一个个的CFile文件,但上面提到的DiskRowSet 包含的六个部分并不是存在同一个CFile中,而是独立在多个CFile内,每一部分都会形成单独的CFile。然而事实上在磁盘中我们并不能看到CFile,而是一个个的.data和.metadata文件。

它们的关系如下:

.metadata文件记录的是一个DiskRowSet中每个block对应CFile的位置以及映射关系,写磁盘通过container处理,Container将CFile合并到.data文件中,因此对于一个DiskRowSet的正常读写,.metadata文件和.data文件缺一不可。 

读写原理

工作模式

Kudu的工作模式如下图,有些在上面的内容中已经介绍了,这里简单标注一下: 

  1. 每个kudu table按照hash或range分区为多个tablet;
  2. 每个tablet中包含一个MemRowSet以及多个DiskRowSet;
  3. 每个DiskRowSet包含BaseData以及DeltaStores;
  4. DeltaStores由多个DeltaFile和一个DeltaMemStore组成;
  5. insert请求的新增数据以及对MemRowSet中数据的update操作 会先进入到MemRowSet;
  6. 当触发flush条件时将新增数据真正的持久化到磁盘的DiskRowSet内;
  7. 对老数据的update和delete操作是提交到内存中的DeltaMemStore;
  8. 当触发flush条件时会将更新和删除操作持久化到磁盘DIskRowSet中的DeltaFile内,此时老数据还在BaseData内(逻辑删除),新数据已在DeltaFile内;
  9. 当触发compaction条件时,将DeltaFile和BaseData进行合并,DiskRowSet进行合并,此时老数据才真正的从磁盘内消失掉(物理删除),只留下更新后的数据记录;

读流程

  1. 客户端向Kudu Master请求tablet所在位置;
  2. Kudu Master返回tablet所在位置;
  3. 为了优化读取和写入,客户端将元数据进行缓存;
  4. 根据主键范围过滤目标tablet,请求Tablet Follower;
  5. 根据主键过滤scan范围,定位DataRowSets;
  6. 加载BaseData,并与DeltaStores合并,得到老数据的最新结果;
  7. 拼接第6步骤得到的老数据与MemRowSet数据 得到所需数据;
  8. 将数据返回给客户端;

写流程

  1. 客户端向Kudu Master请求tablet所在位置;
  2. Kudu Master返回tablet所在位置;
  3. 为了优化读取和写入,客户端将元数据进行缓存;
  4. 根据分区策略,路由到对应Tablet,请求Tablet Leader;
  5. 根据RowSet记录的主键范围过滤掉不包含新增数据主键的RowSet;
  6. 根据RowSet 布隆过滤器再进行一次过滤,过滤掉不包含新数据主键的RowSet;
  7. 查询RowSet中的B树索引判断是否命中新数据主键,若命中则报错主键冲突,否则新数据写入MemRowSet;
  8. 返回响应给客户端;

更新删除流程

 更新删除流程与写入流程类似,区别就是最后判断是否存在主键时候的操作,若存在才能更新,不存在才能插入新数据。

  1. 客户端向Kudu Master请求tablet所在位置;
  2. Kudu Master返回tablet所在位置;
  3. 为了优化读取和写入,客户端将元数据进行缓存;
  4. 根据分区策略,路由到对应Tablet,请求Tablet Leader;
  5. 根据RowSet记录的主键范围过滤掉不包含修改的数据主键的RowSet;
  6. 根据RowSet 布隆过滤器再进行一次过滤,过滤掉不包含修改的数据主键的RowSet;
  7. 查询RowSet中的B树索引判断是否命中修改的数据主键,若命中则修改至DeltaStores,否则报错数据不存在;
  8. 返回响应给客户端;

 

希望本文对你有帮助,请点个赞鼓励一下作者吧~ 谢谢!

评论 1 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:我行我“速” 设计师:Amelia_0503 返回首页

打赏作者

王义凯_Rick

遇见即是缘,路过就给个评论吧~

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值