快照同步
快照同步部分, 主要是同步表的存量数据;增量同步算法是无锁算法; 将存量数据和读取时的biglog数据做合并实现, 下面我们通过代码来解释快照读取过程
chunk划分
将数据更具主键和cdc配置中的scan.snapshot.fetch.size配置将数据划分为一个小的chunk, 将每一个chunk给sourceReader读取处理;
如上图, 更具flink sql中的主键列, 查收数据库中的最大最小值, 然后用查出数据总数, 然后每一个chunk 就由主键的开始值, 主键的结束值组成;
如上图所示, 每一个split(chunk划分之后, sourceReader所分配到的就是split)由主键, splitstart(即主键开始时间), splitEnd(主键结束时间)组成
快照处理
快照处理分为两个部分第一个部分直接根据split的主键范围从数据库读取数据; 在读取数据前后会分别读取当前的binlog日志位置, 然后会将数据库读取出来的数据和biglog中在相同主键范围之内的数据进行合并
读取完成之后本次的数据变成了一下结构
lowerwaterwark (特殊的数据)
|
快照数据
|
endWaterwark(特殊数据, 表示快照数据结束, binlog数据开始)
|
binlog日志数据
读取完快照数据之后会进行binlog数据和快照数据的合并
根据binlog数据的操作类型进行合并快照数据
待所有chunk都读取完成之后快照读取阶段就完成了
binlog同步
所有已完成的快照split中, 找到最小的offset, 从该offset开始读取binlog
如上图所示, 对于从binlog中读取的每一条记录, 都会遍历所有已完成的快照分片, 如果改记录属于分片的处理范围(例如主键在分片的start和end之前)并且该记录的binlog offset 在分片的highWatermark之后, 那么该记录会提交到下游处理;
总结
通过上面的分析整个逻辑是完整自洽的;
对于每一个分片, 在读取快照前后分别读取当前binlog的offset(即lowerWatermark 和 highWatermark), 在快照读取完成之后读取lowerWatermark和highWatermark之间的记录, 将属于该分片处理范围内的记录和快照数据合并, 这样完成了快照读取;
当所有分片都读取完成之后, 从所有分片中最小的offset开始读取binlog(所有分片都有lowerWatermark 和 hightWatermark, 这里就是取最小的lowerWatermark), 对于binlog中的每一条记录, 都会找到对应的分片信息, 如果该binlog记录的offset大于对应的分片的highWatermark , 那么表名改即使是在快照读取之后的记录, 因此加入到数据源中