黑马点评19——多级缓存-缓存同步

embedded/2024/11/13 9:55:42/

文章目录

  • 数据同步策略
  • 安装Canal
  • 监听canal实现缓存同步
  • 数据库连接遇到问题

在多级缓存中的数据一致性问题,也就是缓存同步的问题

数据同步策略

在这里插入图片描述
在这里插入图片描述
要是使用消息队列的方式,我们还需要修改代码,至少需要发送一条通知吧。
在这里插入图片描述
canal可以监听数据库的变化,监听到数据库的变化,发送通知变更,侵入性更小。

安装Canal

在这里插入图片描述
canal地址: https://github.com/alibaba/canal

在这里插入图片描述
安装和配置参考:https://blog.csdn.net/shall_zhao/article/details/142147266

监听canal实现缓存同步

在这里插入图片描述
但是官方原生提供的canal客户端是比较麻烦的,我们使用第三方开源的整合了springboot的canal客户端。😍

在这里插入图片描述
配置好以后,canal就实现了自动装配。

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

canal:destination: heimaserver: 192.168.10.88:11111

在这里插入图片描述
在这里插入图片描述
然后去我们的Item上添加注解

@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;
}

因为我们在监听到数据库发生变动的时候,只会涉及到保存数据到redis和删除redis中的数据,我们可以把这两个函数封装到RedisHandler中,直接调用。


@Component
public class RedisHandler implements InitializingBean {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Autowiredprivate IItemService itemService;@Autowiredprivate IItemStockService stockService;// spring中的默认json处理工具private static final ObjectMapper MAPPER = new ObjectMapper();// afterPropertiesSet()会在bean创建完,Autowired注入以后执行,实现缓存预热效果@Overridepublic void afterPropertiesSet() throws Exception {// 初始化缓存// 1. 查询商品信息,我们查所有的,实际上应该查询热点数据List<Item> itemList = itemService.list();// 2. 放入缓存for (Item item : itemList) {// 2.1 item序列化为JSONString json = MAPPER.writeValueAsString(item);// 2.2 存入redisstringRedisTemplate.opsForValue().set("item:id:" + item.getId(), json);}// 1. 查询库存信息,List<ItemStock> stockList = stockService.list();// 2. 放入缓存for (ItemStock stock : stockList) {// 2.1 item序列化为JSONString json = MAPPER.writeValueAsString(stock);// 2.2 存入redisstringRedisTemplate.opsForValue().set("item:stock:id:" + stock.getId(), json);}}public void saveItem(Item item){try{String json = MAPPER.writeValueAsString(item);stringRedisTemplate.opsForValue().set("item:id:" + item.getId(), json);} catch (JsonProcessingException e){throw new RuntimeException(e);}}public void deleteItemById(Long id){stringRedisTemplate.delete("item:id:" + id);}
}

然后编写我们的ItemHandler,要实现EntryHandler,重写其三个方法

