Preface

最近头条发布了关于 Bytable 的文章: https://juejin.im/post/5ee376fe518825434566d1de , 特地学习下

Bytable

有三种角色: master(控制平面) 、placement driver(Placement Driver) 、tabletServer(TabletServer)

feature:

拆分了 tablet 的 raft 的membership 和 Leader Election 到master, 降低心跳的开销 (tablet server 只需要和master进行通信, 不需要为每个 tablet group进行 tablet server 之间的心跳, 后者随着tablet的增长而增长), leader election 放在master 可以自定义更多的策略

自研了一套WAL 存储引擎 避免同时写入 复制日志和引擎日志 导致的 HDD 盘磁头摇摆, 进而写入性能降低的问题, 按照文章的说法: 不进行 Compaction 时也可以打满 HDD 盘的写入带宽

问题:

  • Split 和 Merge 使用硬链 降低不可用时间, 但是用了硬链, 文件还是一个, 应该还是存在将分裂的tablet 传给其他 tabletServer, 除非分裂还在本地的taletServer

大概能够明白, 使用硬链避免在传输sst文件的时候,文件被compaction流程删除. (需要确认下)

  • 手工生成 BloomFilter 优化点读, 适配table模型 (为什么bloom filter不能适配 table模型?)

特色: O(1) 复杂度的在线写入

因为我们使用了 Raft 作为副本复制协议,而 Raft 的 Apply 流程是串行的,当出现写入热点时需要通过热点 Tablet 分裂来扩展性能。因为我们的分裂合并操作相对比较重,热点分裂的决策并不适合过于实时和敏感,为了扩展单个 Tablet 的写入性能,我们实现了一种新型的 RocksDB MemTable,写入时仅写入队列中实现了 O(1) 复杂度的在线写入,靠后台线程池将数据并发的写入实际的 SkipList 中,在读取的时候使用 ReadIndex 的机制进行等待。将单线程的最大承载能力扩展到单机的最大承载能力。

慢节点反压 的没有细讲, 看上去 是通过 限速实现,但是这里存在着 如何动态限速的问题…. 不然就是写死一个值

Bytable 2.0

存在的问题:

  1. 三副本相对 分布式文件多消耗了 cpu
  2. 三副本独立compaction 导致 多消耗了 两倍 cpu
  3. 分裂合并的 长尾延迟
  4. 更方便的和hadaoop打通, 备份、导入和加载

相应的解决策略:

  1. ByteJournal 管理复制日志 (提供总共 5 副本写入 2 副本成功即可提交,但需要 4 副本 Recover 的高级特性, 有类似 Paxos 的日志乱序复制和提交的特性以尽可能的降低延时)
  2. ByteStore 存储引擎文件

Bytable 2.0 有四个角色: 数据读写层(TabletServer)、全局管理层(GlobalMaster),计算调度层(GroupMaster)和数据调度层(PlacementDriver)

feature:

  1. 将tablet分布信息存储在 MetaTable, 每张表一个 metaTable 存储在 TabletServer, 自治模型, 信息隔离. Bytable1.0 存储在Master
  2. replication group 存放更多的 tablet, 避免tablet过多导致 replication group 太多
  3. 引入 GlocalMaster 和 GroupMaster 替换了 Bytable1.0, GlobalMaster 负责记录所有 Table 和 ReplicationGroup 的元信息, GroupMaster 负责同步GlobalMaster信息后 本地保存, 对自己Region内的TabletServer进行探活和replica分配

相对HBase, 支持了跨 Region 的 Quorum 数据复制,达到了全球一致的效果. 好处2 不是很能理解, 需要在学习

查询上, 原文写的有些拗口, 应该是 Client 先从 对应的MetaTable中获取目标Tablet的ReplicationGroupId, 在从GroupMaster中获取各个Replica的位置, 然后进行读写. 因为MetaTable也是存储在Tablet, 因此也需要请求GroupMaster获取MetaTable对应的Replica信息.

问题:

3.2.1中 在这种设计下迁移不再是将一个 Tablet 从一个 TabletServer 迁往另外一个 TabletServer,而是从一个 ReplicationGroup 将这个 Tablet 的对应数据导入另外一个 ReplicationGroup 有差异吗? 迁移中场景不能通过 数据导入吗?

写入流程上, leader replica 会先写WAL到 journal log, 然后在写入 memtable. follower replica 从 journal log中 读取wal并写入memTable(是否多余呢?), 注意一点, 这里是 leader replica 定期执行 checkpoint 和 compaction, 并将sst写入到 byteStore, follower 并不需要重复操作, 避免了CPU损耗.

读取流程上, leader/follower 都是将 ByteStore sst + memtable 合并归还给用户. follower replica 支持 指定版本读 和 ReadIndex 线性一致性读取(从leader拿取readindex, 等待readindex本地apply之后在读取)

GlobalMaster 是个运维接口, 比如 表、cf 的创建和删除. 存储 表、cf、replicaGroup 的元信息.

GroupMaster 负责 tablet 保活 以及同步到的 GlobalMaster 的元信息调度.

未来规划中, 基于yarn的离线compaction、分析性列式引擎、多模数据库、新型分布式事务机制(目前Percolator)

问题:

  • RootTable 使 MetaTable 其可分裂 ?

  • SST 文件 Range 抽取的方式 ?

  • 慢节点反压的细节

  • 为什么bloom filter不能适配 table模型?