SpringBoot2.X整合Spring-Cache緩存開發的實現
引入依賴
<!-- 引入redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
<!-- 引入SpringCache --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency>
配置
自動配置
CacheAutoConfiguration會導入 RedisCacheConfiguration;自動配置好瞭緩存管理器RedisCacheManager
配置使用redis作為緩存
spring.cache.type=redis
測試使用緩存
- @Cacheable: Triggers cache population. 觸發將數據保存到緩存的操作
- @CacheEvict: Triggers cache eviction. 觸發將數據從緩存刪除的操作
- @CachePut: Updates the cache without interfering with the method execution.不影響方法執行更新緩存
- @Caching: Regroups multiple cache operations to be applied on a method.組合以上多個操作
- @CacheConfig: Shares some common cache-related settings at class-level.在類級別共享緩存的相同配置
@Cacheable註解的使用
- config中開啟緩存功能 @EnableCaching
- 隻需要使用註解就能完成緩存操作
/** * 1、每一個需要緩存的數據我們都來指定要放到哪個名字的緩存。【緩存的分區(按照業務類型分)】 * 2、@Cacheable({"category"}) * 代表當前方法的結果需要緩存,如果緩存中有,方法不再調用。 * 如果緩存中沒有,會調用方法,最後將方法的結果放入緩存。 * 3、默認行為 * 1)、如果緩存中有,方法不用調用。 * 2)、key默認自動生成:格式:緩存的名字::SimpleKey [](自主生成的key值) 例:category::SimpleKey [] * 3)、緩存的value值,默認使用jdk序列化機制。將序列化後的數據存到redis * 4)、默認ttl時間:-1; * * 自定義: * 1)、指定生成的緩存使用的key key屬性指定,接受一個SpEl @Cacheable(value = {"category"}, key = "#root.method.name") key的SpEl可以參考:https://docs.spring.io/spring-framework/docs/5.2.19.RELEASE/spring-framework-reference/integration.html#cache-spel-context * 2)、指定緩存的數據的存活時間 spring.cache.redis.time-to-live=3600000 * 3)、將數據保存為json格式 * * * @return */ @Cacheable(value = {"category"}, key = "#root.method.name") @Override public List<CategoryEntity> findCatelog1() { System.out.println("查詢數據庫---"); return baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0)); }
指定緩存數據的存活時間
spring.cache.redis.time-to-live=3600000
將數據保存為json格式:配置
@EnableConfigurationProperties(CacheProperties.class) @Configuration @EnableCaching // 開啟緩存 public class MyCacheConfig { /** * 配置文件中的東西沒有用上 * * 1、原來和配置文件綁定的配置類是這樣的 * @ConfigurationProperties(prefix = "spring.cache") * public class CacheProperties * * 2、要讓他生效 * @EnableConfigurationProperties(CacheProperties.class) * @return */ @Bean public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) { RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(); config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())); config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); // 將配置文件中的所有配置都生效 CacheProperties.Redis redisProperties = cacheProperties.getRedis(); if (redisProperties.getTimeToLive() != null) { config = config.entryTtl(redisProperties.getTimeToLive()); } if (redisProperties.getKeyPrefix() != null) { config = config.prefixKeysWith(redisProperties.getKeyPrefix()); } if (!redisProperties.isCacheNullValues()) { config = config.disableCachingNullValues(); } if (!redisProperties.isUseKeyPrefix()) { config = config.disableKeyPrefix(); } return config; } }
緩存的其他自定義配置
# 如果指定瞭前綴就用我們指定的前綴,如果沒有就默認使用緩存的名字作為前綴 # spring.cache.redis.key-prefix=CACHE_ # 默認就使用分區名 spring.cache.redis.use-key-prefix=true # 是否緩存空值。防止緩存穿透 spring.cache.redis.cache-null-values=true
@CacheEvict註解的使用
數據一致性中的失效模式
/** * 使用失效模式:先刪除緩存,在訪問系統獲得緩存 * findCatelog1:緩存時的key名 * value = "category" 需要與緩存時的名稱相同 * 存儲同一個類型的數據,都可以指定成同一個分區。分區名默認就是緩存的前綴 */ // @CacheEvict(value = "category", key = "'findCatelog1'")// 刪除具體key的緩存 @CacheEvict(value = "category", allEntries = true)// 指定刪除某個分區下的所有數據 @Transactional @Override public void updateCascade(CategoryEntity category) { this.updateById(category); categoryBrandRelationService.updateCategory(category.getCatId(), category.getName()); }
數據一致性中的雙寫模式,使用@CachePut註解
@Caching註解的使用
/** * @CacheEvict: 失效模式:先刪除緩存,在訪問系統獲得緩存 * 1、同時進行多種緩存操作 @Caching * 2、指定刪除某個分區下的所有數據 * @param category */ @Caching(evict = { @CacheEvict(value = "category", key = "'findCatelog1'"),// 刪除緩存 @CacheEvict(value = "category", key = "'getCatalogJson'"),// 刪除緩存 }) @Transactional @Override public void updateCascade(CategoryEntity category) { this.updateById(category); categoryBrandRelationService.updateCategory(category.getCatId(), category.getName()); }
@CachePut註解的使用
數據一致性中的雙寫模式
@CachePut // 雙寫模式時使用
Spring-Cache的不足
讀模式
- 緩存穿透:查詢一個null數據。解決:緩存空數據:spring.cache.redis.cache-null-values=true
- 緩存雪崩:大量的key同時過期。解決:加隨機時間,加上過期時間。spring.cache.redis.time-to-live=3600000
- 緩存擊穿:大量並發同時查詢一個正好過期的數據。解決:加鎖。SpringCache默認是沒有加鎖的。
@Cacheable(value = {"category"}, key = "#root.method.name", sync = true)
sync = true 相當於是加本地鎖,可以用來解決擊穿問題
寫模式
- 讀寫加鎖
- 引入Canal,感知到MySQL的更新去更新數據庫
- 讀多寫多,直接去數據庫查詢就行
總結
常規數據(讀多寫少,即時性,一致性要求不高的數據),完全可以使用Spring-Cache。寫模式:隻要緩存的數據有過期時間就足夠瞭
到此這篇關於SpringBoot2.X整合Spring-Cache緩存開發的實現的文章就介紹到這瞭,更多相關SpringBoot Spring-Cache緩存 內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Spring Cache相關知識總結
- Java SpringCache+Redis緩存數據詳解
- Spring @Cacheable註解中key的使用詳解
- SpringBoot詳解整合Spring Cache實現Redis緩存流程
- Spring緩存註解@Cacheable @CacheEvit @CachePut使用介紹