缓存同步的常见方式

  • 设置有效期
    • 给缓存社会有效期,到期删除,再来查询,就查数据库,在放入缓存
  • 同步双写
    • 修改DB时,同步修改DB
  • 异步通知
    • 修改DB时,发送事件通知
    • 比如:MQ、Canal

上面场景,只要不傻都知道。各有优势,我就不说了,本文介绍Canal

什么是Canal 需要JDK

Canal主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费

Cnanl地址:https://github.com/alibaba/canal

Canal原理

利用Mysql主从同步机制来实现的。

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

canal 工作原理

  • canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
  • MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
  • canal 解析 binary log 对象(原始为 byte 流)

Canal 伪装成slave节点,监听master binary log的变化。将此信息发送到Canal客户端中。就完成了异步通知了!

修改Mysql配置

修改mysql配置,配置文件一般就是my.cnf中,不管是啥,只要是[mysqld]就行了

[mysqld]
# 这是指定服务编号,我怕你重启报错,建议加上吧!
server-id= 1
# 指定binlog日志名称,傻逼mysql有些文件夹不允许随便指定,error.log说了没文件,创建了文件也不行,去他妈的!
log-bin=/var/log/mysql/mysql-bin.log
# 指定mysql的binlog日志记录哪个db
binlog-do-db=hello,mysql
binlog-format=ROW # 选择 ROW 模式

重启mysql

systemctl restart mysql

确定重启成功了

systemctl restart mysql

给Canal创建一个配置用户,用于管理,最好限制操作库的权限 参考:https://www.zanglikun.com/4473.html

CREATE USER 'canal'@'%' IDENTIFIED BY 'canal';
GRANT all privileges ON *.* TO 'canal'@'%';
-- 如果你root没有系统用户则不可用使用授权命令 添加身份:grant system_user on *.* to 'root';
-- 不知道是不是有啥问题,反正得要配置一下这个
update `mysql`.`user` SET `plugin` ='mysql_native_password' where User = 'canal';
flush privileges;


Drop User 'canal'@'%';
select Host,User from mysql.user;

查看主从状态

-- 查看主从状态
SHOW MASTER STATUS;

安装Canal

下载:https://github.com/alibaba/canal/releases/tag/canal-1.1.6

建议看官方教程:https://github.com/alibaba/canal/wiki/QuickStart

添加一些配置文件

conf/canal.properties

# tcp bind ip
canal.ip =192.168.31.19

example/instance.properties

## mysql serverId , v1.0.26+ will autoGen 这里说了1.0.26 就不用配置了
# canal.instance.mysql.slaveId=0

# position info
canal.instance.master.address=127.0.0.1:3306
# 配置主从在用的binlog文件名 由执行show master status;得到
canal.instance.master.journal.name=mysql-bin.000006
canal.instance.master.position=157
canal.instance.master.timestamp=
canal.instance.master.gtid=

# username/password 我们刚才创建的就是canal,密码也是
canal.instance.dbUsername=canal
canal.instance.dbPassword=canal
canal.instance.connectionCharset = UTF-8

我当前是Ubuntu,安装JDK8

apt install openjdk-8-jdk

禁用防火墙

systemctl stop firewalld.service


systemctl status firewalld.service 

启动Canal

文件需要执行的权限
./startup.sh

启动完成后,看一下端口是否被占用

lsof -i:11111

如果被占用,说明启动成功!

最好看一下控制台

cat /你的Canal安装路径/logs/canal/canal.log

springboot接入 canal

本次使用是这个:https://github.com/NormanGyllenhaal/canal-client 有其他java库,自行寻找其他也可使用!

        <dependency>
            <groupId>top.javatool</groupId>
            <artifactId>canal-spring-boot-starter</artifactId>
            <version>1.2.1-RELEASE</version>
        </dependency>

配置文件

# Canal 配置信息
#  多个服务地址以逗号隔开
canal.server=192.168.31.34:11111
#  instance名称
canal.destination=example
# 消费时间间隔,单位秒,默认1
canal.timeout=3

监听User表 增、删、改。

import com.zanglikun.springdataredisdemo.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import top.javatool.canal.client.annotation.CanalTable;
import top.javatool.canal.client.handler.EntryHandler;

@Slf4j
@Component
@CanalTable("User") // ① 要监听到表
public class CanalTest implements EntryHandler<User> { // ② 实现接口,指定User,主动重写方法

    @Override
    public void insert(User user) {
        EntryHandler.super.insert(user);
        log.info("插入了数据"+user.toString());
    }

    @Override
    public void update(User before, User after) {
        EntryHandler.super.update(before, after);
        log.info("更新前数据"+before.toString());
        log.info("更新后数据"+after.toString());
    }

    @Override
    public void delete(User user) {
        EntryHandler.super.delete(user);
        System.out.println("执行了");
        log.info("删除了"+user.toString());
    }
}

启动即可

日志会打印出变化,我们后期根据User的变化更新相应的缓存数据即可!

特殊说明:
上述文章均是作者实际操作后产出。烦请各位,请勿直接盗用!转载记得标注原文链接:www.zanglikun.com
第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取全部资料 ❤