MySQL数据库同步CDC方案调研

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,内容安全 1000次 1年
对象存储 OSS,恶意文件检测 1000次 1年
简介: 数据库同步是一个比较常见的需求,业务数据一般存储在一致性要求比较高的OLTP数据库中,在分析场景中往往需要OLAP数据库或者比较火的数据湖方案;CDC是数据库同步较为流行的方案,全称是Change Data Capture,主要用于捕捉数据库中变化的数据,然后根据变化的数据写入不同的目标存储。接下来是一些数据库CDC方案的调研及原理探讨,调研方案基于MySQL数据库。

前言

数据库同步是一个比较常见的需求,业务数据一般存储在一致性要求比较高的OLTP数据库中,在分析场景中往往需要OLAP数据库或者比较火的数据湖方案;CDC是数据库同步较为流行的方案,全称是Change Data Capture,主要用于捕捉数据库中变化的数据,然后根据变化的数据写入不同的目标存储。接下来是一些数据库CDC方案的调研及原理探讨,调研方案基于MySQL数据库。

本文会主要关注同步过程中一致性的技术点,如有偏颇,欢迎拍砖。

CDC方案大致可以分为基于查询的和基于日志的方案,基于查询的方案是基于SELECT语句来查询发现变化的数据,基于日志是指MySQL的binlog,天然记录了数据库的变化数据。

基于查询的方案

基于查询是指通过定期执行SELECT语句来查看两次查询的结果的差别,每次查询都全量查询数据,然后比较两次数据的差别的方案比较重,并且对于大数据量场景效率也比较低,一般会借助数据库原有数据的递增字段来查询,比较常见的追踪变化的字段类型包括:

基于更新时间戳

在数据库的行的定义中定义更新字段,比如update_time;将上次同步的时间记为last_update_time,然后下次查询时只拉取update_time比last_update_time大的数据;

此方案实现简单,但是对于update_time有要求,在两次查询期间可能有update_time相同的数据可能会造成数据重复(update_time >= last_update_time)或者漏查(update_time > last_update_time)的风险。

基于递增主键

数据库的行中一般会定义主键,比如订单ID,用户ID等可以定义成自增主键,这些主键也可以用于跟踪变化的数据,下次查询数据只要比上次查询的数据最大的主键大就可以获取到变化的数据;

此方案对于主键有一个要求就是主键必须是递增的,新的数据的主要一定要比原有数据的主键大(类型不限),比如uuid作为主键是不适合的(uuid作为主键一般也不是最佳实践)。

还有一些其他类似的字段或者是多个字段的组合,本质上都是通过字段的递增变化来发现变化的数据。基于查询的方案有如下一些特点:

  • 要求数据库表包含递增字段,最好是严格递增字段(不含等于)。
  • 适合appendonly的数据库表,例如归档订单数据,消息表等,如果含有更新或删除操作,查询的方案往往不能发现。
  • 使用基于查询的产品有Splunk DBConnect,Kafka Connect。

基于Binlog方案

binlog是在MySQL服务层实现的独立于存储引擎的事务日志,会记录所有的DDL和和包含变更的DML,以Event的格式记录,同时会记录语句的执行时间。可以认为是MySQL的ChangeLog。binlog主要用在数据库的崩溃恢复和主从复制场景。数据同步方案类一般是模拟主从复制场景。开源领域有很多成熟的方案,如阿里的Canal,debezium等。

以下是MySQL借助binlog实现主备复制的原理:

master写入binlog后,slave通过IO线程将binlog写到自己的relay log,然后slave通过sql线程重放relay log中的事件,来实现主备的数据同步。

canal是基于master/slave的同步协议,将自己注册成slave来实现同步,主要步骤:

  • canal发送dump协议给MySQL master。
  • master收到dump请求,将binlog推送到canal。
  • canal解析binlog事件对象。

在该方案中,主要通过注册slave和dump协议来完成对数据的同步,对于订阅数据库的变更是很理想的方案,特点如下:

  • binlog记录了数据库的变更,对于增量数据的同步非常适合,比如数据的变更更新到消息系统或者更新缓存。
  • 由于master的binlog可能会删除,所以对于全量同步还是有一定局限性。

基于Snapshot+Binlog

Flink CDC 2版本在2021年发布,包含了MySQL CDC的版本更新,接下来根据分别介绍下其旧版本的原理和新版本的改进。

如果要全量读取MySQL的数据并且保持增量数据的更新,直观的方案就是先对MySQL的数据进行读取snapshot,然后接着从binlog消费变更数据。这个方案的关键点在于binlog消费与snapshot的无缝衔接。总体来说:Flink CDC 1.x使用了锁方案,Flink CDC 2使用了无锁方案。

全局锁方案

