canal1.1.8+mysql8.0+jdk17+redis的使用

文章目录

一、Canal

在工作中,我们常常会遇到同步MySQL数据到Redis的需求,我们也会有很多种方式去解决,常见的方式有如下几种

  • 业务操作中同步
  • 使用消息队列
  • 基于binlog方式

基于binlog方式

其中Mysql主从工作原理:

Mysql主从,根据2/8原则,80%的性能问题都在读上面,当我们数据库的读并发较大的时候,我们可以使用Mysql主从来分担读的压力。它的原理是所有的写操作在主库上,读操作在从库上,当然主库也可以承担读请求,而从库的数据则通过主库复制而来。

  • MySQL master 将数据变更写入二进制日志( binary log, 其中记录叫做二进制日志事件binary log events,可以通过 show binlog events 进行查看)
  • MySQL slave 将 master 的 binary log events 拷贝到它的中继日志(relay log)
  • MySQL slave 重放 relay log 中事件,将数据变更反映它自己的数据

主从复制步骤:

  1. 将Master的binary-log日志文件打开,mysql会把所有的DDL,DML,TCL写入BinaryLog日志文件中
  2. Master会生成一个 log dump 线程,用来给从库的 i/o线程传binlog
  3. 从库的i/o线程去请求主库的binlog,并将得到的binlog日志写到中继日志(relaylog)中
  4. 从库的sql线程,会读取relaylog文件中的日志,并解析成具体操作,通过主从的操作一致,而达到最终数据一致
  5. 而Canal的工作原理就是伪装成mysql的从库去获取Binlog中SQL语句再更新到Redis。

二、前期准备

2.1 检查MySQL是否开启binlog

binlog是二进制日志文件,用于记录mysql的数据变更,数据在恢复的时候binlog日志起着至关重要的作用

sql 复制代码
#cmd打开命令提示符
#输入该代码登录mysql
mysql -u root -p
#执行命令查看 binlog 状态 Value 为 ON,则表示 binlog 已开启
SHOW VARIABLES LIKE 'log_bin';
#执行命令查看 binlog 格式 如果 Value 为 ROW,则表示 binlog 格式为 ROW,这是 Canal 正常工
作所必需的格式
SHOW VARIABLES LIKE 'binlog_format';

若没有开启binlog,则需要进行配置,配置步骤如下:

找到my.ini文件,默认位置: C:\ProgramData\MySQL\MySQL Server 8.0

如果在安装MySQL时使用的是自定义安装,请看你安装位置的文件中的my.ini文件

bash 复制代码
#在mysqld下面添加
server_id=1918
log_bin = mysql-bin
binlog_format = ROW

重启MySQL服务,并查看是否开启binlog,查看方式同上

创建用户,方便后续测试

bash 复制代码
# 使用命令登录: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;

执行完上面的语句后查看所有用户

bash 复制代码
select * from mysql.user;

2.2 下载canal

Canal仓库地址 : https://github.com/alibaba/canal/releases

解压后文件目录:

2.2 修改Canal的配置文件

修改instance.properties

修改instance 配置文件 : conf/example/instance.properties

bash 复制代码
# 按需修改成自己的数据库信息
#################################################
canal.instance.master.address=127.0.0.1:3380
# username/password,数据库的用户名和密码
...
#刚才开通的mysql的账户密码
canal.instance.dbUsername = canal
canal.instance.dbPassword = canal

.......
# table regex 将canal.instance.filter.regex=.*\\..* 改为 canal.instance.filter.regex=canaldb\\..*
canal.instance.filter.regex=canaldb\\..*

...
#################################################
# mq config 数据同步到MQ中的topic名字
canal.mq.topic=canal.exchange
# 添加账号密码
canal.mq.username=guest
canal.mq.password=guest
# 针对库名或者表名发送动态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

修改canal.properties

修改canal 配置文件 conf/canal.properties

bash 复制代码
canal.ip = 0.0.0.0
# register ip to zookeeper
canal.register.ip = 127.0.0.1
# 添加下面这一条 确保实例加载配置正确(默认加载 conf 目录下的所有实例文件夹)
canal.destinations = example  

# ...
# 可选项: tcp(默认) tcp, kafka, rocketMQ, rabbitMQ
# 这里使用rabbitMQ
canal.serverMode = tcp
##################################################
######### RabbitMQ #############
##################################################
# rabbitMQ所在主机地址
rabbitmq.host = 127.0.0.1:5672
rabbitmq.virtual.host = /
# 交换机
rabbitmq.exchange = canal.exchange
# 用户名
rabbitmq.username = guest
# 密码
rabbitmq.password = guest
rabbitmq.deliveryMode =

修改startup.bat

修改bin/startup.bat

因为我们使用的Java17 版本过高,不再支持 -XX:PermSize参数。这个参数在 Java 8 及以后版本已被移除。

修改完毕后,启动canal,找到bin/startup.bat 启动canal

2.3 查看canal是否启动

注意:下面三步必须全对才算启动canal成功

  1. 查看logs\canal\canal.log日志是否最近修改时间是你启动的时间。
  2. 查看logs\example\example.log查看是否报错,可以按住Ctrl+F搜一下是否有ERROR,如果没有说明启动成功。
  3. 新打开命令行窗口执行netstat -ano | findstr :11111指令查看是否启动,如果出现以下情况说明启动成功。

