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

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