Flink CDC背后使用的是Debezium对数据进行同步,同步一张表包含两个阶段:

  • 全量同步:拉取所有表中的现有数据。
  • 增量同步:消费binlog变更数据。

全量同步阶段使用了锁,默认使用全局锁,在全局锁不可用的时候会使用表锁。我们来看下为什么需要锁,假如不用锁的情况下,可能分为如下两种情况:

  • 1)SELECT所有数据,2)读取binlog消费点,3)从binlog消费点消费:这种情况SELECT数据在执行的过程中,会消耗一定的时间,这段时间内可能会有新的更新,这个更新在SELECT数据中不存在;在SELECT数据读取完毕后,在获取binlog消费点,这时候binlog消费点可能丢失了SELECT数据后的一小段更新,造成数据丢失。
  • 1)读取binlog消费点,2)SELECT所有数据,3)从binlog消费点消费。在步骤2中的SELECT数据可能已经包含了步骤1中的消费点后的数据,比如SELECT包含了数据a,binlog消费点后包含数据a的insert,这时候步骤3从binlog消费点消费时,数据a又会插入,出现数据重复。

简单原理可以通过下图示意:图中每个格子表示一个CUD操作,可以简单的把每个格子连起来当做binlog。如果在读取Snapshot时加锁,在读完的时候再读取binlog的位置,可以保证数据是连续的,不重不漏,过早或者过晚读取binlog都会造成数据的不一致。

所以为了保证数据的一致性,需要增加全局锁或者表锁,然后借助MySQL的可重复读事务进行读取全量数据和binlog消费点,最后释放锁;在可重复事务中,可以保证消费点和当前数据的无缝衔接。在最后的binlog消费过程中,保证数据不重不漏。

该方法有如下特点:

  • 可重复读事务保证了数据库表的schema和binlog消费位点更当前数据的匹配。
  • 全局锁或者表锁,会阻止数据的更新,锁的时间越长对于数据库影响越多,特别是线上业务可能会造成业务的阻塞。

无锁方案

Flink CDC 2.0使用了无锁方案,避免了1.x中的锁造成的阻塞。方案借鉴了Netflix的DBlog的设计。主要改进在于Chunk并发读取和无锁操作。所以这里直接看下DBLog的基于Chunk的无锁实现。直接拿文中的实例来看算法的实现。


以MySQL为例,在执行SELECT前后在binlog中增加Low watermark和High watermark,这时候SELECT出的resultset一定是lw和hw之间的快照。然后在result set中去掉与lw和hw之间有重叠的数据,最后再把去掉后的数据作为output buffer,最后在执行binlog的replay,这样就能做到数据的不重不漏。可以通过一些例子来看是否有重复和遗漏:

  • 一个insert事件在lw之后,select之前,这时select的数据是包含insert的数据,把select中的数据去掉insert的条目,在执行从lw到hw的binlog replay,insert的数据还是会出现在最终结果中。
  • insert事件在select之后,hw之前,这时select不包含insert的数据,在select数据去掉insert的条目(没有改变),在执行lw到hw的binlog replay,insert的数据还是会出现在最终结果中。

同理,对于update和delete事件,都可以做到保证数据的一致性。

接下来以一个简单的图示来描述根据snapshot和binlog如何做到一致性:

上图中排除chunk的影响,把数据库的数据可以想象成binlog的序列,假设binlog是无大小限制,图中每个格子代表一个原子操作,操作序列从开始到任意一个格子按顺序apply可以得到当前数据库的所有内容。图中LW,HW代表获取的binlog位置的低水位和高水位,执行流程:

  1. 首先通过 SHOW MASTER STATUS 获取当前binlog文件的偏移量当做LW;
  2. 然后通过SELECT读取全量数据的快照Snaphost,在读取的过程中无锁操作,允许数据的插入和更新;
  3. 读取完快照Snaphost再通过SHOW MASTER STATUS获取当前binlog文件偏移量当做HW;
  4. 读取LW到HW中的数据集称为delta,设置Snapshot = Snapshot - delta;
  5. 基于最新的Snaphost,从LW开始消费binlog;从此之后可以获取数据库的Full State。

从这张图的可以看出提前读取binlog可以做到无锁读取数据库的Full State,根本原因在于从Snaphot排除掉LW到HW的binlog的影响,第4步得到的结果可以当作LW之前的全量数据;这里第4步有一个前提:数据行必须有主键,否则不好做差集操作。


通过上面的例子可以看出无锁方案获取完整数据的思路,但是在获取Snapshot时,往往数据量很庞大,由于无锁方案一般要求数据行有主键,所以可以根据主键将数据拆分成多个chunk,然后在每个chunk中执行类似操作,使用并发的方式可以提供读取的性能。细节在参考文件中会有介绍,本文主要关注在数据表Full State的获取方案,chunk方案可以参考论文或者Flink CDC 2.0的实现。还有很多细节文中没有过多介绍,比如binlog中数据库schema的变更,也会影响到数据的同步。