2.4 RabbitMQ队列创建

添加交换机 canal.exchange

添加队列 canal.queue

队列绑定交换机

点进去队列

输入canal.exchangecanal.routing.key

三、SpringBoot项目中集成 Canal + RabbitMQ

创建项目

pom文件中引入依赖

xml 复制代码
<!-- Canal 协议依赖 -->
<dependency>
    <groupId>com.alibaba.otter</groupId>
    <artifactId>canal.protocol</artifactId>
    <version>1.1.6</version>
</dependency>

<!-- Canal 公共组件 -->
<dependency>
    <groupId>com.alibaba.otter</groupId>
    <artifactId>canal.common</artifactId>
    <version>1.1.6</version>
</dependency>

<!-- Canal 客户端依赖 -->
<dependency>
    <groupId>com.alibaba.otter</groupId>
    <artifactId>canal.client</artifactId>
    <version>1.1.6</version>
</dependency>

<!-- Spring Boot 核心启动器 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

<!-- Redis  -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- MySQL  -->
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>

<!-- 消息队列 AMQP 支持(如 RabbitMQ) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

<!-- 阿里巴巴 FastJSON2 (JSON处理) -->
<dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
    <version>2.0.31</version>
</dependency>

<!-- 测试依赖(解决 JUnit 和 Spring Boot Test 缺失问题) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

yml配置

yml 复制代码
spring:
    # 数据库连接配置(Canal需要连接数据库获取binlog)
    datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3380/smbms?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8
        username: root  # 数据库用户名(需要有binlog权限)
        password: root  # 数据库密码
    rabbitmq:
        host: 127.0.0.1
        port: 5672
        username: guest
        password: guest
        virtual-host: /
    redis:
        host: 127.0.0.1
        port: 6379
        database: 0
        password: 123456

# Canal客户端配置(监听数据库binlog)
canal:
    client:
        instances:
            example:  # 实例名,可自定义
                host: 192.168.108.13  # Canal Server地址(如果是本地部署的Canal服务)
                port: 11111      # Canal默认端口
                username: canal  # Canal默认用户名
                password: canal  # Canal默认密码
                filter: smbms.*  # 监听的数据库表(格式:库名.表名,*表示所有表)
# 日志配置
logging:
    level:
        com.yak: DEBUG
        org.springframework.amqp: INFO
        com.alibaba.otter.canal: INFO  # 开启Canal日志,方便调试

CanalRabbitMQConsumer

java 复制代码
package com.hsh.canal.listen;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
@Component
public class CanalRabbitMQConsumer {
    @Autowired
    private StringRedisTemplate redisTemplate;
    /**
     * 直接监听Canal通过RabbitMQ发送的消息
     * Canal会直接将binlog数据发送到配置的exchange中
     */
    @RabbitListener(queues = "canal.queues")
    public void processCanalMessage(String message) {
        System.out.println("收到CALAL数据: " + message);
        // 存储到Redis
        redisTemplate.opsForValue().set("canal:lastChange", message);
        System.out.println("已同步到Redis: " + message);
        // 这里可以添加具体的业务处理逻辑
        // 比如解析JSON、更新缓存、同步到其他系统等
    }
}

RabbitConfig

java 复制代码
package com.hsh.canal.config;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitConfig {
    @Bean
    public Queue canalSyncQueue() {
        return new Queue("canal.queues", true);
    }
    @Bean
    public DirectExchange canalExchange() {
        return new DirectExchange("canal.exchange", true, false);
    }

    // 修改绑定,使用空路由键
    @Bean
    public Binding bindingCanalQueue(Queue canalSyncQueue, DirectExchange
            canalExchange) {
        return BindingBuilder.bind(canalSyncQueue)
                .to(canalExchange)
                .with(""); // 改为空路由键,匹配所有消息
    }
}

我这demo只要运行起来不报错说明canal能用,但是没有说canal怎么用,我会在另一篇帖子说明。

相关推荐
00后程序员张2 小时前
混淆 iOS 类名与变量名的实战指南,多工具组合把混淆做成工程能力(混淆 iOS 类名变量名/IPA 成品混淆Ipa/Guard CLI 实操)
android·ios·小程序·https·uni-app·iphone·webview
介一安全3 小时前
【Frida Android】实战篇1:环境准备
android·网络安全·逆向·frida
许愿OvO4 小时前
MySQL触发器
android·mysql·adb
循环不息优化不止4 小时前
Jetpack Compose 从重组到副作用的全方位解析
android
2501_916007476 小时前
iOS文件管理工具深度剖析,从系统沙盒到跨平台文件操作的多工具协同实践
android·macos·ios·小程序·uni-app·cocoa·iphone
Android疑难杂症6 小时前
鸿蒙Notification Kit通知服务开发快速指南
android·前端·harmonyos
lcanfly6 小时前
Mysql作业5
android·数据库·mysql
MuYiLuck7 小时前
redis持久化与集群
java·数据库·redis
埃泽漫笔8 小时前
Redis性能优化避坑指南
redis