使用Canal同步MySQL数据到Kafka

Canal架构原理

1.Canal Server结构
在这里插入图片描述

  • server 代表一个 canal 运行实例,对应于一个 jvm。
  • instance 对应于一个数据队列 (1个 canal server 对应 1…n 个 instance )
  • instance 下的子模块
    a.eventParser: 数据源接入,模拟 slave 协议和 master 进行交互,协议解析
    b.eventSink: Parser 和 Store 链接器,进行数据过滤,加工,分发的工作
    c.eventStore: 数据存储
    metaManager: 增量订阅 & 消费信息管理器

2.Canal同步MySQL数据原理
EventParser在向mysql发送dump命令之前会先从Log Position中获取上次解析成功的位置(如果是第一次启动,则获取初始指定位置或者当前数据段binlog位点)。mysql接受到dump命令后,由EventParser从mysql上pull binlog数据进行解析并传递给EventSink(传递给EventSink模块进行数据存储,是一个阻塞操作,直到存储成功),传送成功之后更新Log Position。流程图如下:
在这里插入图片描述
EventSink起到一个类似channel的功能,可以对数据进行过滤、分发/路由(1:n)、归并(n:1)和加工。EventSink是连接EventParser和EventStore的桥梁。
EventStore实现模式是内存模式,内存结构为环形队列,由三个指针(Put、Get和Ack)标识数据存储和读取的位置。
MetaManager是增量订阅&消费信息管理器,增量订阅和消费之间的协议包括get/ack/rollback,分别为:
(1)Message getWithoutAck(int batchSize),允许指定batchSize,一次可以获取多条,每次返回的对象为Message,包含的内容为:batch id[唯一标识]和entries[具体的数据对象]。
(2)void rollback(long batchId),顾名思义,回滚上次的get请求,重新获取数据。基于get获取的batchId进行提交,避免误操作。
(3)void ack(long batchId),顾名思义,确认已经消费成功,通知server删除数据。基于get获取的batchId进行提交,避免误操作。

3.关于同步MySQL数据配置信息
在这里插入图片描述
首先Canal可以是一个集群,这里以Canal单机为例解释Canal同步MySQL数据配置文件配置原理。
首先需要在Canal中配置CanalServer 对应的canal.properties,这个文件中主要配置Canal对应的同步数据实例(Canal Instance)位置信息及数据导出的模式,例如:我们需要将某个mysql中的数据同步到Kafka中,那么就可以创建一个“数据同步实例”,导出到Kafka就是一种模式。
其次,需要配置Canal Instance 实例中的instance.properties文件,指定同步到MySQL数据源及管道信息。

配置步骤

1.配置“canal.properties”
进入“/opt/canal/conf”目录下,编辑“canal.properties”文件:

#canal将数据写入Kafka,可配:tcp, kafka, RocketMQ,tcp就是使用canal代码接收
canal.serverMode = kafka
#配置canal写入Kafka地址
canal.mq.servers = node1:9092,node2:9092,node3:9092

2.配置mysql slave的权限
Canal的原理是模拟自己为mysql slave,所以这里一定需要做为mysql slave的相关权限 ,授权Canal连接MySQL具有作为MySQL slave的权限:

mysql> CREATE USER canal IDENTIFIED BY 'canal'; 
mysql> GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';  
mysql> FLUSH PRIVILEGES;
mysql> show grants for 'canal' ;

3.配置“instance.properties”
进入“/software/canal/conf/example/”下,编辑“instance.properties”文件:

#canal伪装为一个mysql的salve,配置其id,不要和真正mysql server-id冲突,这里也可以不配置,会自动生成
canal.instance.mysql.slaveId=123456
#配置mysql master 节点及端口
canal.instance.master.address=node2:3306

#配置连接mysql的用户名和密码,就是前面复制权限的用户名和密码
canal.instance.dbUsername=canal
canal.instance.dbPassword=canal

#配置Canal将数据导入到Kafka topic
canal.mq.topic=canal_topic

4.启动Canal
进入“/opt/canal/bin”,执行“startup.sh”脚本启动Canal。

[root@node3 bin]# ./startup.sh 
[root@node3 bin]# jps
68675 CanalLauncher  #启动成功

5.启动zookeeper和Kafka,并监控Kafka中“canal_topic”的数据
注意:“canal_topic”不需要提前创建,默认创建就是1个分区。
6.在MySQL中建表,插入语句

