【科普小文】3分钟搞懂 Apache SeaTunnel CDC 数据同步

2024-04-08 19:52

本文主要是介绍【科普小文】3分钟搞懂 Apache SeaTunnel CDC 数据同步,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

CDC简介

CDC(Change Data Capture)是一种用于跟踪数据库库变更事件(插入、更新、删除)中的行级更改,并将事件以发生的顺序通知到其他系统处理。在容灾场景下,CDC主要实现的是主备间的数据同步,即从主数据库到备数据库的数据实时同步。

file

source ----------> CDC ----------> sink

Apache SeaTunne CDC

SeaTunnel CDC的数据同步分为两种:

  • 快照读:读取表的历史数据

  • 增量跟踪:读取表的增量日志更改数据

2.1 无锁快照同步

无锁快照同步阶段,为什么强调无锁,是因为现有的CDC平台在进行历史数据的同步时可能会进行锁表操作,例如Debezium。快照读阶段就是对数据库的历史数据库进行同步的过程,其基本概述流程如下:

storage------------->splitEnumerator----------split---------->reader^                                   ||                                   |\-----------------report------------/

split划分:splitEnumerator(split分发器)按照指定的字段(例如表id或唯一键)和步长将表数据划分为多个分片split。 并行处理:每个split通过路由算法分配给不同的reader进行并行读取,一个reader会占用一个连接。 事件反馈:每个reader完成split读取后会向splitEnumerator报告进度。 splitEnumerator会发送给reader一个分片,分片的元数据信息如下:

String              splitId         路由id
TableId             tableId         表id
SeatunnelRowType    splitKeyType    分片基于的字段的类型
Object              splitStart      分片读取起点
Object              splitEnd        分片读取终点

reader收到split信息后会生成相关的sql语句,在此之前会记录当前split对应到数据库日志log的开始位置,等处理完当前split后上报report给splitEnumerator,report内容如下:

String      splitId         分片id
Offset      highWatermark   分片对应log的位置,用于后续的校对

2.2 增量同步

增量同步阶段是基于上述快照读取阶段后,在源数据库发生变化时,实时将变更的数据同步到备数据库,不同的是,此阶段监听的是数据库的log日志,例如mysql的bin log。增量跟踪通常是单线程处理,这样可以避免重复拉取bin log,减轻对数据库的压力,因此该阶段只有一个reader工作,只占用一个连接。

data log------------->splitEnumerator----------split---------->reader^                                   ||                                   |\-----------------report------------/

增量同步会合成快照阶段所有split、table,因此只会存在一个split,增量同步阶段的split信息如下:

String                              splitId
Offset                              startingOffset                  所有split中最小的log start
Offset                              endingOffset                    log的结束位置,若无则代表是持续的,例如增量阶段
List<TableId>                       tableIds
Map<TableId, Offset>                tanleWatermarks                 所有split的watermark
List<CompletedSnapshotSplitInfo>    completedSnapshotSplitInfos     快照阶段读取的split细节信息

其中CompletedSnapshotSplitInfo的具体字段如下:

String              splitId
TableId             tableId
SeatunnelRowType    splitKeyType
Object              splitStart
Object              splitEnd
Offset              watermark       对应了report中的highWatermark

增量阶段的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

          insert k3      update k2      delete k1|               |               |v               v               vbin log --|---------------------------------------------------|-- log offsetlow watermark                                     high watermarkCDC读到的数据: k1 k3  k4| 重放v
真实的数据:    k2 k3' k4

增量阶段

在增量阶段开始之前首先会对上一个步骤的所有split做校验,因为在split和split之间的间隙也有可能出现数据更新,例如在split1和split2之间插入了若干条记录,在快照阶段就会遗漏掉,对于这种split之间的数据回捞,seatunnel的做法是:

从所有的split的report中找到最小的watermark,作为start watermark,开始读取log。 每读一条log都去completedSnapshotSplitInfos中找该条数据是否在某个split被处理过了,如果没有被处理过,说明是split间隙数据,应该被重新修正。 当表过滤完后,可以从completedSnapshotSplitInfos中删除,继续处理剩余的表。 直到所有的split都校验结束,就进入到了完全的增量阶段。

    |------------filter split2-----------------||----filter split1------|                  
