springboot 缓存一致性常用解决方案( 四 )

6、测试1、启动服务后,按照上面的测试步骤,分别调用2个查询接口 
通过控制台输出结果,可以看到节点数据注册到zk中

springboot 缓存一致性常用解决方案

文章插图
 
springboot 缓存一致性常用解决方案

文章插图
 
2、调用删除接口
此时zk的监听逻辑中监听到了节点数据变更的事件,在变更的逻辑中,我们将同步删除本地缓存的数据;
springboot 缓存一致性常用解决方案

文章插图
 
再次调用时发现缓存已经被清理
springboot 缓存一致性常用解决方案

文章插图
 
通过上面的操作演示,实现了基于zk的节点注册与事件监听机制实现缓存一致性的问题处理;
五、解决方案三:使用redis事件订阅与发布机制实现缓存同步
Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息 。
这种模式很像消息队列的实现机制,服务端发布消息到topic,客户端监听topic的消息,并做自身的业务处理;
只不过在redis这里,不叫topic,而是channel,下面来看一个简单的redis实现的发布订阅使用
1、导入依赖org.springframework.bootspring-boot-starter-data-redis2、自定义 RedisMessageListener
该类的功能和消息中间件中的监听逻辑很相似
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.connection.Message;import org.springframework.data.redis.connection.MessageListener;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;@Componentpublic class RedisMessageListener implements MessageListener {@Autowiredprivate RedisTemplate redisTemplate;@Overridepublic void onMessage(Message message, byte[] pattern) {// 获取消息byte[] messageBody = message.getBody();// 使用值序列化器转换Object msg = redisTemplate.getValueSerializer().deserialize(messageBody);// 获取监听的频道byte[] channelByte = message.getChannel();// 使用字符串序列化器转换Object channel = redisTemplate.getStringSerializer().deserialize(channelByte);// 渠道名称转换String patternStr = new String(pattern);System.out.println(patternStr);System.out.println("---频道---: " + channel);System.out.println("---消息内容---: " + msg);3、自定义 RedisSubConfig
该类用于配置特定的channel,即监听来自哪些channel的消息
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.listener.ChannelTopic;import org.springframework.data.redis.listener.RedisMessageListenerContainer;@Configurationpublic class RedisSubConfig {@Beanpublic RedisMessageListenerContainer container(RedisConnectionFactory factory, RedisMessageListener listener) {RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory(factory);//订阅频道redis.news 和 redis.life 这个container 可以添加多个 messageListenercontainer.addMessageListener(listener, new ChannelTopic("redis.life"));container.addMessageListener(listener, new ChannelTopic("redis.news"));return container;4、最后编写一个接口做测试@GetMapping("/testPublish")public void testPublish(){dbUserService.testPublish();@Autowiredprivate RedisTemplate redisTemplate;@Overridepublic void testPublish() {redisTemplate.convertAndSend("redis.life", "aaa");redisTemplate.convertAndSend("redis.news", "bbb");
调用下接口,可以看到控制台输出如下信息
springboot 缓存一致性常用解决方案

文章插图
 
通过上面的演示,快速了解了一下redis的这种发布订阅模式的功能使用,下面就来使用这种方式来解决缓存一致性问题;
5、删除用户接口中向redis channel 推送消息@Override@CacheEvict(value = https://www.isolves.com/it/cxkf/kj/2022-09-05/{"dbUser"},key = "#root.args[0]",cacheManager = "cacheManagerMinutes")public String deleteById(String id) {dbUserMapper.deleteByUserId(id);redisTemplate.convertAndSend("redis.user", id);return "delete success";


推荐阅读