Canal实现0侵入同步缓存数据

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: Canal实现0侵入同步缓存数据

开启MySQL binlog功能

cd /home/mysql8/conf

vim my.cnf

[mysqld]
log-bin=/var/lib/mysql/mysql-bin # 开启 binlog,这里路径来自Docker安装mysql的时,挂载目录是/var/lib/mysql
binlog-format=ROW # 选择 ROW 模式
server_id=1 # 配置 MySQL replaction 需要定义,不要和 canal 的 slaveId 重复
binlog-do-db=imooc-hire-dev # 配置binlog给哪个数据库使用,可以配多个

重启MySQL:

docker restart mysql

检测binlog是否开启:

Docker安装Canal

docker pull canal/canal-server:v1.1.6
docker run -p 11111:11111 --name canal -e canal.destinations=imooc -e canal.instance.mysql.slaveId=20231111 -e canal.instance.master.address=192.168.233.128:3306 -e canal.instance.dbUsername=root -e canal.instance.dbPassword=Admin~123456 -e canal.instance.connectionCharset=UTF-8 -e canal.instance.filter.regex=imooc-hire-dev.data_dictionary --restart=always -d canal/canal-server:v1.1.6

canal.destinations=imooc表示起个名字跟后面的yml中对应上即可;

canal.instance.master.address=192.168.233.128:3306表示监听的数据库ip和端口;

canal.instance.filter.regex=imooc-hire-dev.data_dictionary表示的是监听imooc-hire-dev库的data_dictionary表,可以逗号分隔,监听多张表;

canal.instance.dbUsername=root -e canal.instance.dbPassword=Admin~123456表示被监听的数据库账号密码;

查看是否启动成功:

docker exec -it canal bash
cd canal-server/logs/imooc
vi imooc.log

不报错就对了。

SpringBoot集成Canal实现0侵入缓存同步

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

yml

canal:
  destination: imooc
  server: 192.168.233.128:11111
  user-name: canal
  password: canal
logging:
  level:
    top.javatool.canal.client: warn