@CanalTable("tb_item")
@Component
public class ItemHandler implements EntryHandler<Item> {@Autowiredprivate RedisHandler redisHandler;@Autowiredprivate Cache<Long, Item> itemCache;@Overridepublic void insert(Item item) {// 写数据到JVM进程缓存itemCache.put(item.getId(),item);// 写数据到redisredisHandler.saveItem(item);}@Overridepublic void update(Item before, Item after) {// 写数据到JVM进程缓存itemCache.put(after.getId(), after);// 写数据到redisredisHandler.saveItem(after);}@Overridepublic void delete(Item item) {// 删除JVM进程缓存数据itemCache.invalidate(item.getId());// 删除redis数据redisHandler.deleteItemById(item.getId());}
}

数据库连接遇到问题

最后重启项目测试,但是重启的时候遇到一个小问题,关于数据库的,报错内容:“Public Key Retrieval is not allowed”。
还是因为mysql8.0以后的密码验证方式发生变化了。
mysql 8.0 默认使用 caching_sha2_password 身份验证机制 (即从原来mysql_native_password 更改为 caching_sha2_password。)

从 5.7 升级 8.0 版本的不会改变现有用户的身份验证方法,但新用户会默认使用新的 caching_sha2_password 。 客户端不支持新的加密方式。 修改用户的密码和加密方式。
方式一(在这里不建议):
在命令行模式下进入mysql,输入以下命令:

ALTER USER ‘root’@‘localhost’ IDENTIFIED WITH mysql_native_password BY ‘root’;
或者

ALTER USER ‘root’@‘%’ IDENTIFIED WITH mysql_native_password BY ‘root’;
然后就可以正常连接了。

方式二:
可以去直接修改密码验证方式,但这样canal就连不上了。
所以我们采用直接在配置数据源的时候直接将属性allowPublicKeyRetrieval设置为true即可
在这里插入图片描述


http://www.ppmy.cn/embedded/113891.html

相关文章

Java之文件操作和IO

目录 File类 属性 构造方法 方法 文件内容的读写 InputStream OutputStream File类 属性 修饰符及类型属性说明static StringpathSeparator依赖于系统的路径分隔符&#xff0c;String类型的表示static charpathSeparator依赖于系统的路径分隔符&#xff0c;char类型的…

Linux-进程优先级

&#x1f308;个人主页&#xff1a;Yui_ &#x1f308;Linux专栏&#xff1a;Linux &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;数据结构专栏&#xff1a;数据结构 &#x1f308;C专栏&#xff1a;C 文章目录 1. 为什么要有优先级的概念2.进程优先级的基本…

国内外ChatGPT网站集合,无限制使用【2024-09最新】~

经过我一年多以来&#xff0c;使用各种AI工具的体验&#xff0c;我收集了一批AI工具和站点 这些工具都是使用的最强最主流的模型&#xff0c;也都在各个领域里都独领风骚的产品。 而且&#xff0c;这些工具你都可以无限制地使用。 无论你是打工人、科研工作者、学生、文案写…

xml中SQL执行错误(使用另外一张表的两个字段,组装SQL的where查询条件)

SQL实现功能描述&#xff1a;根据系统设置中的商店到期提醒周期、单位&#xff0c;在过期提醒的列表中&#xff0c;对数据进行周期展示 错误复现&#xff1a; Mapper接口中抽象方法的定义如下&#xff1a; Page<ShopVo> queryList(Param(“vo”) ShopVo shopVo ,Page&…

解决内存8G但是需要读取一个几百G的文件到内存的方法

内存映射&#xff08;Memory Mapping&#xff09;提供了一种有效的方法来处理这类问题&#xff0c;通过将文件的一部分或全部映射到进程的虚拟地址空间&#xff0c;使得对文件的访问就像访问内存一样高效。 1. 内存映射的基本概念 内存映射文件是一种将磁盘上的文件与进程的虚…

PDF——压缩大小的方法

方法一&#xff1a;QQ浏览器->格式转换->PDF转纯图PDF

C/C++实现植物大战僵尸(PVZ)(打地鼠版)

&#x1f680;欢迎互三&#x1f449;&#xff1a;程序猿方梓燚 &#x1f48e;&#x1f48e; &#x1f680;关注博主&#xff0c;后期持续更新系列文章 &#x1f680;如果有错误感谢请大家批评指出&#xff0c;及时修改 &#x1f680;感谢大家点赞&#x1f44d;收藏⭐评论✍ 游戏…

【C-项目】网盘(一期,线程池版)

网盘二期 概述 登录服务器后&#xff0c;即可浏览服务器的文件系统。通过命令上传或下载文件。 服务器使用线程池技术 创建两个进程&#xff0c;主进程负责接收退出信号&#xff0c;子进程负责管理线程池。子进程中的主线程 &#xff08;包工头&#xff09;&#xff1a;监听客…