个人名片:
博主:酒徒ᝰ.
个人简介:沉醉在酒中,借着一股酒劲,去拼搏一个未来。
本篇励志:三人行,必有我师焉。
本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》,SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
【SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 点击观看
目录
五、缓存同步
3. 监听Canal
Canal提供了各种语言的客户端,当Canal监听到binlog变化时,会通知Canal的客户端。
我们可以利用Canal提供的Java客户端,监听Canal通知消息。当收到变化的消息时,完成对缓存的更新。
不过这里我们会使用GitHub上的第三方开源的canal-starter客户端。地址:https://github.com/NormanGyllenhaal/canal-client
与SpringBoot完美整合,自动装配,比官方客户端要简单好用很多。
- 引入依赖:
<dependency>
<groupId>top.javatool</groupId>
<artifactId>canal-spring-boot-starter</artifactId>
<version>1.2.1-RELEASE</version>
</dependency>
- 编写配置:
canal:
destination: heima # canal的集群名字,要与安装canal时设置的名称一致
server: 192.168.179.128:11111 # canal服务地址
- 修改Item实体类
通过@Id、@Column、等注解完成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 javax.persistence.Column;
import java.util.Date;
@Data //自动生成getter, setter, toString等方法
@TableName("tb_item") //对应的数据库表名
public class Item {
@TableId(type = IdType.AUTO)
@Id //主键
private Long id;//商品id
@Column(name = "name") //对应数据库表中的name属性
private 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) //该字段在数据库表item中不存在
@Transient //该字段不需要持久化到数据库
private Integer stock;
@TableField(exist = false)
@Transient
private Integer sold;
}
- 编写监听器
通过实现
EntryHandler<T>
接口编写监听器,监听Canal消息。注意两点:
- 实现类通过
@CanalTable("tb_item")
指定监听的表信息- EntryHandler的泛型是与表对应的实体类
在Redis中操作类RedisHandler中添加Redis中增加和删除操作:
/**
* 新增数据
* @param item
*/
public void saveItem(Item item) {
try {
String json = MAPPER.writeValueAsString(item);
redisTemplate.opsForValue().set("item:id:" + item.getId(), json);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
/**
* 删除数据
* @param id
*/
public void deleteById(Long id) {
redisTemplate.delete("item:id:" + id);
}
编写监听器
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("tb_item") //监听tb_item表
@Component
public class ItemHandler implements EntryHandler<Item> {
@Autowired
private RedisHandler redisHandler;
@Autowired
private Cache<Long, Item> itemCache;
@Override
public void insert(Item item) {
//写数据到JVM进程缓存
itemCache.put(item.getId(), item);
//写数据到Redis
redisHandler.saveItem(item);
}
@Override
public void update(Item before, Item after) {
itemCache.put(after.getId(), after);
redisHandler.saveItem(after);
}
@Override
public void delete(Item item) {
//删除JVM进程缓存中的数据
itemCache.invalidate(item.getId());
//删除Redis中的数据
redisHandler.deleteById(item.getId());
}
}
重启项目:
访问:
http://localhost:8081/item/10003
访问:
http://localhost:8081/
修改ID为10003的商品信息
刷新第一个访问的页面,修改同步完成
查看Redis,也完成了修改
本文含有隐藏内容,请 开通VIP 后查看