总结

在CDC方案中,基于查询和binlog的方案都有一定的劣势,在全量数据下,一致性方面都会有所欠缺,基于Snapshot+binlog的方案结合了两者的特点,可以保证同步数据的一致性。但是原生的基于锁的全量数据获取具有一定的性能问题,基于DBLog的无锁方案在性能和一致性上可以兼得。是比较理想的方案。

参考

Change data capturehttps://en.wikipedia.org/wiki/Change_data_capture#Methodology

Alibaba canalhttps://github.com/alibaba/canal

Flink CDC 2.0 正式发布,详解核心改进:https://flink-learning.org.cn/article/detail/3ebe9f20774991c4d5eeb75a141d9e1e

DBLog: A Generic Change-Data-Capture Frameworkhttps://netflixtechblog.com/dblog-a-generic-change-data-capture-framework-69351fb9099b

splunk DB Connect:https://splunkbase.splunk.com/app/2686/

MySQL Source (JDBC) Connector for Confluent Cloud:https://docs.confluent.io/cloud/current/connectors/cc-mysql-source.html#step-2-add-a-connector


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
14天前
|
安全 关系型数据库 MySQL
如何将数据从MySQL同步到其他系统
【10月更文挑战第17天】如何将数据从MySQL同步到其他系统
85 0
|
2月前
|
canal 缓存 NoSQL
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
根据对一致性的要求程度,提出多种解决方案:同步删除、同步删除+可靠消息、延时双删、异步监听+可靠消息、多重保障方案
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
|
18小时前
|
存储 SQL 关系型数据库
Mysql高可用架构方案
本文阐述了Mysql高可用架构方案,介绍了 主从模式,MHA模式,MMM模式,MGR模式 方案的实现方式,没有哪个方案是完美的,开发人员在选择何种方案应用到项目中也没有标准答案,合适的才是最好的。
21 3
Mysql高可用架构方案
|
2天前
|
缓存 关系型数据库 MySQL
高并发架构系列:数据库主从同步的 3 种方案
本文详解高并发场景下数据库主从同步的三种解决方案:数据主从同步、数据库半同步复制、数据库中间件同步和缓存记录写key同步,旨在帮助解决数据一致性问题。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
高并发架构系列:数据库主从同步的 3 种方案
|
1天前
|
关系型数据库 MySQL
mysql 5.7.x版本查看某张表、库的大小 思路方案说明
mysql 5.7.x版本查看某张表、库的大小 思路方案说明
17 5
|
6天前
|
关系型数据库 MySQL
mysql 5.7.x版本查看某张表、库的大小 思路方案说明
mysql 5.7.x版本查看某张表、库的大小 思路方案说明
14 1
|
12天前
|
算法 大数据 数据库
云计算与大数据平台的数据库迁移与同步
本文详细介绍了云计算与大数据平台的数据库迁移与同步的核心概念、算法原理、具体操作步骤、数学模型公式、代码实例及未来发展趋势与挑战。涵盖全量与增量迁移、一致性与异步复制等内容,旨在帮助读者全面了解并应对相关技术挑战。
20 3
|
2月前
|
存储 SQL 关系型数据库
【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)
MySQL调优主要分为三个步骤:监控报警、排查慢SQL、MySQL调优。 排查慢SQL:开启慢查询日志 、找出最慢的几条SQL、分析查询计划 。 MySQL调优: 基础优化:缓存优化、硬件优化、参数优化、定期清理垃圾、使用合适的存储引擎、读写分离、分库分表; 表设计优化:数据类型优化、冷热数据分表等。 索引优化:考虑索引失效的11个场景、遵循索引设计原则、连接查询优化、排序优化、深分页查询优化、覆盖索引、索引下推、用普通索引等。 SQL优化。
489 15
【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)
|
2月前
|
存储 SQL 关系型数据库
一篇文章搞懂MySQL的分库分表,从拆分场景、目标评估、拆分方案、不停机迁移、一致性补偿等方面详细阐述MySQL数据库的分库分表方案
MySQL如何进行分库分表、数据迁移?从相关概念、使用场景、拆分方式、分表字段选择、数据一致性校验等角度阐述MySQL数据库的分库分表方案。
314 15
一篇文章搞懂MySQL的分库分表,从拆分场景、目标评估、拆分方案、不停机迁移、一致性补偿等方面详细阐述MySQL数据库的分库分表方案
|
29天前
|
SQL 存储 关系型数据库
Mysql主从同步 清理二进制日志的技巧
Mysql主从同步 清理二进制日志的技巧
22 1

推荐镜像

更多