本文主要围绕同步MySQL数据到Redis进行展开,主角是阿里的一个工具Canal,是企业做数据同步使用的比较多的方案
目录
2. 开启Mysql的binlog,并创建用户 以Mysql 8.0 外例
1). 修改instance 配置文件 : conf/example/instance.properties
2).修改canal 配置文件 conf/canal.properties
4.SpringBoot项目中集成 Canal + RabbitMQ
前言
在工作中,我们常常会遇到同步MySQL数据到Redis的需求,我们也会有很多种方式去解决,常见的方式有如下几种
- 业务操作中同步
- 基于binlog方式,本文重点
- 使用消息队列
============以下是针对第二种方案的一个内容整理============
开始之前,看下我们的思路图
======================== 正文内容 ========================
1.认识Canal
canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费
早期阿里巴巴因为杭州和美国双机房部署,存在跨机房同步的业务需求,实现方式主要是基于业务 trigger 获取增量变更。从 2010 年开始,业务逐步尝试数据库日志解析获取增量变更进行同步,由此衍生出了大量的数据库增量订阅和消费业务。
基于日志增量订阅和消费的业务包括
数据库镜像
数据库实时备份
索引构建和实时维护(拆分异构索引、倒排索引等)
业务 cache 刷新
带业务逻辑的增量数据处理
当前的 canal 支持源端 MySQL 版本包括 5.1.x , 5.5.x , 5.6.x , 5.7.x , 8.0.x
2.了解Canal工作原理
1). MySQL主从复制原理
MySQL master 将数据变更写入二进制日志( binary log, 其中记录叫做二进制日志事件binary log events,可以通过 show binlog events 进行查看)
MySQL slave 将 master 的 binary log events 拷贝到它的中继日志(relay log)
MySQL slave 重放 relay log 中事件,将数据变更反映它自己的数据
2).Canal 工作原理
Canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
Canal 解析 binary log 对象(原始为 byte 流)
2. 开启Mysql的binlog,并创建用户 以Mysql 8.0 外例
binlog
binlog是二进制日志文件,用于记录mysql的数据变更,数据在恢复的时候binlog日志起着至关重要的作用。
开启binlog
通过show variables like 'log_%'
查看binlog 是否开启:若开启,可自行跳过该步骤
找到my.ini文件,默认位置:C:\ProgramData\MySQL\MySQL Server 8.0
在mysqld下面添加 server_id=1918 log_bin = mysql-bin binlog_format = ROW 完整的my.ini: [mysql] # 设置mysql客户端默认字符集 default-character-set=utf8 [mysqld] #设置3306端口 port = 3306 # 设置mysql的安装目录 basedir=D:\mysql-5.7.23-winx64 # 允许最大连接数 max_connections=200 # 服务端使用的字符集默认为8比特编码的latin1字符集 character-set-server=utf8 # 创建新表时将使用的默认存储引擎 default-storage-engine=INNODB # Binary Logging server_id=1918 log_bin = mysql-bin binlog_format = ROW
重启MySQL服务,并查看是否开启binlog,查看方式同上。
创建用户,方便后续测试
-- 使用命令登录:mysql -u root -p 或 在客户端软件操作 -- 创建用户 用户名:canal 密码:canal # 注意:myql8.0版本的密码加密方式为caching_sha2_password,如果不做处理在canal连接时会提示连接不上或没有权限 # 所以我们修改为mysql_native_password create user 'canal'@'%' IDENTIFIED WITH mysql_native_password BY 'canal'; -- 授权 *.*表示所有库 grant SELECT, REPLICATION SLAVE, REPLICATION CLIENT on *.* to 'canal'@'%'; #刷新权限 FLUSH PRIVILEGES;
2.下载canal
Canal仓库地址 : https://github.com/alibaba/canal/releases
下载后解压得到如图所示结构
============= 修改Canal的配置文件 =============
1). 修改instance 配置文件 : conf/example/instance.properties
# 按需修改成自己的数据库信息 ################################################# canal.instance.master.address=192.168.1.20:3306 # username/password,数据库的用户名和密码 ... #刚才开通的mysql的账户密码 canal.instance.dbUsername = canal canal.instance.dbPassword = canal ... ################################################# # mq config 数据同步到MQ中的topic名字 canal.mq.topic=example # 针对库名或者表名发送动态topic #canal.mq.dynamicTopic=mytest,.*,mytest.user,mytest\..*,.*\..* canal.mq.partition=0 # hash partition config #canal.mq.partitionsNum=3 #库名.表名: 唯一主键,多个表之间用逗号分隔 #canal.mq.partitionHash=mytest.person:id,mytest.role:id
需要修改部分列出:
master.address :Mysql的地址,我的端口是3307,默认是3306
dbUsername :上面开通的Mysql用户
dbPassword : 密码
canal.mq.topic=example : 数据同步到MQ中的topic名字
2).修改canal 配置文件 conf/canal.properties
# ... # 可选项: tcp(默认) tcp, kafka, rocketMQ, rabbitMQ # 这里使用rabbitMQ canal.serverMode = rabbitMQ ################################################## ######### RabbitMQ ############# ################################################## # rabbitMQ所在主机地址 rabbitmq.host = 192.168.241.128 rabbitmq.virtual.host =/ # 交换机 rabbitmq.exchange =canal.exchange # 用户名 rabbitmq.username =admin # 密码 rabbitmq.password =admin rabbitmq.deliveryMode =
需修改部分
canal.serverMode = rabbitMQ: 我这里以rabbitMQ为例
rabbitmq.host
rabbitmq.exchange
rabbitmq.username
rabbitmq.password
修改完毕后,启动canal,找到bin/startup.cmd 启动canal
3.RabbitMQ队列创建
添加交换机 canal.exchange
添加队列 canal.queue
队列绑定交换机
4.SpringBoot项目中集成 Canal + RabbitMQ
所需依赖
<!--canal依赖-->
<dependency>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal.client</artifactId>
<version>1.1.3</version>
</dependency>
<!---rabbitMQ依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
rabbitmq配置
spring: rabbitmq: host: x.youlai.tech port: 5672 username: guest password: guest
监听器内容如下,具体可根据业务需求进行调整
@Component
@Slf4j
@RequiredArgsConstructor
public class CanalListener {
@RabbitListener(bindings = {
@QueueBinding(
value = @Queue(value = "canal.queue", durable = "true"),
exchange = @Exchange(value = "canal.exchange"),
key = "canal.routing.key"
)
})
public void handleDataChange(String message) {
log.info("Canal 监听内容:{}", message);
}
}