背景简介
想必做过商品服务都是将商品相关的信息和价格保存在数据库中,例如 MySql
,当有商品的信息和价格一条数据新增或修改需要马上将数据同步到 kafka 中或其他的数据库中,这时候就可以借助阿里开源出来的 Canal
来实现我们功能。
阿里巴巴 B2B 公司,因为业务的特性,卖家主要集中在国内,买家主要集中在国外,所以衍生出了同步杭州和美国异地机房的需求,从 2010 年开始,阿里系公司开始逐步的尝试基于数据库的日志解析,获取增量变更进行同步,由此衍生出了增量订阅&消费的业务。Canal 是用 Java 开发的基于数据库增量日志解析,提供增量数据订阅&消费的中间件。
目前。Canal 主要支持了 MySQL 的 Binlog 解析,解析完成后才利用 Canal Client 来处理获得的相关数据。(数据库同步需要阿里的 Otter 中间件,基于 Canal)。
What is canal
![](https://img.haomeiwen.com/i5898843/0d077fe7d2cd80d7.png)
官方描述:canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 「MySQL 数据库增量日志解析」,提供「增量数据订阅和消费」。
简单理解 canal
主要是针对 MySQL
「增量数据同步工具」,将实时数据同步到 Mysql
、Kafka
、Elasticsearch
、Hbase
、RocketMQ
、Pulsar
等
[图片上传失败...(image-c1ec1-1680519205500)]
canal 使用场景
-
数据库镜像
-
数据库实时备份
-
索引构建和实时维护(拆分异构索引、倒排索引等)
-
业务
cache
刷新 -
带业务逻辑的增量数据处理
注意: 当前 Canal支持的 MySQL 版本有 5.1.x
, 5.5.x
, 5.6.x
, 5.7.x
, 8.0.x
MySQL 的 Binary Log 简介
什么是 Binlog MySQL 的二进制日志可以说 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 想做监控分析,选择 row 格式比较合适。
-
mysql
的binlog
是多文件存储,定位一个LogEvent
需要通过binlog filename + binlog position
,进行定位 -
mysql
的binlog
数据格式,按照生成的方式,主要分为:statement-based
、row-based
、mixed
。
mysql> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 row in set (0.00 sec)
「binlog 结构解析图」
![](https://img.haomeiwen.com/i5898843/2dc13ed65781a01d.png)
canal 工作原理
了解 canal 工作原理前,我们需要知道 **「MySQL 主备复制原理」
![](https://img.haomeiwen.com/i5898843/49ce23d805aff006.png)
MySQL 主备复制原理
-
MySQL master
将数据变更写入二进制日志(binary log
, 其中记录叫做二进制日志事件binary log events
,可以通过show binlog events
进行查看) -
MySQL slave
将master
的binary log events
拷贝到它的中继日志(relay log
) -
MySQL slave
重放relay log
中事件,将数据变更反映它自己的数据
「canal 工作原理」也就是基于「MySQL 主备复制原理」,因此也就相对比较简单:
-
canal 模拟
mysql slave
的交互协议,伪装自己为mysql slave
,向mysql master
发送dump
协议 -
mysql master
收到dump
请求,开始推送binary log
给slave
(也就是 canal) -
canal 解析
binary log
对象(原始为byte
流)
canal 架构
1.1.4 canal 整体架构,主要包括 admin模块、server模块、instance模块、client-adapter模块、RDS、zk、消息中间件等。个人认知:
一个Canal Sever服务器中可以包含一个或者多个Instance(实例|目的地),每一个Instance就是一个任务处理线程,用于从不同的MySQL服务器或者同一个MySQL的不同数据库监听收集binlog日志(canal监听mysql的数据配置在example/instance.properties文件中),canal默认提供一个example实例,如果需要多个实例在conf中创建一个文件夹instanceA,复制example/instance.properties文件到instanceA中并修改,在canal.properties文件中设置destinations时逗号分割,如果没有设置则实例无效。
![](https://img.haomeiwen.com/i5898843/4d67332c351d52fd.png)
「说明:」
-
「canal-admin」:设计上是为
canal
提供整体配置管理、节点运维等面向运维的功能,提供相对友好的WebUI
操作界面,方便更多用户快速和安全的操作 -
「canal-server cluster」:同一个集群中的多台
canal-server
,一个集群中有多个instance
实例任务,每个instance
实例通过zookeeper
在集群中实现高可用,一般我们是通过3台canal-server
组成集群模式 -
「canal-server」:一个
canal-server
里可以运行多个instance
实例任务 -
「instance」:一个实际运行订阅
mysql
的数据队列(核心模块),包括了EventPaser
、EventSink
、EventStore
等组件 -
「canal-client」:用于消费
instance
订阅mysql
的数据队列,RocketMQ 投递的方式是一样的(内嵌 client 将消费到的数据直接投递到 RocketMQ中,业务开发只需要订阅 RocketMQ 消息即可)。不管是内嵌 client 的方式,还是 canal-client 的方式都是 基于Mysql 的 Slave 协议实时 dump binlog 流,解析为事件发送给订阅方。数据对象格式:EntryProtocol.proto
Entry
Header
logfileName [binlog文件名]
logfileOffset [binlog position]
executeTime [binlog里记录变更发生的时间戳]
schemaName [数据库实例]
tableName [表名]
eventType [insert/update/delete类型]
entryType [事务头BEGIN/事务尾END/数据ROWDATA]
storeValue [byte数据,可展开,对应的类型为RowChange]
RowChange
isDdl [是否是ddl变更操作,比如create table/drop table]
sql [具体的ddl sql]
rowDatas [具体insert/update/delete的变更数据,可为多条,1个binlog event事件可对应多条变更,比如批处理]
beforeColumns [Column类型的数组]
afterColumns [Column类型的数组]
Column
index [column序号]
sqlType [jdbc type]
name [column name]
isKey [是否为主键]
updated [是否发生过变更]
isNull [值是否为null]
value [具体的内容,注意为文本]
说明:
-
可以提供数据库变更前和变更后的字段内容,针对binlog中没有的name,isKey等信息进行补全
-
可以提供ddl的变更语句
![](https://img.haomeiwen.com/i5898843/360965f16ad3060b.png)
canal-server 架构
「说明:」
-
server
代表一个canal
运行实例,对应于一个jvm
-
instance
对应于一个数据队列 (1个server
对应1..n个instance
)
「instance模块:」
-
「eventParser」 :数据源接入,模拟
slave
协议和master
进行交互:dump binlog、协议解析 -
「eventSink」 :
Parser
和Store
链接器,进行数据过滤,加工,分发的工作 -
「eventStore」 :存储
sink
模块处理后的数据 -
「metaManager」 :增量订阅&消费信息管理器
canal 部署
Canal Server的 VM命令行模式快速启动,参考:Canal Server QuickStart
Canal Server的 docker 模式快速启动,参考:Canal Server Docker QuickStart
Canal Admin的 VM命令行模式快速启动,参考:Canal Admin QuickStart
Canal Admin的 docker 模式快速启动,参考:Canal Admin Docker
Canal Admin
canal 1.1.4版本,迎来最重要的WebUI能力,引入canal-admin工程,支持面向WebUI的canal动态管理能力,支持配置、任务、日志等在线白屏运维能力,官方参考文档:Canal Admin Guide
canal-admin的核心模型主要有:
-
instance,对应canal-server里的instance,一个最小的订阅mysql的队列
-
server,对应canal-server,一个server里可以包含多个instance
-
集群,对应一组canal-server,组合在一起面向高可用HA的运维
简单解释:
-
instance因为是最原始的业务订阅诉求,它会和 server/集群 这两个面向资源服务属性的进行关联,比如instance A绑定到server A上或者集群 A上.
-
有了任务和资源的绑定关系后,对应的资源服务就会接收到这个任务配置,在对应的资源上动态加载instance,并提供服务动态加载的过程,有点类似于之前的autoScan机制,只不过基于canal-admin之后可就以变为远程的web操作,而不需要在机器上运维配置文件。
-
将server抽象成资源之后,原本canal-server运行所需要的canal.properties/instance.properties配置文件就需要在web ui上进行统一运维,每个server只需要以最基本的启动配置 (比如知道一下canal-admin的manager地址,以及访问配置的账号、密码即可)。
理解了这一层基本概念之后,就开始WebUI的操作介绍.
集群运维
-
创建集群
image.png
- 集群变更
![](https://img.haomeiwen.com/i5898843/ac43d6b8e7eab5fd.png)
配置项:
-
修改集群/删除集群,属于基本的集群信息维护和删除
-
主配置,主要是指集群对应的canal.properties配置,设计上一个集群的所有server会共享一份全局canal.properties配置 (如果有个性化的配置需求,可以创建多个集群)
-
查看server,主要是指查看挂载在这个集群下的所有server列表
Server运维
- 新建Server
![](https://img.haomeiwen.com/i5898843/43951b0d758db38e.png)
配置项:
-
所属集群,可以选择为单机 或者 集群。一般单机Server的模式主要用于一次性的任务或者测试任务
-
Server名称,唯一即可,方便自己记忆
-
Server Ip,机器ip
-
admin端口,canal 1.1.4版本新增的能力,会在canal-server上提供远程管理操作,默认值11110
-
tcp端口,canal提供netty数据订阅服务的端口
-
metric端口, promethues的exporter监控数据端口 (未来会对接监控)
- Server变更
![](https://img.haomeiwen.com/i5898843/b3ad9a8af2f98d48.png)
配置项:
-
配置,主要是维护单机模式的canal.properties配置,注意:挂载到集群模式的server,不允许单独编辑server的canal.properties配置,需要保持集群配置统一
-
修改/删除,主要是维护server的基本属性,比如名字和ip、port
-
启动/停止,主要是提供动态启停server的能力,比如集群内这个机器打算下线了,可以先通过停止释放instance的运行,集群中的其他机器通过HA就会开始接管任务
-
日志,查看server的根日志,主要是canal/canal.log的最后100行日志
-
详情,主要提供查询在当前这个server上运行的instance列表,以server维度方便快速做instance的启动、停止操作. 比如针对集群模式,如果server之间任务运行负载不均衡,可以通过对高负载Server执行部分Instance的停止操作来达到均衡的目的
image.png
Instance运维
- 创建Instance
![](https://img.haomeiwen.com/i5898843/284b45da54fc0786.png)
instance配置比较简单,主要关注:
-
资源关联,比如挂载到具体的单机 或 集群
-
instance.properties配置维护,可以载入默认模板进行修改
- Instance变更
![](https://img.haomeiwen.com/i5898843/291423658ef4a9fb.png)
配置项:
-
修改,主要就是维护instance.properties配置,做了修改之后会触发对应单机或集群server上的instance做动态reload
-
删除,相当于直接执行instance stop,并执行配置删除
-
启动/停止,对instance进行状态变更,做了修改会触发对应单机或集群server上的instance做启动/停止操作
-
日志,主要针对instance运行状态时,获取对应instance的最后100行日志,比如example/example.log
Summary
canal的好处在于对业务代码没有侵入,因为是基于监听binlog日志去进行同步数据的。实时性也能做到准实时,其实是很多企业一种比较常见的数据同步的方案。
实际项目我们是使用mq模式-服务端主动推送模式,配合RocketMQ或者Kafka,canal会把数据发送到MQ/kafka的topic中,然后通过消息队列的消费者进行处理。
![](https://img.haomeiwen.com/i5898843/085f2768f5a53476.png)
canal相关文档
canal 消息投递给 kafka/RocketMQ 相关文档
canal 的 docker 模式快速启动
canal Client API 相关文档
网友评论