【科普小文】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

相关文章

MySQL快速复制一张表的四种核心方法(包括表结构和数据)

《MySQL快速复制一张表的四种核心方法(包括表结构和数据)》本文详细介绍了四种复制MySQL表(结构+数据)的方法,并对每种方法进行了对比分析,适用于不同场景和数据量的复制需求,特别是针对超大表(1... 目录一、mysql 复制表(结构+数据)的 4 种核心方法(面试结构化回答)方法 1:CREATE

详解C++ 存储二进制数据容器的几种方法

《详解C++存储二进制数据容器的几种方法》本文主要介绍了详解C++存储二进制数据容器,包括std::vector、std::array、std::string、std::bitset和std::ve... 目录1.std::vector<uint8_t>(最常用)特点:适用场景:示例:2.std::arra

一篇文章让你彻底搞懂Java中VO、DTO、BO、DO、PO

《一篇文章让你彻底搞懂Java中VO、DTO、BO、DO、PO》在java编程中我们常常需要做数据交换,那么在数据交换过程中就需要使用到实体对象,这就不可避免的使用到vo、dto、po等实体对象,这篇... 目录深入浅出讲解各层对象区别+实战应用+代码对比,告别概念混淆,设计出更优雅的系统架构!一、 为什么

SpringBoot整合Apache Spark实现一个简单的数据分析功能

《SpringBoot整合ApacheSpark实现一个简单的数据分析功能》ApacheSpark是一个开源的大数据处理框架,它提供了丰富的功能和API,用于分布式数据处理、数据分析和机器学习等任务... 目录第一步、添加android依赖第二步、编写配置类第三步、编写控制类启动项目并测试总结ApacheS

MySQL中的DELETE删除数据及注意事项

《MySQL中的DELETE删除数据及注意事项》MySQL的DELETE语句是数据库操作中不可或缺的一部分,通过合理使用索引、批量删除、避免全表删除、使用TRUNCATE、使用ORDERBY和LIMI... 目录1. 基本语法单表删除2. 高级用法使用子查询删除删除多表3. 性能优化策略使用索引批量删除避免

MySQL 数据库进阶之SQL 数据操作与子查询操作大全

《MySQL数据库进阶之SQL数据操作与子查询操作大全》本文详细介绍了SQL中的子查询、数据添加(INSERT)、数据修改(UPDATE)和数据删除(DELETE、TRUNCATE、DROP)操作... 目录一、子查询:嵌套在查询中的查询1.1 子查询的基本语法1.2 子查询的实战示例二、数据添加:INSE

Linux服务器数据盘移除并重新挂载的全过程

《Linux服务器数据盘移除并重新挂载的全过程》:本文主要介绍在Linux服务器上移除并重新挂载数据盘的整个过程,分为三大步:卸载文件系统、分离磁盘和重新挂载,每一步都有详细的步骤和注意事项,确保... 目录引言第一步:卸载文件系统第二步:分离磁盘第三步:重新挂载引言在 linux 服务器上移除并重新挂p

使用MyBatis TypeHandler实现数据加密与解密的具体方案

《使用MyBatisTypeHandler实现数据加密与解密的具体方案》在我们日常的开发工作中,经常会遇到一些敏感数据需要存储,比如用户的手机号、身份证号、银行卡号等,为了保障数据安全,我们通常会对... 目录1. 核心概念:什么是 TypeHandler?2. 实战场景3. 代码实现步骤步骤 1:定义 E

使用C#导出Excel数据并保存多种格式的完整示例

《使用C#导出Excel数据并保存多种格式的完整示例》在现代企业信息化管理中,Excel已经成为最常用的数据存储和分析工具,从员工信息表、销售数据报表到财务分析表,几乎所有部门都离不开Excel,本文... 目录引言1. 安装 Spire.XLS2. 创建工作簿和填充数据3. 保存为不同格式4. 效果展示5

Python多任务爬虫实现爬取图片和GDP数据

《Python多任务爬虫实现爬取图片和GDP数据》本文主要介绍了基于FastAPI开发Web站点的方法,包括搭建Web服务器、处理图片资源、实现多任务爬虫和数据可视化,同时,还简要介绍了Python爬... 目录一. 基于FastAPI之Web站点开发1. 基于FastAPI搭建Web服务器2. Web服务