本地缓存设计

本地缓存设计

为什么要用本地缓存?

优势:速度快,减少网络IO,数据不会持久化,避免敏感数据存储在其他地方

劣势:不适合大数据量,毕竟是内存存储;多节点的情况存在数据不一致问题(有解决方案)

适合频繁访问的数据,比如数据字典、权限信息等

本地缓存怎么选

Map、JetCache、GuavaCache……

本地缓存选型推荐Caffeine等,自带过期策略

Jedis(方案1)

清理机制:集群部署项目的时候,本地缓存清理通过MQ通知或者Redis发布订阅通知,现在项目用的Redis发布订阅,因为RocketMQ默认用集群消费模式,没用广播模式(RocketMQ消费模式),为了避免混淆,采用了Redis来实现消息通知

  1. 消息注册器

    定义一个消息处理器

    节点本地缓存(黑名单缓存)实现消息处理器

    将消息处理器实现绑定到消息注册器

  2. 订阅管理器

    依赖:订阅中心、线程池、消息注册器

    启动:启动消息注册器

    销毁:销毁注册器订阅类,销毁注册器

  3. 发布工具类

    针对某个管道发布消息

Spring RedisTemplate(方式2)

  1. 依赖配置,spring-boot-starter-cache,spring-boot-starter-data-redis,lettuce-core,caffeine

  2. 配置 RedisTemplate,用于推送消息

    @Bean
    public StringRedisTemplate template(RedisConnectionFactory connectionFactory) {
        return new StringRedisTemplate(connectionFactory);
    }
    
  3. 消息发布服务

    @Slf4j
    @Component
    public class PublishService {
        @Autowired
        private StringRedisTemplate redisTemplate;
    
        public void publish(String channel, String message) {
            log.info("publish channel: {}, message: {}", channel, message);
            redisTemplate.convertAndSend(channel, message);
        }
    }
    
  4. 消息消费者接口 SubscriptService

    public interface SubscriptService {
        String getTopic();
    
        void handleMessage(String message);
    }
    
  5. 配置 RedisMessageListenerContainer,绑定消息处理器服务到监听容器

    @Bean
    public RedisMessageListenerContainer container(LettuceConnectionFactory connectionFactory,
        List<SubscriptService> subscriptServiceList) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
    
        for (SubscriptService subscriptService : subscriptServiceList) {
            MessageListenerAdapter listenerAdapter = new MessageListenerAdapter(subscriptService);
            listenerAdapter.afterPropertiesSet();
            container.addMessageListener(listenerAdapter, new PatternTopic(subscriptService.getTopic()));
        }
        return container;
    }
    

    这里需要注意

    如果 MessageListenerAdapter 不是以 @Bean的方式 注册的,则需要手动调用afterPropertiesSet,不然消息消费的时候会报空指针

    如果 MessageListenerAdapter 不指定消费方法的时候,默认调用handleMessage方法,这就是为什么前面SubscriptService方法名叫handleMessage

  6. 配置本地缓存(黑名单)caffeineCache

  7. 定义消息处理器服务(黑名单) SubscriptServiceImpl

使用的时候,通过PublishService或者直接用RedisTemplate发布缓存清理消息,SubscriptService监听到消息后执行清理逻辑

未完待续
未完待续

posted @ 2025-05-11 19:50  一只盐桔鸡  阅读(24)  评论(0)    收藏  举报