文章目录
- 一、Canal服务
- 1. mysql添加canal用户
- 2. mysql配置文件
- 3. canal配置文件
- 二、引入依赖
- 三、监听Canal消息
- 四、运行
- 五、测试
通过本文章,可以完成多级缓存架构中的缓存同步。
一、Canal服务
1. mysql添加canal用户
连接在上一次multiCache
项目中运行的mysql
容器,创建canal
用户。
CREATE USER canal IDENTIFIED BY 'canal';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
-- GRANT ALL PRIVILEGES ON *.* TO 'canal'@'%' ;
FLUSH PRIVILEGES;
2. mysql配置文件
在docker/mysql/conf/my.cnf
添加如下配置
server-id=1000
log-bin=/var/lib/mysql/mysql-bin
binlog-do-db=heima
binlog_format=row
3. canal配置文件
添加canal
服务块到docker-compose.yml
,如下
canal:container_name: canalimage: canal/canal-server:v1.1.7volumes:- ./canal/logs:/home/admin/canal-server/logs- ./canal/conf:/home/admin/canal-server/confports:- "11111:11111"depends_on:- mysqlnetworks:multi-cache:ipv4_address: 172.30.3.7
docker pull canal/canal-server:v1.1.7
任意启动一个canal-server
容器,将里面的/home/admin/canal-server/conf
文件夹复制到宿主机,对应docker/canal/conf
文件夹。
删除此临时容器。
修改docker/canal/conf/canal.properties
如下条目
canal.destinations=example
canal.instance.tsdb.enable=true
修改docker/canal/conf/example/instance.properties
如下条目
canal.instance.master.address=172.30.3.2:3306
canal.instance.dbUsername=canal
canal.instance.dbPassword=canal
canal.instance.connectionCharset = UTF-8
canal.instance.tsdb.enable=true
canal.instance.gtidon=false
canal.instance.filter.regex=heima\\..*
二、引入依赖
pom.xml
<dependency><groupId>top.javatool</groupId><artifactId>canal-spring-boot-starter</artifactId><version>1.2.1-RELEASE</version></dependency>
application.yml
canal:destination: exampleserver: 172.30.3.7:11111
三、监听Canal消息
这是canal-spring-boot-starter
官方仓库,含使用文档
新建canal.ItemHandler
类,内容如下
package com.heima.item.canal;import com.github.benmanes.caffeine.cache.Cache;
import com.heima.item.config.RedisHandler;
import com.heima.item.pojo.Item;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import top.javatool.canal.client.annotation.CanalTable;
import top.javatool.canal.client.handler.EntryHandler;@CanalTable(value = "tb_item")
@Component
public class ItemHandler implements EntryHandler<Item> {@Autowiredprivate RedisHandler redisHandler;@Autowiredprivate Cache<Long, Item> itemCache;@Overridepublic void insert(Item item) {itemCache.put(item.getId(), item);redisHandler.saveItem(item);}@Overridepublic void update(Item before, Item after) {itemCache.put(after.getId(), after);redisHandler.saveItem(after);}@Overridepublic void delete(Item item) {itemCache.invalidate(item.getId());redisHandler.deleteItemById(item.getId());}
}
修改pojo.Item
类,如下
package com.heima.item.pojo;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;import java.util.Date;@Data
@TableName("tb_item")
public class Item {@TableId(type = IdType.AUTO)@Idprivate Long id;//商品idprivate String name;//商品名称private String title;//商品标题private Long price;//价格(分)private String image;//商品图片private String category;//分类名称private String brand;//品牌名称private String spec;//规格private Integer status;//商品状态 1-正常,2-下架private Date createTime;//创建时间private Date updateTime;//更新时间@TableField(exist = false)@Transientprivate Integer stock;@TableField(exist = false)@Transientprivate Integer sold;
}
四、运行
到此为止,docker-compose.yml
内容应该如下
version: '3.8'networks:multi-cache:driver: bridgeipam:driver: defaultconfig:- subnet: 172.30.3.0/24services:mysql:container_name: mysqlimage: mysql:8volumes:- ./mysql/conf/my.cnf:/etc/mysql/conf.d/my.cnf- ./mysql/data:/var/lib/mysql- ./mysql/logs:/logsports:- "3306:3306"environment:- MYSQL_ROOT_PASSWORD=1009networks:multi-cache:ipv4_address: 172.30.3.2nginx:container_name: nginximage: nginx:stablevolumes:- ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf- ./nginx/conf/conf.d/default.conf:/etc/nginx/conf.d/default.conf- ./nginx/dist:/usr/share/nginx/distports:- "8080:8080"networks:multi-cache:ipv4_address: 172.30.3.3canal:container_name: canalimage: canal/canal-server:v1.1.7volumes:- ./canal/logs:/home/admin/canal-server/logs- ./canal/conf:/home/admin/canal-server/confports:- "11111:11111"depends_on:- mysqlnetworks:multi-cache:ipv4_address: 172.30.3.7openresty1:container_name: openresty1image: openresty/openresty:1.21.4.3-3-jammy-amd64volumes:- ./openresty1/conf/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf- ./openresty1/conf/conf.d/default.conf:/etc/nginx/conf.d/default.conf- ./openresty1/lua:/usr/local/openresty/nginx/lua- ./openresty1/lualib/common.lua:/usr/local/openresty/lualib/common.luanetworks:multi-cache:ipv4_address: 172.30.3.11redis:container_name: redisimage: redis:7.2volumes:- ./redis/redis.conf:/usr/local/etc/redis/redis.confports:- "6379:6379"command: [ "redis-server", "/usr/local/etc/redis/redis.conf" ]networks:multi-cache:ipv4_address: 172.30.3.21
删除原来的multiCache
,重新启动各项服务。
docker-compose -p multi-cache up -d
启动springboot
程序。
五、测试
springboot
不断输入类似如下日志,属于正常监听canal
消息中。
09:27:17:175 INFO 1 --- [l-client-thread] t.j.c.client.client.AbstractCanalClient : 获取消息 Message[id=-1,entries=[],raw=false,rawEntries=[]]
09:27:18:177 INFO 1 --- [l-client-thread] t.j.c.client.client.AbstractCanalClient : 获取消息 Message[id=-1,entries=[],raw=false,rawEntries=[]]
09:27:19:178 INFO 1 --- [l-client-thread] t.j.c.client.client.AbstractCanalClient : 获取消息 Message[id=-1,entries=[],raw=false,rawEntries=[]]
访问http://localhost:8081/item/10001
,此时信息为tomcat
查询数据库所得数据,而后存入Caffeine
缓存。
访问http://localhost:8080/item.html?id=10001
,此时信息为Redis
缓存数据。
然后,
访问http://localhost:8081/
来到商品管理页面。
修改id=10001的数据的商品分类
确认后
springboot日志出现类似如下日志
09:31:29:234 INFO 1 --- [l-client-thread] t.j.c.client.client.AbstractCanalClient : 获取消息 Message[id=1,entries=[header {version: 1logfileName: "binlog.000007"logfileOffset: 236serverId: 1serverenCode: "UTF-8"executeTime: 1705051889000sourceType: MYSQLschemaName: ""tableName: ""eventLength: 93
}
entryType: TRANSACTIONBEGIN
storeValue: " \r"
, header {version: 1logfileName: "binlog.000007"logfileOffset: 411serverId: 1serverenCode: "UTF-8"executeTime: 1705051889000sourceType: MYSQLschemaName: "heima"tableName: "tb_item"eventLength: 626eventType: UPDATEprops {key: "rowsCount"value: "1"}
}
entryType: ROWDATA
storeValue: "\bV\020\002P\000b\332\n\n&\b\000\020\373\377\377\377\377\377\377\377\377\001\032\002id \001(\0000\000B\00510001R\006bigint\nd\b\001\020\f\032\005title \000(\0000\000BCRIMOWA 21\345\257\270\346\211\230\350\277\220\347\256\261\346\213\211\346\235\206\347\256\261 SALSA AIR\347\263\273\345\210\227\346\236\234\347\273\277\350\211\262 820.70.36.4R\fvarchar(264)\n)\b\002\020\f\032\004name \000(\0000\000B\tSALSA AIRR\fvarchar(128)\n)\b\003\020\373\377\377\377\377\377\377\377\377\001\032\005price \000(\0000\000B\00516900R\006bigint\n\226\001\b\004\020\f\032\005image \000(\0000\000Buhttps://m.360buyimg.com/mobilecms/s720x720_jfs/t6934/364/1195375010/84676/e9f2c55f/597ece38N0ddcbc77.jpg!q70.jpg.webpR\fvarchar(200)\n0\b\005\020\f\032\bcategory \000(\0000\000B\f\346\213\211\346\235\206\347\256\261777R\fvarchar(200)\n\'\b\006\020\f\032\005brand \000(\0000\000B\006RIMOWAR\fvarchar(100)\nG\b\a\020\f\032\004spec \000(\0000\000B\'{\"\351\242\234\350\211\262\": \"\347\272\242\350\211\262\", \"\345\260\272\347\240\201\": \"26\345\257\270\"}R\fvarchar(200)\n\032\b\b\020\004\032\006status \000(\0000\000B\0011R\003int\n6\b\t\020]\032\vcreate_time \000(\0000\000B\0232019-05-01 00:00:00R\bdatetime\n6\b\n\020]\032\vupdate_time \000(\0000\000B\0232019-05-01 00:00:00R\bdatetime\022&\b\000\020\373\377\377\377\377\377\377\377\377\001\032\002id \001(\0000\000B\00510001R\006bigint\022d\b\001\020\f\032\005title \000(\0000\000BCRIMOWA 21\345\257\270\346\211\230\350\277\220\347\256\261\346\213\211\346\235\206\347\256\261 SALSA AIR\347\263\273\345\210\227\346\236\234\347\273\277\350\211\262 820.70.36.4R\fvarchar(264)\022)\b\002\020\f\032\004name \000(\0000\000B\tSALSA AIRR\fvarchar(128)\022)\b\003\020\373\377\377\377\377\377\377\377\377\001\032\005price \000(\0000\000B\00516900R\006bigint\022\226\001\b\004\020\f\032\005image \000(\0000\000Buhttps://m.360buyimg.com/mobilecms/s720x720_jfs/t6934/364/1195375010/84676/e9f2c55f/597ece38N0ddcbc77.jpg!q70.jpg.webpR\fvarchar(200)\0220\b\005\020\f\032\bcategory \000(\0010\000B\f\346\213\211\346\235\206\347\256\261888R\fvarchar(200)\022\'\b\006\020\f\032\005brand \000(\0000\000B\006RIMOWAR\fvarchar(100)\022G\b\a\020\f\032\004spec \000(\0000\000B\'{\"\351\242\234\350\211\262\": \"\347\272\242\350\211\262\", \"\345\260\272\347\240\201\": \"26\345\257\270\"}R\fvarchar(200)\022\032\b\b\020\004\032\006status \000(\0000\000B\0011R\003int\0226\b\t\020]\032\vcreate_time \000(\0000\000B\0232019-05-01 00:00:00R\bdatetime\0226\b\n\020]\032\vupdate_time \000(\0000\000B\0232019-05-01 00:00:00R\bdatetime"
],raw=false,rawEntries=[]]
09:31:30:572 INFO 1 --- [l-client-thread] t.j.c.client.client.AbstractCanalClient : 获取消息 Message[id=2,entries=[header {version: 1logfileName: "binlog.000007"logfileOffset: 1037serverId: 1serverenCode: "UTF-8"executeTime: 1705051889000sourceType: MYSQLschemaName: ""tableName: ""eventLength: 31
}
entryType: TRANSACTIONEND
storeValue: "\022\00287"
],raw=false,rawEntries=[]]
这里可以先用redis
连接工具查询数据,发现rediis
已被更新。
再次访问http://localhost:8081/item/10001
直接向springboot
的controller
发送请求,发现caffeine
数据更新,并且springboot
日志没有出现查询记录,说明走的是caffeine
。