使用Spring自帶的緩存注解維護數(shù)據(jù)一致性的全過程
簡介
Cache(緩存),已經(jīng)是項目中不可缺失的存在,登錄時,存儲用戶信息、操作權(quán)限、Token 等,高并發(fā)場景,存儲熱點信息、實時信息等。按照類型分類,可分為本地緩存和分布式緩存,前者重啟服務(wù)失效,后者可以持久化,按照設(shè)置的過期時間或策略失效。
一旦項目中需要使用到緩存,就需要考慮到數(shù)據(jù)一致性問題,即緩存數(shù)據(jù)與數(shù)據(jù)庫數(shù)據(jù)的一致性問題,本文介紹在 Spring Boot 項目中,如何使用 Spring 自帶的注解來進行數(shù)據(jù)一致性的維護。
整合
Spring 自帶了緩存維護的注解,如果你的項目就是 Spring/Spring Boot 項目,不需要額外引入依賴

但如果你需要緩存不會因項目重啟而失效,可以引入 Redis,把 Redis 當(dāng)作緩存容器,需引入 Redis 依賴?;舅械捻椖慷紩玫?Redis,當(dāng)然引入了就需要保證系統(tǒng)與 Redis 的連通。
<!-- 引入 Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
在項目中創(chuàng)建一個 Redis 緩存配置類,里面對緩存進行統(tǒng)一的配置,如過期時間等。
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
/**
* Redis 緩存配置
*/
@Configuration
@EnableCaching
public class RedisCacheConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(30))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.build();
}
}
配置文件中,添加 Redis 配置。
spring:
redis:
host: localhost
port: 6379
使用
配合下面幾個注解使用,可以加在接口上,如下,cacheNames 是設(shè)置緩存名稱,key 設(shè)置緩存的 key 值,可以用 # 與方法入?yún)㈥P(guān)聯(lián),如 #id 表示 key 值取自方法入?yún)?id 的值。
- @Cacheable(cacheNames = “緩存名”, key = “#id”):添加緩存;
- @CachePut(cacheNames = “緩存名”, key = “#id”):執(zhí)行方法后,添加緩存;
- @CacheEvict(cacheNames = “緩存名”, key = “#id”):使緩存失效;
需要注意的是,這套緩存作用的機制是,關(guān)聯(lián)方法入?yún)⑴c返回,當(dāng)方法入?yún)⑾嗤瑫r,返回緩存中的結(jié)果,不再執(zhí)行代碼。所以只有相同的入?yún)⒉拍苡玫蒙暇彺妗?/strong>
驗證
創(chuàng)建下面這四個接口,查詢方法添加緩存,新增方法執(zhí)行后添加緩存,刪除和更新方法刪除緩存。
import org.example.service.CacheService;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
@RequestMapping("/cache")
public class CacheController {
@Resource
private CacheService cacheService;
@GetMapping("/getOne")
@Cacheable(cacheNames = "cacheName", key = "#id")
public String getOne(@RequestParam String id) {
return cacheService.getOne();
}
@PostMapping("/createOne")
@CachePut(cacheNames = "cacheName", key = "#id")
public String createOne(@RequestParam String id) {
return cacheService.createOne();
}
@PostMapping("/deleteOne")
@CacheEvict(cacheNames = "cacheName", key = "#id")
public String deleteOne(@RequestParam String id) {
return cacheService.deleteOne();
}
@PostMapping("/updateOne")
@CacheEvict(cacheNames = "cacheName", key = "#id", allEntries = true)
public String updateOne(@RequestParam String id) {
return cacheService.updateOne();
}
}
對應(yīng)的實現(xiàn)類代碼。
import org.springframework.stereotype.Service;
@Service
public class CacheServiceImpl implements CacheService {
@Override
public String getOne() {
return "Select is a cache data.";
}
@Override
public String createOne() {
return "Create is a cache data.";
}
@Override
public String deleteOne() {
return "Deleted is a cache data.";
}
@Override
public String updateOne() {
return "Updated is a cache data.";
}
}
啟動項目,測試一下。

首次查詢,斷點卡在查詢方法實現(xiàn)類這里,執(zhí)行了實現(xiàn)類方法。

再次查詢,直接返回了結(jié)果。

Redis 中增加了一個緩存。

參數(shù)換一下,傳入 id=1。

發(fā)送請求,斷點卡住了,說明沒走緩存。

新增了一個 id=1 的緩存。

再試下更新方法,更新 id=1 的記錄。

發(fā)送請求,查看 Redis,緩存都沒了。

本來可以只讓符合條件的,即 id=1 的緩存失效,上面都失效了,是因為我在更新方法的注解上額外加了一個屬性。
allEntries = true,名稱相同的所有緩存都失效,默認 false。

再試下,刪除方法我沒加這個屬性。

調(diào)用刪除方法,刪除 id=1 的記錄。

這回只有 id=1 的緩存被刪除。

另外再試下創(chuàng)建方法,創(chuàng)建方法會再執(zhí)行完創(chuàng)建方法后,主動將返回值添加到緩存中。

實際開發(fā)中,可以在某個創(chuàng)建接口完成后,將完整的對象數(shù)據(jù)返回,無縫銜接,就不用首次查詢還要走一遍實現(xiàn)層。

以上就是使用Spring自帶的緩存注解維護數(shù)據(jù)一致性的全過程的詳細內(nèi)容,更多關(guān)于Spring自帶緩存注解維護數(shù)據(jù)一致性的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Mybatis中傳遞多個參數(shù)的4種方法總結(jié)
這篇文章主要給大家介紹了關(guān)于Mybatis中傳遞多個參數(shù)的4種方法,并且介紹了關(guān)于使用Mapper接口時參數(shù)傳遞方式,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-04-04
springboot+Quartz實現(xiàn)任務(wù)調(diào)度的示例代碼
本篇文章主要介紹了springboot + Quartz 實現(xiàn)任務(wù)調(diào)度的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02
Spring Boot 2.0 整合 Spring Security&
OAuth 2.0是一個行業(yè)標(biāo)準(zhǔn)的授權(quán)協(xié)議,它允許用戶在不將用戶名和密碼提供給第三方應(yīng)用的情況下,授權(quán)第三方應(yīng)用訪問用戶存儲在服務(wù)提供方的資源,本文給大家介紹Spring Boot 2.0 整合 Spring Security OAuth2的完整實現(xiàn)方案,感興趣的朋友一起看看吧2026-03-03
SpringBoot獲取http數(shù)據(jù)、打印HTTP參數(shù)的4種方式
Java的話本地打斷點可以調(diào)試獲取rest入?yún)?但是在生產(chǎn)環(huán)境可能我們獲取入?yún)ⅲ℉ttp?header/parameter)可能就沒有那么的輕松了,所以本文給大家介紹了SpringBoot獲取http數(shù)據(jù)、打印HTTP參數(shù)的4種方式,需要的朋友可以參考下2024-03-03

