开启MySQL binlog功能
cd /home/mysql8/conf
vim my.cnf
[mysqld]
log-bin=/var/lib/mysql/mysql-bin # 开启 binlog
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));
}
}
}