mysql> create database testdb;
mysql> use testdb;
mysql> create table person(id int ,name varchar(255),age int);
mysql> insert into person values (1,"zs",18),(2,"ls",19),(3,"ww",20);
#对应的在Kafka中有对应的数据日志写入
[root@node3 bin]# ./kafka-console-consumer.sh --bootstrap-server node1:9092,node2:9092,node3:9092 --topic canal_topic --from-beginning
{"data":null,"database":"testdb","es":1641278962000,"id":1,"isDdl":false,"mysqlType":null,"old":null,"pkNames":null,"sql":"create database testdb","sqlType":null,"table":"","ts":1641278962857,"type":"QUERY"}
{"data":null,"database":"testdb","es":1641278978000,"id":2,"isDdl":true,"mysqlType":null,"old":null,"pkNames":null,"sql":"create table person(id int ,name varchar(255),age int)","sqlType":null,"table":"person","ts":1641278978622,"type":"CREATE"}
{"data":[{"id":"1","name":"zs","age":"18"},{"id":"2","name":"ls","age":"19"},{"id":"3","name":"ww","age":"20"}],"database":"testdb","es":1641278984000,"id":3,"isDdl":false,"mysqlType":{"id":"int","name":"varchar(255)","age":"int"},"old":null,"pkNames":null,"sql":"","sqlType":{"id":4,"name":12,"age":4},"table":"person","ts":1641278985191,"type":"INSERT"}

以上写入Kafka中json格式如下:

[{
		"data": null,
		"database": "testdb",
		"es": 1641278962000,
		"id": 1,
		"isDdl": false,
		"mysqlType": null,
		"old": null,
		"pkNames": null,
		"sql": "create database testdb",
		"sqlType": null,
		"table": "",
		"ts": 1641278962857,
		"type": "QUERY"
	},
	{
		"data": null,
		"database": "testdb",
		"es": 1641278978000,
		"id": 2,
		"isDdl": true,
		"mysqlType": null,
		"old": null,
		"pkNames": null,
		"sql": "create table person(id int ,name varchar(255),age int)",
		"sqlType": null,
		"table": "person",
		"ts": 1641278978622,
		"type": "CREATE"
	},
	{
		"data": [{
			"id": "1",
			"name": "zs",
			"age": "18"
		}, {
			"id": "2",
			"name": "ls",
			"age": "19"
		}, {
			"id": "3",
			"name": "ww",
			"age": "20"
		}],
		"database": "testdb",
		"es": 1641278984000,
		"id": 3,
		"isDdl": false,
		"mysqlType": {
			"id": "int",
			"name": "varchar(255)",
			"age": "int"
		},
		"old": null,
		"pkNames": null,
		"sql": "",
		"sqlType": {
			"id": 4,
			"name": 12,
			"age": 4
		},
		"table": "person",
		"ts": 1641278985191,
		"type": "INSERT"
	}
]

关于以上json字段解析如下:
data:最新的数据,为JSON数组,如果是插入则表示最新插入的数据,如果是更新,则表示更新后的最新数据,如果是删除,则表示被删除的数据。
database:数据库名称。
es:事件时间,13位的时间戳。
id:事件操作的序列号,1,2,3…
isDdl:是否是DDL操作。
mysqlType:字段类型。
old:旧数据。
pkNames:主键名称。
sql:SQL语句。
sqlType:是经过canal转换处理的,比如unsigned int会被转化为Long,unsigned long会被转换为BigDecimal。
table:表名。
ts:日志时间。
type:操作类型,比如DELETE,UPDATE,INSERT。

7.更新一条数据

mysql> update person set age=100 where id=1;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0

查看kafka监控

[root@node3 bin]# ./kafka-console-consumer.sh --bootstrap-server node1:9092,node2:9092,node3:9092 --topic canal_topic
{"data":[{"id":"1","name":"zs","age":"100"}],"database":"testdb","es":1641281027000,"id":4,"isDdl":false,"mysqlType":{"id":"int","name":"varchar(255)","age":"int"},"old":[{"age":"18"}],"pkNames":null,"sql":"","sqlType":{"id":4,"name":12,"age":4},"table":"person","ts":1641281027891,"type":"UPDATE"}

对应json数据

