3 分钟搞懂 Apache SeaTunnel CDC 数据同步

CDC 简介
CDC(Change Data Capture)是一种用于跟踪数据库库变更事件(插入、更新、删除)中的行级更改,并将事件以发生的顺序通知到其他系统处理。在容灾场景下,CDC 主要实现的是主备间的数据同步,即从主数据库到备数据库的数据实时同步。
source ----------> CDC ----------> sink
Apache SeaTunne CDC
SeaTunnel CDC 的数据同步分为两种:
快照读:读取表的历史数据
增量跟踪:读取表的增量日志更改数据
2.1 无锁快照同步
无锁快照同步阶段,为什么强调无锁,是因为现有的 CDC 平台在进行历史数据的同步时可能会进行锁表操作,例如 Debezium。快照读阶段就是对数据库的历史数据库进行同步的过程,其基本概述流程如下:
split 划分:splitEnumerator(split 分发器)按照指定的字段(例如表 id 或唯一键)和步长将表数据划分为多个分片 split。并行处理:每个 split 通过路由算法分配给不同的 reader 进行并行读取,一个 reader 会占用一个连接。事件反馈:每个 reader 完成 split 读取后会向 splitEnumerator 报告进度。splitEnumerator 会发送给 reader 一个分片,分片的元数据信息如下:
reader 收到 split 信息后会生成相关的 sql 语句,在此之前会记录当前 split 对应到数据库日志 log 的开始位置,等处理完当前 split 后上报 report 给 splitEnumerator,report 内容如下:
2.2 增量同步
增量同步阶段是基于上述快照读取阶段后,在源数据库发生变化时,实时将变更的数据同步到备数据库,不同的是,此阶段监听的是数据库的 log 日志,例如 mysql 的 bin log。增量跟踪通常是单线程处理,这样可以避免重复拉取 bin log,减轻对数据库的压力,因此该阶段只有一个 reader 工作,只占用一个连接。
增量同步会合成快照阶段所有 split、table,因此只会存在一个 split,增量同步阶段的 split 信息如下:
其中 CompletedSnapshotSplitInfo 的具体字段如下:
增量阶段的 split 包含了快照阶段所有 split 的 watermark,会去从其中选出一个合适的位置进行增量同步,这个合适位置就是最小的 watermark。
三、Exactly-once 无论是快照读还是增量读,同步的过程中数据库可能也在经历变化,如何保证 exactly-once?
3.1 快照读阶段
在快照读阶段,例如某个 split 在同步的过程中,这段 split 中的数据发生了变换,例如下图操作,插入一条 k3,更新 k2,删除 k1,如果在读的过程中不做任务标识,那么这部分的更新信息就会丢失,seatunnel 的做法是:
在 split 读取之前首先去数据库查一下 bin log 位置:low watermark
读取 split{start, end}数据
再记录一下高水位 high watermark
如果 high = low 说明在读取该 split 期间,该 split 的数据没有发生变化;如果(high - low) > 0,说明在处理的过程中发生了数据变化,会进行如下操作:①将读到的 split 数据在内存中建立内存表缓存;②将 low watermark~high watermark 的变更;③按顺序、主键重放操作到内存表
报告 report high watermark
增量阶段
在增量阶段开始之前首先会对上一个步骤的所有 split 做校验,因为在 split 和 split 之间的间隙也有可能出现数据更新,例如在 split1 和 split2 之间插入了若干条记录,在快照阶段就会遗漏掉,对于这种 split 之间的数据回捞,seatunnel 的做法是:
从所有的 split 的 report 中找到最小的 watermark,作为 start watermark,开始读取 log。每读一条 log 都去 completedSnapshotSplitInfos 中找该条数据是否在某个 split 被处理过了,如果没有被处理过,说明是 split 间隙数据,应该被重新修正。当表过滤完后,可以从 completedSnapshotSplitInfos 中删除,继续处理剩余的表。直到所有的 split 都校验结束,就进入到了完全的增量阶段。
断点续传
如果做到暂停恢复?分布式快照算法(Chandy-Lamport):
假设系统中包含了两个进程 p1 和 p2,p1 进程状态包含三个变量 X1 Y1 Z1,p2 包含了三个变量 X2 Y2 Z2,初始状态如下:
此时由 p1 发起全局 snapshot 记录,p1 先记录本身的进程状态,然后向 p2 发送 marker 信息。在 marker 信息到达 p2 之前,p2 向 p1 发送 message M。
p2 收到 p1 发送来的 marker 信息后,记录自己的状态,然后 p1 收到 p2 之前发送来的 message M,由于 p1 已经做了 local snapshot 了,所以 p1 只需要记录 M。,所以最终的 snapshot 如下:
在 SeaTunnel CDC 的过程中,marker 同发送给所有的 reader、splitEnumerator、writer 等节点都会保存自己的内存状态。
版权声明: 本文为 InfoQ 作者【白鲸开源】的原创文章。
原文链接:【http://xie.infoq.cn/article/dda96819740ae3d562b1d717a】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论