SpringBoot2.X整合Spring-Cache緩存開發(fā)的實現(xiàn)
引入依賴
<!-- 引入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會導(dǎo)入 RedisCacheConfiguration;自動配置好了緩存管理器RedisCacheManager
配置使用redis作為緩存
spring.cache.type=redis
測試使用緩存
- @Cacheable: Triggers cache population. 觸發(fā)將數(shù)據(jù)保存到緩存的操作
- @CacheEvict: Triggers cache eviction. 觸發(fā)將數(shù)據(jù)從緩存刪除的操作
- @CachePut: Updates the cache without interfering with the method execution.不影響方法執(zhí)行更新緩存
- @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、每一個需要緩存的數(shù)據(jù)我們都來指定要放到哪個名字的緩存?!揪彺娴姆謪^(qū)(按照業(yè)務(wù)類型分)】 ?* 2、@Cacheable({"category"}) ?* ? ? ?代表當(dāng)前方法的結(jié)果需要緩存,如果緩存中有,方法不再調(diào)用。 ?* ? ? ?如果緩存中沒有,會調(diào)用方法,最后將方法的結(jié)果放入緩存。 ?* 3、默認(rèn)行為 ?* ? ? ?1)、如果緩存中有,方法不用調(diào)用。 ?* ? ? ?2)、key默認(rèn)自動生成:格式:緩存的名字::SimpleKey [](自主生成的key值) 例:category::SimpleKey [] ?* ? ? ?3)、緩存的value值,默認(rèn)使用jdk序列化機(jī)制。將序列化后的數(shù)據(jù)存到redis ?* ? ? ?4)、默認(rèn)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)、指定緩存的數(shù)據(jù)的存活時間 spring.cache.redis.time-to-live=3600000 ?* ? ? ?3)、將數(shù)據(jù)保存為json格式 ?* ?* ?* @return ?*/ @Cacheable(value = {"category"}, key = "#root.method.name") @Override public List<CategoryEntity> findCatelog1() { ? System.out.println("查詢數(shù)據(jù)庫---"); ? return baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0)); }
指定緩存數(shù)據(jù)的存活時間
spring.cache.redis.time-to-live=3600000
將數(shù)據(jù)保存為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; ? ? } }
緩存的其他自定義配置
# 如果指定了前綴就用我們指定的前綴,如果沒有就默認(rèn)使用緩存的名字作為前綴 # spring.cache.redis.key-prefix=CACHE_ # 默認(rèn)就使用分區(qū)名 spring.cache.redis.use-key-prefix=true # 是否緩存空值。防止緩存穿透 spring.cache.redis.cache-null-values=true
@CacheEvict注解的使用
數(shù)據(jù)一致性中的失效模式
/** * 使用失效模式:先刪除緩存,在訪問系統(tǒng)獲得緩存 * findCatelog1:緩存時的key名 * value = "category" 需要與緩存時的名稱相同 * 存儲同一個類型的數(shù)據(jù),都可以指定成同一個分區(qū)。分區(qū)名默認(rèn)就是緩存的前綴 */ // @CacheEvict(value = "category", key = "'findCatelog1'")// 刪除具體key的緩存 @CacheEvict(value = "category", allEntries = true)// 指定刪除某個分區(qū)下的所有數(shù)據(jù) @Transactional @Override public void updateCascade(CategoryEntity category) { this.updateById(category); categoryBrandRelationService.updateCategory(category.getCatId(), category.getName()); }
數(shù)據(jù)一致性中的雙寫模式,使用@CachePut注解
@Caching注解的使用
/** * @CacheEvict: 失效模式:先刪除緩存,在訪問系統(tǒng)獲得緩存 * 1、同時進(jìn)行多種緩存操作 @Caching * 2、指定刪除某個分區(qū)下的所有數(shù)據(jù) * @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注解的使用
數(shù)據(jù)一致性中的雙寫模式
@CachePut // 雙寫模式時使用
Spring-Cache的不足
讀模式
- 緩存穿透:查詢一個null數(shù)據(jù)。解決:緩存空數(shù)據(jù):spring.cache.redis.cache-null-values=true
- 緩存雪崩:大量的key同時過期。解決:加隨機(jī)時間,加上過期時間。spring.cache.redis.time-to-live=3600000
- 緩存擊穿:大量并發(fā)同時查詢一個正好過期的數(shù)據(jù)。解決:加鎖。SpringCache默認(rèn)是沒有加鎖的。
@Cacheable(value = {"category"}, key = "#root.method.name", sync = true)
sync = true 相當(dāng)于是加本地鎖,可以用來解決擊穿問題
寫模式
- 讀寫加鎖
- 引入Canal,感知到MySQL的更新去更新數(shù)據(jù)庫
- 讀多寫多,直接去數(shù)據(jù)庫查詢就行
總結(jié)
常規(guī)數(shù)據(jù)(讀多寫少,即時性,一致性要求不高的數(shù)據(jù)),完全可以使用Spring-Cache。寫模式:只要緩存的數(shù)據(jù)有過期時間就足夠了
到此這篇關(guān)于SpringBoot2.X整合Spring-Cache緩存開發(fā)的實現(xiàn)的文章就介紹到這了,更多相關(guān)SpringBoot Spring-Cache緩存 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot整合ehcache 實現(xiàn)支付超時限制的方法
在線支付系統(tǒng)需要極高的穩(wěn)定性,在有限的系統(tǒng)資源下,穩(wěn)定性優(yōu)先級要高于系統(tǒng)并發(fā)以及用戶體驗,因此需要合理的控制用戶的支付請求。下面通過本文給大家介紹springboot整合ehcache 實現(xiàn)支付超時限制的方法,一起看看吧2018-01-01IntelliJ IDEA 安裝教程2019.09.23(最新版)
本文通過圖文并茂的形式給大家介紹了IntelliJ IDEA 安裝教程2019.09.23最新版,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-10-10mybatis-plus IdWorker生成的Id和返回給前臺的不一致的解決
這篇文章主要介紹了mybatis-plus IdWorker生成的Id和返回給前臺的不一致的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03Java 十進(jìn)制轉(zhuǎn)二、八、十六進(jìn)制的字符串
本文主要介紹了十進(jìn)制轉(zhuǎn)二進(jìn)制;十進(jìn)制轉(zhuǎn)八進(jìn)制;十進(jìn)制轉(zhuǎn)十六進(jìn)制的方法,具有很好的參考價值,下面跟著小編一起來看下吧2017-02-02Maven Plugin的@Mojo和@Execute的具體使用
本文主要介紹了Maven Plugin的@Mojo和@Execute的具體使用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09Java設(shè)計模式編程中的責(zé)任鏈模式使用示例
這篇文章主要介紹了Java設(shè)計模式編程中的責(zé)任鏈模式使用示例,責(zé)任鏈模式可以避免很多請求的發(fā)送者和接收者之間的耦合關(guān)系,需要的朋友可以參考下2016-05-05Spring boot項目中異常攔截設(shè)計和處理詳解
這篇文章主要介給大家紹了關(guān)于Spring boot項目中異常攔截設(shè)計和處理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用spring boot具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起看看吧2018-12-12