Debezium Incremental分析
简介
Incremental snapshotting提供了任意时间点可触发的快照同步、可中断恢复的快照、与流模式并行的快照,也提供了捕获新表快照的能力。
配置使用
- 正常开启Source端抽取,只开启流模式,没有进行历史数据同步。且配置signal.data.collection信号表,表结构如下
# 表名随意 只需要跟signal.data.collection的值对应起来即可 为schema.table模式的名字
CREATE TABLE debezium_signal (id VARCHAR(42) PRIMARY KEY, type VARCHAR(32) NOT NULL, data VARCHAR(2048) NULL);
- 一定要保证signal.data.collection配置的表 要被流模式捕获!oracle需要配置为database.schema.table格式
- 此时我们如果要触发某一张表或者某一批表的历史数据快照,我们只需要往debezium_signal表里插入
# id随意取名 但建议命名可读
INSERT INTO public.debezium_signal (id, type, data) VALUES('ad-hoc-1', 'execute-snapshot', '{"data-collections":["public.config"]');
- 此时Dbz就是public.config这样表开启了增量快照同步
原理分析
基本流程图
时序图
处理数据示例
DBZ代码流程分析
基本流程
-
io.debezium.pipeline.EventDispatcher#dispatchDataChangeEvent
-
io.debezium.pipeline.spi.ChangeRecordEmitter#emitChangeRecords
-
io.debezium.pipeline.spi.ChangeRecordEmitter.Receiver#changeRecord
-
io.debezium.pipeline.signal.ExecuteSnapshot#arrived
-
插入新表的增量快照触发
-
然后会触发进入第一次的read chunk 然后会调用
-
io.debezium.pipeline.source.snapshot.incremental.AbstractIncrementalSnapshotChangeEventSource#emitWindowOpen
方法往信号表里插入一条开启窗口的语句 -
然后会根据排序规则 取到 当前主键组合最大的值 然后进行 Select数据 当一批数据库Select完成之后
-
读取到的数据会被写入到下述变量之中
io.debezium.pipeline.source.snapshot.incremental.AbstractIncrementalSnapshotChangeEventSource#window
-
然后调用
io.debezium.pipeline.source.snapshot.incremental.AbstractIncrementalSnapshotChangeEventSource#emitWindowClose
方法往信号表里插入一条关闭窗口的语句 -
上述整个过程 会阻挡Stream读取一小会时间
-
关闭窗口之后 会继续处理Stream的消息
-
当处理到上面 发送的窗口打开消息的时候 调用下面方法 标记window已经打开
-
io.debezium.pipeline.source.snapshot.incremental.OpenIncrementalSnapshotWindow#arrived
-
然后接着处理Stream的消息,但是会对每条消息跟Window缓存的消息对比,如果发现有更新就保留流式消息最后的结果
-
当Stream消息读取到Close window的时候,会触发
io.debezium.pipeline.source.snapshot.incremental.CloseIncrementalSnapshotWindow#arrived
-
然后会将消息发送到Kafka 完成一次窗口数据的读取合并与发送。
QA
为什么说增量快照是可恢复的
基于信号表的窗口开启关闭与kafka connect offset机制,可以实现当Connect重启之后,重新读取快照的消息。Offset在增量快照阶段,会储存incremental_snapshot_collections、incremental_snapshot_primary_key、incremental_snapshot_maximum_key三个字段来记录增量快照的进程。当出现故障重启的的时候,会读取Offset的内容进行原位置恢复。io.debezium.pipeline.source.snapshot.incremental.AbstractIncrementalSnapshotContext#store
为什么说任意时间点可触发的快照同步
通过Signal表与流阶段捕获消息的方式,可以在任意时间节点,往信号表里插入触发某些表增量同步的信号。