{
	"data": [{
		"id": "1",
		"name": "zs",
		"age": "100"
	}],
	"database": "testdb",
	"es": 1641281027000,
	"id": 4,
	"isDdl": false,
	"mysqlType": {
		"id": "int",
		"name": "varchar(255)",
		"age": "int"
	},
	"old": [{
		"age": "18"
	}],
	"pkNames": null,
	"sql": "",
	"sqlType": {
		"id": 4,
		"name": 12,
		"age": 4
	},
	"table": "person",
	"ts": 1641281027891,
	"type": "UPDATE"
}
  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 可以使用Canal来实现将MySQL数据同步Kafka。Canal是阿里巴巴开源的一款基于MySQL数据库增量日志解析和同步的工具,可以实时捕获MySQL数据库的增量日志,解析日志内容,并将解析后的数据发送到Kafka等消息队列中。 具体实现步骤如下: 1. 安装Canal并配置MySQL数据源信息。 2. 配置CanalKafka输出端,包括Kafka的地址、topic等信息。 3. 启动Canal服务,并开启Kafka输出端。 4. 在MySQL数据库中进行数据操作,Canal会实时捕获增量日志并将解析后的数据发送到Kafka中。 通过以上步骤,就可以实现将MySQL数据同步Kafka中。 ### 回答2: Canal是一个开源的MySQL数据库数据同步工具,可用于将MySQL数据库中的数据推送到Kafka等消息队列系统中。Canal具有简单易用和高效稳定等特点,可以实时地将MySQL的操作事件转换为消息发布到Kafka中,从而实现数据的传输和同步。 Canal数据同步过程主要分为三个步骤:数据的抽取、数据的传输和数据的写入。在数据的抽取阶段,Canal会通过监听MySQL的binlog日志来实时获取数据库的更新操作事件。在数据的传输阶段,Canal会将获取到的数据转化为Kafka数据结构并将数据推送到Kafka中。在数据的写入阶段,Kafka消费者会接收到Canal推送过来的数据并将数据写入到目标数据库中。 Canal同步MySQL数据Kafka具有以下优点: 1. 实时性好:Canal可以实时获取MySQL的binlog日志,因此同步数据的速度较快,数据可以实时同步Kafka中,提高了数据同步的实时性。 2. 高效稳定:Canal具有高效稳定的数据同步能力,可以对MySQL的大量数据进行实时同步,同时Canal对复杂的数据类型和操作也具有很好的兼容性。 3. 低延迟:Canal同步MySQL数据Kafka的过程中,除了Canal本身的处理时间外,数据传输和写入等步骤都可以实现实时同步,因此具有低延迟的特点。 4. 扩展性强:Canal支持插件机制,可以根据需要进行扩展和定制,支持多种不同的数据源和目标,也支持多线程和分布式部署等高级特性。 总之,Canal同步MySQL数据Kafka是一种高效稳定、实时性好、低延迟、扩展性强的数据同步方案。在实际的数据同步应用中,可以根据具体情况选择适合自己的部署方式和应用场景,并结合其他工具和技术进行更加灵活高效的数据同步。 ### 回答3: Canal是阿里巴巴公司开发的一款基于binlog的增量数据同步工具,可以把MySQL数据库数据变更同步Kafka等消息队列或其他存储介质中。 Canal架构包括三个组件:Canal Server、Canal Client和Canal Adapter。 Canal Server是作为数据源的MySQL数据库的代理工具,负责解析MySQL的binlog日志,并将变更事件以JSON的形式发送给Canal Client。 Canal Client是Canal数据同步的传输逻辑,接受Canal Server解析出来的binlog事件,并将事件转化为适合Kafka等消息队列的消息格式。 Canal Adapter是Canal的一个插件式架构,根据业务需求,可以通过Adapter来将数据发送到Kafka或其他消息队列、ElasticSearch等存储介质中。 在使用Canal同步MySQL数据Kafka时,需要配置Canal Server和Canal Client,其中Canal Server需要连接MySQL数据库,并开启Binlog日志功能。Canal Client需要连接Canal Server,接收MySQL数据库的变更事件,并将事件转换为对应的消息格式发送到Kafka中。 同时,需要根据业务需求配置Canal Adapter,将MySQL数据库数据变更事件转化为Kafka消息队列的消息格式,并发送到Kafka中。 总之,Canal是一款可靠高效的增量数据同步工具,可以帮助企业快速实现数据的分布式同步和多数据源之间的数据交换。在实际应用中,可以结合其他开源工具,如Flink、Presto等,构建出一套全方位的数据处理和分析平台,实现数据的快速处理和洞察。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

留不住的人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值