- 设计思路
- 背景:淘宝店收藏夹数据量很大,但短时间内的增量相对不大
- 思路
- 采用单台 Update Server 来处理增量数据,之前的数据不变称为基线数据
- 所有的写操作集中在单台 Update Server 上,因此避免了分布式事务,高效地实现了跨行事务
- Update Server 上的修改增量定期分发到基线数据服务器中
- 查询时,同时查询基线数据和 Update Server 中的数据,进行合并
- 架构设计
- 双机房部署
- 升级方案:停备集群流量 -> 升级备集群版本 -> 主备切换 -> 升级旧住集群版本
- Root Server
- 保证集群内只有一个 Update Server Master,通过 Lease 机制保证
- 存储了子表划分及每个子表所在 Chunk Server 位置信息
- Root Server 检测到 Chunk Server 发生故障时,触发对这台 Chunk Server 上的子表的增加备份操作
- Root Server 定期进行负载均衡,将子表从负载高的机器迁移到负责低的机器
- Merge Server:SQL 计算层
- 本身无状态
- 缓存子表分布信息
- 按需对 SQL 请求拆分到对应的 Chunk Server 并聚合结果
- 转发写请求到 Update Server
- Chunk Server:存储节点
- 数据按子表组织,每个子表约为 256MB,每个子表包含一个或多个 SSTable
- SSTable 内 key 有序,可以进行二分查找
- SSTable 支持 Block Cache 和 Row Cache
- OceanBase 定期触发合并或数据分发操作,在这个过程中,ChunkServer 从 UpdateServer 取一段时间之前的更新数据
- Update Server 唯一的写入模块
- 内存表的数据量超过一定值时,生成快照存储到 SSD,组织方式类似 SSTable,数据稀疏
- 主 UpdateServer 更新内存表前先将操作日志同步到备 UpdateServer
- 重启后,先加载快照,然后重复操作日志
- 定期合并 & 数据分发:将 UpdateServer 中的增量更新分发到 ChunkServer,流程如下
- UpdateServer 冻结当前内存活跃表 (Active MemTable),并开启新的内存活跃表,后续写操作写入新的内存活跃表
- UpdateServer 通知 RootServer 数据版本发送了变化,之后 RootServer 通过心跳通知 ChunkServer
- 每台 ChunkServer 启动定期合并或数据分发操作,从 UpdateServer 获取每个子表对应的更新操作
- 合并期间不停读:如果合并没完成,则读旧子表 + 冻结内存表,否则读新子表
- 定期合并 & 数据分发的区别
- 定期合并:需要将本地 SSTable 中的基线数据与 UpdateServer 中冻结内存表中的增量更新数据执行一次多路归并,融合的数据写入到新的 SSTable
- 数据分发:将 UpdateServer 中冻结内存表中的增量更新缓存到本地
- 数据结构
- 每个表按主键组成一颗分布式 B+ 数,每个叶子节点包含一个左开右闭的主键范围内的数据
- 每个叶子节点为一个子表(tablet),包含一个或多个 SSTable
- 每个 SSTable 内部按主键顺序划分为多个 block,并建立块索引(block index)
- 每个 block 大小通常在 4-64KB
- 在块内建行索引(row index)
- block 是数据压缩的单元
- 叶子节点可能合并或者分裂
- 通常情况下每个叶子节点有 2-3 个副本
- 叶子节点是负载均衡和任务调度的单元
- 叶子结点支持 bloom filter
- 增量数据为一颗内存中的 B+ 树,称为 MemTable,到达一定大小后会被冻结,并开启新的 MemTable 接受写操作
- 冻结的 MemTable 将以 SSTable 的形式存储到 SSD 中持久化
- 每个 SSTable 内部按主键范围有序划分为多个块
- 每个块大小通常为 4-8K
- 块内建行索引
- 一般不压缩
- 示意图
- 每个表按主键组成一颗分布式 B+ 数,每个叶子节点包含一个左开右闭的主键范围内的数据
- 读写事务
- 只读事务:MergeServer 解析 SQL 生成执行计划 -> MergeServer 将请求转发到 ChunkServer -> MergeServer 合并查询结果或处理链表、嵌套查询 -> MergeServer 向 Client 返回结果
- 读写事务::MergeServer 解析 SQL 生成执行计划 -> MergeServer 从 ChunkServer 获取基线数据,将物理执行计划和基线数据一起发给 UpdateServer -> UpdateServer 执行读写事务 -> UpdateServer 向 MergeServer 返回事务执行结果 -> MergeServer 向 Client 返回结果
- 数据校验措施
- 数据存储校验:每个存储记录保存 64-bit CRC,数据访问时做比对
- 数据传输校验:记录传输时同时传输 64-bit CRC,数据接收后作比对
- 数据镜像校验
- UpdateServer 为 MemTable 生成一个校验码,MemTable 每次更新时同步更新校验码,并记录在操作日志中
- 备 UpdateServer 重放操作日志时比对 MemTable 计算出的校验码和操作日志中的校验码
- 数据副本校验:ChunkServer 定期合并 MemTable 生成新 SSTable 时,为每个子表生成一个校验码,随新子表汇报给 RootServer,由 RootServer 比对不同副本的校验码