TiFlow README
本项目为 TiFlow(原 TiCDC)增加 Key-Range 粒度负载均衡的能力,以提高资源利用率、满足单表大速率写入、纯 Key-Value 等业务场景下 CDC 的需要。
TiFlow 目前以 table 为粒度进行任务调度和负载均衡。这个设计在以下场景中存在限制:
因此,为了满足上述三个业务场景的需要,本项目为 TiFlow 增加 Key-Range 粒度的任务调度和负载均衡能力,帮助 TiDB、TiKV 进一步完善生态。
Table 之下再进行数据分片,Key Range 是一个显而易见的粒度。事实上 TiDB 本身就是按照 Key Range 进行数据分片,因此 TiFlow 在这个粒度仍然可以很好的与 TiDB / TiKV 配合。
Region 本质上是 TiKV 按照负载均衡的需要划分 Key Range。TiFlow 不直接采用 Region 作为粒度,原因包括:
- Region 的划分同时考虑了存储容量、读写负载、高可用等因素,而 TiFlow 主要考虑写负载。因此按照 Region 的划分很可能不适合 TiFlow
- Region 不稳定,如果采用 Region 与 task 对应,Region merge 会引起 task 失效、Region split 则导致 key range 出现空洞,将大大增加系统的复杂度 但同时需要注意的是,因为 TiFlow 与 TiKV 之间的数据同步以 Region 为单位,获取一个 Region 的部分数据在现有实现下有资源浪费。因此 TiFlow 在进行数据切分的时候,应当尽可能在 Region 边界
基于 1 和 2,调度模块应当统计各个 Region 的变更数据量,并根据资源数量,在 Region 边界均衡划分 同时,在每个调度周期,重新获取 Region 分布,结合变更数据量统计调整调度 当出现 Region 变化时:
- Region Split:不影响任务调度
- Region Merge:如果导致捕获 Region 的部分数据,在适当的时机调整任务调度 此外,由于存在 table 粒度的 Metrics,因此 Key Range 的划分应当考虑在 table 边界(可能与 Region 边界冲突。可以暂时优先满足 table 边界,以降低实现复杂度)
目前 TiFlow 在 MySQL sink 上不拆分单表事务,保证单表事务的原子性。调度粒度变更为 Key Range 之后,这点保证将被破坏,上游的一个事务可能被拆分为多个事务,并破坏下游的 Snapshot Isolation。解决方案如下:
增加 TiDB sink。TiDB sink 将直接在 mvcc 层写入数据,并复制上游数据的 start_ts 和 commit_ts,从而在上下游之间产生完全相同的 snapshot。同时,resolved_ts 也将同步给下游 TiDB。当读请求的 start_ts 小于 resolved_ts,就可以获得与上游 snapshot 一致的数据。 TiDB sink 还有以下优点:
- 直接写入 TiKV,在同步性能上更优
- 保持跨表事务原子性
- 实际上是一个 TiKV sink + DDL sink。TiKV sink 可用于满足 TiKV CDC 的场景
目前没有比较好的解决方案,需要用户在同步效率与事务原子性之间权衡。
没有变化。
- 根据调度算法生成 Key Range Task。一个 Changefeed 的 Task 数量与 Capture 数量相等,(参考 Region 分布)平均分配到所有 Capture
- 根据 Key Range 收集并汇总 Changefeed 粒度的 Metrics
- 接收 Key Range Task 并拉起 Processor
- 处理 Key Range Task
- 一个 Processor 处理一个 Task,即
一个Changefeed
在一个Capture
上的一个或多个Key Range
- processor.addTable 需要增加相应的 addKeySpan 版本
- processor.handlePosition 处理 KeySpans 的 position
暂无
bufferSink 以 tableID 作为缓存粒度,需要修改