data log -|-----------------------|------------------|----------------------------------|- log offsetmin watermark      split1 watermark    split2 watermark                    max watermark    

断点续传

如果做到暂停恢复?分布式快照算法(Chandy-Lamport):

假设系统中包含了两个进程p1和p2,p1进程状态包含三个变量X1 Y1 Z1,p2包含了三个变量X2 Y2 Z2,初始状态如下:

p1                                  p2
X1:0                                X2:4
Y1:0                                Y2:2
Z1:0                                Z2:3

此时由p1发起全局snapshot记录,p1先记录本身的进程状态,然后向p2发送marker信息。在marker信息到达p2之前,p2向p1发送message M。

p1                                  p2
X1:0     -------marker------->      X2:4
Y1:0     <---------M----------      Y2:2
Z1:0                                Z2:3

p2收到p1发送来的marker信息后,记录自己的状态,然后p1收到p2之前发送来的message M,由于p1已经做了local snapshot了,所以p1只需要记录M。,所以最终的snapshot如下:

p1 M                                p2
X1:0                                X2:4
Y1:0                                Y2:2
Z1:0                                Z2:3

在SeaTunnel CDC的过程中,marker同发送给所有的reader、splitEnumerator、writer等节点都会保存自己的内存状态。

本文由 白鲸开源科技 提供发布支持!

这篇关于【科普小文】3分钟搞懂 Apache SeaTunnel CDC 数据同步的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/886350

相关文章

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Linux下利用select实现串口数据读取过程

《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设... 目录示例代码(使用select实现)代码解释总结在 linux 系统里,我们可以借助 select、

C#使用iText获取PDF的trailer数据的代码示例

《C#使用iText获取PDF的trailer数据的代码示例》开发程序debug的时候,看到了PDF有个trailer数据,挺有意思,于是考虑用代码把它读出来,那么就用到我们常用的iText框架了,所... 目录引言iText 核心概念C# 代码示例步骤 1: 确保已安装 iText步骤 2: C# 代码程

Pandas处理缺失数据的方式汇总

《Pandas处理缺失数据的方式汇总》许多教程中的数据与现实世界中的数据有很大不同,现实世界中的数据很少是干净且同质的,本文我们将讨论处理缺失数据的一些常规注意事项,了解Pandas如何表示缺失数据,... 目录缺失数据约定的权衡Pandas 中的缺失数据None 作为哨兵值NaN:缺失的数值数据Panda

C++中处理文本数据char与string的终极对比指南

《C++中处理文本数据char与string的终极对比指南》在C++编程中char和string是两种用于处理字符数据的类型,但它们在使用方式和功能上有显著的不同,:本文主要介绍C++中处理文本数... 目录1. 基本定义与本质2. 内存管理3. 操作与功能4. 性能特点5. 使用场景6. 相互转换核心区别

一文详解MySQL索引(六张图彻底搞懂)

《一文详解MySQL索引(六张图彻底搞懂)》MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度,:本文主要介绍MySQL索引的相关资料,文中通过代码介绍的... 目录一、什么是索引?为什么需要索引?二、索引该用哪种数据结构?1. 哈希表2. 跳表3. 二叉排序树4.

python库pydantic数据验证和设置管理库的用途

《python库pydantic数据验证和设置管理库的用途》pydantic是一个用于数据验证和设置管理的Python库,它主要利用Python类型注解来定义数据模型的结构和验证规则,本文给大家介绍p... 目录主要特点和用途:Field数值验证参数总结pydantic 是一个让你能够 confidentl

JAVA实现亿级千万级数据顺序导出的示例代码

《JAVA实现亿级千万级数据顺序导出的示例代码》本文主要介绍了JAVA实现亿级千万级数据顺序导出的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 前提:主要考虑控制内存占用空间,避免出现同时导出,导致主程序OOM问题。实现思路:A.启用线程池

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

PHP轻松处理千万行数据的方法详解

《PHP轻松处理千万行数据的方法详解》说到处理大数据集,PHP通常不是第一个想到的语言,但如果你曾经需要处理数百万行数据而不让服务器崩溃或内存耗尽,你就会知道PHP用对了工具有多强大,下面小编就... 目录问题的本质php 中的数据流处理:为什么必不可少生成器:内存高效的迭代方式流量控制:避免系统过载一次性