前面我们已经实现了多级缓存架构,大大提高了查询商品的性能,缓存在提高性能的同时,也带来了一致性的问题,比如说数据库发生了修改,这个时候,如果缓存依然是旧的数据,两者就产生了不一致,这不是我们需要看到的,如何保证缓存与数据库的一致性,这是我们下面结局的问题,缓存同步问题:
(1)缓存同步策略
大多数缓存都可以用异步通知方案:
用MQ还是需要在代码中做一定的修改,我们用下一种方案
修改商品的业务不需要修改,来了以后直接写数据库,写完结束,这个时候canal监听数据库的变化发现数据库变了之后,直接通知缓存服务完成更新,做到了代码0侵入
(2)安装Canal
在bin目录下生成一个文件:
通过Posttion来确定主库与从库之间的数据,从库position小于主库position,就说明需要新的log需要获取了
进入canal:
(3)监听Canal
Canal监听Mysql的变化,去更新客户端
Canal的java的客户端编写是比较麻烦的,我们第三方开源的canal-start
创建类:
在RedisHandler中添加:
JVM的进程还存也是有的,可以这样操作:
上面我们只是对Redis跟JVM做了修改,nginx本地缓存没有修改,浏览器用户前端页面上不太容易看到,只能查看看接口直接访问
我们直接调用接口查看数据修改情况,先查询到1001
现在对1001数据做修改:我们提供了一个修改页面
修改:
浏览器做有日志显示:
这个是直接查询接口,查询tomcat返回的数据,页面进行了修改,这样则可以证明,Redis和tomcat
进行了修改
(JVM)本地缓存进行了修改
Redis也进行修改:
如果openResty也做了集群,nginx也要修改负载均衡的算法,让查询你一个商品,请求的是同一个openResty
在openResty我们做的是超时的同步,设置时间,到期自动删除,下次再查就变成新数据了,这种方案它适合于数据更新频率较低的数据,商品中一些大多数通用数据,不怎么变得
变化频率较高的,对时效性要求交强的数据,不建议放到openResty做过期缓存了
对于Redis和tomcat就可以放任何的数据了,要想更新的话时效性比较强,这里采用的是Canal监听Mysql的方式