springboot快速启动(十四)——解决boot cache存在问题

一、缓存的好与坏
1、缓存带来的回报

        1)高速读写
           缓存加速读写速度:CPU L1/L2/L3 Cache、Linux page Cache加速硬盘读写、浏览器缓存、Ehcache缓存数据库结果

       
        2)降低后端负载
           后端服务器通过前端缓存降低负载: 业务端使用Redis降低后端MySQL负载等  

2、缓存带来的代价

        1)数据不一致
           缓存层和数据层有时间窗口不一致,和更新策略有关      


        2)代码维护成本
           原本只需要读写MySQL就能实现功能,但加入了缓存之后就要去维护缓存的数据,增加了代码复杂度。


        3)堆内缓存可能带来内存溢出的风险影响用户进程,如ehCache、loadingCache      

               堆、java虚拟机栈、方法区、本地方法栈、程序计数器 
        
               堆内缓存和远程服务器缓存redis的选择

               1、堆内缓存一般性能更好,远程缓存需要套接字传输

               2、用户级别缓存尽量采用远程缓存
               
               3、大数据量尽量采用远程缓存,服务节点化原则

如何快速整合cache地址https://blog.csdn.net/weixin_42083036/article/details/103388222

二、boot cache存在问题

1、生成key过于简单 容易冲突?
解决方案: 自定义 key generator
解决代码:

   @Bean
public KeyGenerator simpleKeyGenerator() {
    return (o, method, objects) -> {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(o.getClass().getSimpleName());
        stringBuilder.append(".");
        stringBuilder.append(method.getName());
        stringBuilder.append("[");
        for (Object obj : objects) {
            stringBuilder.append(obj.toString());
        }
        stringBuilder.append("]");

        return stringBuilder.toString();
    };
}

2、无法设置过期时间 默认过期时间为永久?
解决方案:自定义 cacheManager 设置过期时间
解决代码:

@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
    return new RedisCacheManager(
            RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),
            this.getRedisCacheConfigurationWithTtl(600), // 默认策略,未配置的 key 会使用这个
            this.getRedisCacheConfigurationMap() // 指定 key 策略
    );
}

3、需要配置序列化方式 默认 jdk Serializable?
解决方案: 自定义序列化方式
解决代码:

private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
    Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
    ObjectMapper om = new ObjectMapper();
    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    jackson2JsonRedisSerializer.setObjectMapper(om);

    RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
    redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
            RedisSerializationContext
                    .SerializationPair
                    .fromSerializer(jackson2JsonRedisSerializer)
    ).entryTtl(Duration.ofSeconds(seconds));

    return redisCacheConfiguration;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章