一、緩存的好與壞
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;
}