本文主要围绕同步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);
}
}