package com.imooc.canal;
import com.imooc.base.BaseInfoProperties;
import com.imooc.pojo.DataDictionary;
import com.imooc.pojo.co.DataDictionaryCO;
import com.imooc.utils.GsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import top.javatool.canal.client.annotation.CanalTable;
import top.javatool.canal.client.handler.EntryHandler;
import java.util.ArrayList;
import java.util.List;
@CanalTable("data_dictionary")      // 指定监听的表名
@Component
public class DataDictSyncHelper extends BaseInfoProperties
        implements EntryHandler<DataDictionaryCO> // 指定表关联的实体对象(javabean)
{
    private static final String DDKEY_PREFIX = DATA_DICTIONARY_LIST_TYPECODE + ":";
    @Override
    public void insert(DataDictionaryCO dataDictionary) {
        String ddkey = DDKEY_PREFIX + dataDictionary.getType_code();
        // 先查询redis中是否存在该数据字典list
        String ddListStr = redis.get(ddkey);
        List<DataDictionary> redisDDList = null;
        if (StringUtils.isBlank(ddListStr)) {
            // 如果不存在,则直接new一个list,添加并存入到redis中即可
            redisDDList = new ArrayList<>();
        } else {
            // 如果redis中存在该list,则直接在缓存的list中新增即可
            redisDDList = GsonUtils.stringToListAnother(ddListStr,
                                                        DataDictionary.class);
        }
        // 转换对象并且塞入list
        DataDictionary pendingDictionary = convertDD(dataDictionary);
        redisDDList.add(pendingDictionary);
        redis.set(ddkey, GsonUtils.object2String(redisDDList));
    }
    private DataDictionary convertDD(DataDictionaryCO dataDictionaryCO) {
        DataDictionary pendingDictionary = new DataDictionary();
        BeanUtils.copyProperties(dataDictionaryCO, pendingDictionary);
        pendingDictionary.setTypeCode(dataDictionaryCO.getType_code());
        pendingDictionary.setTypeName(dataDictionaryCO.getType_name());
        pendingDictionary.setItemKey(dataDictionaryCO.getItem_key());
        pendingDictionary.setItemValue(dataDictionaryCO.getItem_value());
        return pendingDictionary;
    }
    @Override
    public void update(DataDictionaryCO before, DataDictionaryCO after) {
        String ddkey = DDKEY_PREFIX + after.getType_code();
        // 先查询redis中是否存在该数据字典list
        String ddListStr = redis.get(ddkey);
        List<DataDictionary> redisDDList = null;
        if (StringUtils.isBlank(ddListStr)) {
            // 如果不存在,啥都不要干
        } else {
            // 如果redis中存在该list,则直接在缓存的list中修改对应的数据字典项就行,再重置缓存
            redisDDList = GsonUtils.stringToListAnother(ddListStr,
                                                        DataDictionary.class);
            for (DataDictionary dd : redisDDList) {
                if (dd.getId().equalsIgnoreCase(after.getId())) {
                    DataDictionary pendingDictionary = convertDD(after);
                    redisDDList.remove(dd);
                    redisDDList.add(pendingDictionary);
                    break;
                }
            }
            redis.set(ddkey, GsonUtils.object2String(redisDDList));
        }
    }
    @Override
    public void delete(DataDictionaryCO dataDictionary) {
        String ddkey = DDKEY_PREFIX + dataDictionary.getType_code();
        // 先查询redis中是否存在该数据字典list
        String ddListStr = redis.get(ddkey);
        List<DataDictionary> redisDDList = null;
        if (StringUtils.isBlank(ddListStr)) {
            // 如果不存在,啥都不要干
        } else {
            // 如果redis中存在该list,则直接在缓存的list中删除该数据字典项就行,再重置缓存
            redisDDList = GsonUtils.stringToListAnother(ddListStr,
                                                        DataDictionary.class);
            for (DataDictionary dd : redisDDList) {
                if (dd.getId().equalsIgnoreCase(dataDictionary.getId())) {
                    redisDDList.remove(dd);
                    break;
                }
            }
            redis.set(ddkey, GsonUtils.object2String(redisDDList));
        }
    }
}


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
9天前
|
存储 缓存 分布式计算
亿级数据如何分钟级别写入缓存?
亿级数据如何分钟级别写入缓存?
32 0
|
9天前
|
缓存 JavaScript
vue使用localStorage缓存数据
vue使用localStorage缓存数据
|
9天前
|
缓存
详解CentOS8更换yum源后出现同步仓库缓存失败的问题
详解CentOS8更换yum源后出现同步仓库缓存失败的问题
161 0
|
9天前
|
缓存 NoSQL 算法
17- 数据库有1000万数据 ,Redis只能缓存20w数据, 如何保证Redis中的数据都是热点数据 ?
保证Redis中的20w数据为热点数据,可以通过设置Redis的LFU(Least Frequently Used)淘汰策略。这样,当数据库有1000万数据而Redis仅能缓存20w时,LFU会自动移除使用频率最低的项,确保缓存中的数据是最常使用的。
69 8
|
4天前
|
消息中间件 缓存 监控
中间件如果缓存中存在所需的数据(缓存命中)
【5月更文挑战第12天】中间件如果缓存中存在所需的数据(缓存命中)
24 3
|
4天前
|
存储 缓存 监控
|
8天前
|
存储 缓存 JavaScript
vue中缓存页面数据(刷新不丢失)
vue中缓存页面数据(刷新不丢失)
|
9天前
|
存储 缓存 NoSQL
数据缓存,可以尝试用RocksDB了
`shigen`,一个专注于Java、Python、Vue和Shell的博主,探讨了为何在学习阿里云DRM产品时选择RocksDB而非Redis或Guava。RocksDB是一个高速、可配置的存储系统,适用于Flash和HDFS,支持数据压缩。与Redis相比,RocksDB在高速存储和灵活性上更具优势。在尝试使用RocksDB与SpringBoot集成时遇到问题,目前尚未解决。他还对比了RocksDB、Redis和Guava Cache的特性,强调RocksDB适合大规模、高性能场景,而Redis适合内存存储和实时性需求。
20 0
数据缓存,可以尝试用RocksDB了
|
9天前
|
存储 缓存 NoSQL
Redis入门到通关之Redis缓存数据实战
Redis入门到通关之Redis缓存数据实战
25 0