CDC 的全称是 Change Data Capture ,在广义的概念上,只要能捕获数据变更的技术,我们都可以称为 CDC 。我们通常所描述的CDC 技术主要是指面向数据库的变更,是一种用于捕获数据库中数据变更的技术。
数据同步,用于备份,容灾
数据分发,一个数据源分发给多个下游系统
数据采集,面向数据仓库/数据湖的 ETL 数据集成,是非常重要的数据源
基于查询的 CDC
基于日志的 CDC
差异点对比:
总结:
经过以上对比,我们可以发现基于日志的 CDC 有以下几种优势:
能够捕获所有数据的变化,捕获完整的变更记录。在异地容灾,数据备份等场景中得到广泛应用,如果是基于查询的 CDC 有可能导致两次查询的中间一部分数据丢失
每次 DML 操作均有记录无需像查询 CDC 这样发起全表扫描进行过滤,拥有更高的效率和性能,具有低延迟,不增加数据库负载的优势
无需入侵业务,业务解耦,无需更改业务模型
捕获删除事件和捕获旧记录的状态,在查询 CDC 中,周期的查询无法感知中间数据是否删除
简单了解了CDC的概念以及一些基本的CDC工具之后,下面我们就针对个别CDC工具来进行详细介绍,以便帮助大家了解下CDC的具体工作原理。
Canal 是用 Java 开发的基于数据库增量日志解析,提供增量数据订阅&消费的中间件。
举个例子:假设我们有一个需要同步数据的数据库product_source,还有一个用来存储product_source中数据的数据库product_sink,若product_source中有10条数据,那么此时我们就可以启动canal,将product_source中后续更新的数据同步到product_sink这个数据库中。不过,这同时也体现出了canal的一个缺点——不支持数据的全量同步,也就是说之前的10条数据是无法通过canal同步过去的。
目前,Canal 主要支持了 MySQL 的 Binlog 解析。
可能有些同学对于MySQL的Binlog不太熟悉,这里简单介绍一下:
Binlog概述:
MySQL 的二进制日志记录了所有的 DDL 和 DML(除了数据查询语句)语句,以事件形式记录,还包含语句执行时所消耗的时间,MySQL 的二进制日志是事务安全型的。
一般来说开启二进制日志大概会有 1%的性能损耗。二进制有两个最重要的使用场景:
其一:MySQL Replication 在 Master 端开启 Binlog,Master 把它的二进制日志传递给 Slaves,来达到 Master-Slave 数据一致的目的。
其二:自然就是数据恢复了,通过使用 MySQL Binlog 来使数据恢复。
二进制日志包括两类文件:二进制日志索引文件(文件名后缀为.index),用于记录所有的二进制文件;二进制日志文件(文件名后缀为.00000*),用于记录数据库所有的 DDL 和 DML(除了数据查询语句)语句事件。
Binlog分类:
MySQL Binlog 的格式有三种,分别是 STATEMENT,MIXED和ROW。在配置文件中可以选择配置:
binlog_format= statement|mixed|row。
三种格式的区别:
1)statement:语句级,binlog 会记录每次执行写操作的语句。相较于 row 模式更节省空间,但是可能会产生不一致性,比如“update tt set create_date=now()”,如果用 binlog 日志进行恢复,由于执行时间不同可能产生的数据就不同。
优点:节省空间。
缺点:有可能造成数据不一致。
2)row:行级, binlog 会记录每次操作后每行记录的变化。
优点:保持数据的绝对一致性。因为不管 sql 是什么,引用了什么函数,他只记录执行后的效果。
缺点:占用较大空间。
3)mixed:statement 的升级版,一定程度上解决了因为一些情况而造成的 statement模式不一致问题,默认还是 statement,但在某些情况下譬如:当函数中包含 UUID() 时;包含AUTO_INCREMENT 字段的表被更新时;执行 INSERT DELAYED 语句时;用 UDF 时,会按照ROW 的方式进行处理。
优点:节省空间,同时兼顾了一定的一致性。
缺点:还有极个别情况依旧会造成不一致,另外 statement 和 mixed 对于那种需要对binlog进行监控的情况来说都不方便。
Canal工作原理
MySQL主备复制原理:
MySQL master 将数据变更写入二进制日志( binary log,其中的记录叫做二进制日志事件binary log events,可以通过 show binlog events 进行查看)
MySQL slave 将 master 的 binary log events 拷贝到它的中继日志(relay log)里面
MySQL slave 重放 relay log 中的事件,将数据变更反映成它自己的数据
canal 工作原理:
canal 模拟 MySQL slave 的交互协议,把自己伪装成 MySQL slave ,向 MySQL master 发送dump 协议
MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
canal 解析 binary log 对象(原始为 byte 流)
思路梳理:
现在,我们知道了Mysql Binlog的基本情况:记录了所有的 DDL 和 DML(除了数据查询语句)语句。那么当canal获取到这些DDL和DML语句时,就需要针对这些语句进行解析,然后可以按照配置过滤掉不需要的数据,最后将数据分发到下游,完成同步。那么我们就带着这个思路来了解下canal的架构。
canal架构:
server 代表一个 canal 运行实例,对应一个 jvm。既然有server,那么自然就有client。server端主要负责同步mysql消息,client负责访问server端消费消息。
instance 对应一个数据队列 (1个 canal server 对应 1..n 个 instance )
instance 下的子模块
– eventParser: 数据源接入,模拟 slave 协议和 master 进行交互,协议解析
– eventSink: Parser 和 Store 链接器,进行数据过滤,加工和分发的工作
– eventStore: 数据存储
– metaManager: 增量订阅 & 消费信息管理器
Canal的Server端本身根据配置启动了很多个Instance对象,所谓的Instance对象就是模拟的数据库slave和master进行连接,换句话说就是假设canal同时成为N个数据库的slave,那么就会有N个Instance实例。
同步的数据流是按照eventParser->eventSink->eventStore进行传输的。
eventParser:
最基本的组件,类似于mysql从库的dump线程,负责从master中获取bin_log并解析
从图中可以看出,eventParser负责记录binlog解析位置、伪装slave端获取binlog、解析binlog并传递。
eventSink :
使用设置的filter对bin log进行过滤、路由/分发等。
eventStore :
用来存储filter过滤后的数据,目前实现了 memory 模式,支持按照内存大小和内存记录数进行存储大小限制。
canal整体架构:
总结:
canal server代表一个canal运行实例,该实例可以同时监控多个数据库的binlog,那么想要同时监控多个数据库的binlog,就需要开启多个instance实例,数据库与instance一般是一一对应的关系。那么我们可以理解为一个instance就是用来同步某个数据库的一条龙服务:即需要包含获取该数据库的binlog、解析binlog、对binlog进行过滤分发,将处理完的数据暂时存储,等待消费端获取数据,同时需要记录自己的binlog日志解析的位置,所以每个instance实例又包含parser、sink、store以及metamanager服务。
注意:如果没有client消费数据,server是不会从mysql中去获取日志的。同样的,由于event store是将数据存储在内存队列中的,当队列满了之后,server就会阻塞从而无法继续获取binlog。
Canal特性:
支持所有平台。
支持细粒度的系统监控,由Prometheus提供支持。
支持通过GTID等不同方式解析和订阅MySQL binlog。
支持高性能、实时的数据同步。
Canal Server 和 Canal Client 都支持 HA/Scalability。
支持docker。
了解canal的工作原理后,其实应该对所有的CDC工具的基本实现有了初步的了解。譬如第一点:如果获取源数据库的日志变更信息,譬如mysql是将这些信息保存在binlog,但是sqlserver、oracle等并没有binlog的概念,但是有类似的东西,所以基于日志的CDC工具必然需要支持获取这些日志并解析(类似于canal伪装成slave去获取binlog)。然后将解析的数据经过转换分发,最后供给下游消费。差异点无非是支持的功能可能各不相同,比如增量同步、全量同步、全量+增量同步模式的支持,再比如数据转换方面的支持,有些工具可以针对表字段进行聚合、计算等操作之后再同步到目标表。
本期主要依据canal简单介绍CDC工具的大致工作原理,具体业务选择还需要根据具体的业务目标进行调研和考察。
本期主要内容就先到这里,感谢阅读。
* 部分素材来源于网络,版权归原作者所有,如有侵权请联系删除。