微服务架构-分布式解决方案-110:基于canal整合kafka异步解决数据一致性的问题

1 canal整合kafka的效果演示

课题内容

  1. 简单回顾canal基本实现原理
  2. windows环境快速搭建kafka+Zookeeper环境
  3. canal快速整合kafka异步实现保证数据一致性

canal的实现原理基本总结
canal会启动一个Server端作为一个mysql从节点拉取mysql主节点最新的binlog文件,只要mysql主节点的binlog文件发生变化都会以增量的形式通知给canalServer端,canalServer再通知给canalClient,canalClient自己手动配置刷新Redis接口。

2 构建zookeeper环境

canal目前支持三种监听通讯模式 tcp/kafka/rocketmq

安装zookeeper(当前服务器已有java环境)

  1. 解压zk压缩包(zookeeper-3.4.14.tar.gz),进入conf目录,将zoo_sample.cfg修改为 zoo.cfg;
  2. conf同级目录创建文件夹data,修改 zoo.cfg 中的dataDir=xx\xx\data(创建的data文件夹目录)
  3. 新增环境变量:
    ZOOKEEPER_HOME: D:\devtool\zookeeper (zookeeper目录)
    Path: 在现有的值后面添加 “;%ZOOKEEPER_HOME%\bin;”
    运行zk,双击bin目录下文件zkServer.cmd
    在这里插入图片描述

3 构建kafka的环境

安装kafka

  1. 解压kafka安装包(kafka_2.13-2.4.0)改名为 kafka(名称太长运行可能报错)
  2. config同级目录新建文件夹logs,修改\config\server.properties中的配置
    log.dirs= D:\devtool\kafka\logs
  3. 进入到kafka安装目录,执行命令
    .\bin\windows\kafka-server-start.bat .\config\server.properties
    在这里插入图片描述

4 canal将消息异步投递到kafka中

修改canal\conf\example\instance.properties文件配置
canal.instance.master.address=127.0.0.1:3306
canal.instance.dbUsername=canal
canal.instance.dbPassword=canal
canal.mq.topic=mayikt-topic
修改canal\conf\canal.properties文件配置
canal.serverMode = kafka
canal.mq.servers = 127.0.0.1:9092

5 消费者整合kafka获取消息

@KafkaListener(topics = "mayikt-topic")
public void receive(ConsumerRecord<?, ?> consumer) {
    System.out.println("topic名称:" + consumer.topic() + ",key:" +
            consumer.key() + "," +
            "分区位置:" + consumer.partition()
            + ", 下标" + consumer.offset() + "," + consumer.value());

    String json = (String) consumer.value();
    JSONObject jsonObject = JSONObject.parseObject(json);
    String sqlType = jsonObject.getString("type");
    JSONArray data = jsonObject.getJSONArray("data");
    JSONObject userObject = data.getJSONObject(0);
    String id = userObject.getString("id");
    String database = jsonObject.getString("database");
    String table = jsonObject.getString("table");
    String key = database + "_" + table + "_" + id;
    if ("UPDATE".equals(sqlType) || "INSERT".equals(sqlType)) {
        redisUtils.setString(key, userObject.toJSONString());
        return;
    }
    if ("DELETE".equals(sqlType)) {
        redisUtils.deleteKey(key);
    }
}

测试效果:
在这里插入图片描述

6 canal异步json消息的原理分析

如果是批量插入一次性commit的情况下,data的数据可能是一个数组的形式,需要注意循环遍历批量同步到redis中。
Begin
Insert Insert Insert Update Update
Commit
Kafka推送两条消息 Insert类型消息(data数组长度3)、Update类型消息(data数组长度2)

Ps:conf下自配置文件夹(类似example)下的h2.mv.db是canal缓存数据库结构的文件,如果数据库表有变动可能canal启动后同步不了数据或者字段错位,删除h2.mv.db和meta.dat文件后重启canal即可。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值