使用Spring自带的缓存注解维护数据一致性的全过程

 更新时间:2026年01月14日 08:55:15   作者:何中应  
Cache(缓存),已经是项目中不可缺失的存在,一旦项目中需要使用到缓存,就需要考虑到数据一致性问题,即缓存数据与数据库数据的一致性问题,本文介绍在 Spring Boot 项目中,如何使用 Spring 自带的注解来进行数据一致性的维护,需要的朋友可以参考下

简介

Cache(缓存),已经是项目中不可缺失的存在,登录时,存储用户信息、操作权限、Token 等,高并发场景,存储热点信息、实时信息等。按照类型分类,可分为本地缓存和分布式缓存,前者重启服务失效,后者可以持久化,按照设置的过期时间或策略失效。

一旦项目中需要使用到缓存,就需要考虑到数据一致性问题,即缓存数据与数据库数据的一致性问题,本文介绍在 Spring Boot 项目中,如何使用 Spring 自带的注解来进行数据一致性的维护。

整合

Spring 自带了缓存维护的注解,如果你的项目就是 Spring/Spring Boot 项目,不需要额外引入依赖

但如果你需要缓存不会因项目重启而失效,可以引入 Redis,把 Redis 当作缓存容器,需引入 Redis 依赖。基本所有的项目都会用到 Redis,当然引入了就需要保证系统与 Redis 的连通。

 <!-- 引入 Redis -->
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-redis</artifactId>
 </dependency>

在项目中创建一个 Redis 缓存配置类,里面对缓存进行统一的配置,如过期时间等。

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 是设置缓存名称,key 设置缓存的 key 值,可以用 # 与方法入参关联,如 #id 表示 key 值取自方法入参 id 的值。

  • @Cacheable(cacheNames = “缓存名”, key = “#id”):添加缓存;
  • @CachePut(cacheNames = “缓存名”, key = “#id”):执行方法后,添加缓存;
  • @CacheEvict(cacheNames = “缓存名”, key = “#id”):使缓存失效;

需要注意的是,这套缓存作用的机制是,关联方法入参与返回,当方法入参相同时,返回缓存中的结果,不再执行代码。所以只有相同的入参才能用得上缓存。

验证

创建下面这四个接口,查询方法添加缓存,新增方法执行后添加缓存,删除和更新方法删除缓存。

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

对应的实现类代码。

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

启动项目,测试一下。

首次查询,断点卡在查询方法实现类这里,执行了实现类方法。

再次查询,直接返回了结果。

Redis 中增加了一个缓存。

参数换一下,传入 id=1。

发送请求,断点卡住了,说明没走缓存。

新增了一个 id=1 的缓存。

再试下更新方法,更新 id=1 的记录。

发送请求,查看 Redis,缓存都没了。

本来可以只让符合条件的,即 id=1 的缓存失效,上面都失效了,是因为我在更新方法的注解上额外加了一个属性。

allEntries = true,名称相同的所有缓存都失效,默认 false。

再试下,删除方法我没加这个属性。

调用删除方法,删除 id=1 的记录。

这回只有 id=1 的缓存被删除。

另外再试下创建方法,创建方法会再执行完创建方法后,主动将返回值添加到缓存中。

实际开发中,可以在某个创建接口完成后,将完整的对象数据返回,无缝衔接,就不用首次查询还要走一遍实现层。

以上就是使用Spring自带的缓存注解维护数据一致性的全过程的详细内容,更多关于Spring自带缓存注解维护数据一致性的资料请关注脚本之家其它相关文章!

相关文章

  • Mybatis中传递多个参数的4种方法总结

    Mybatis中传递多个参数的4种方法总结

    这篇文章主要给大家介绍了关于Mybatis中传递多个参数的4种方法,并且介绍了关于使用Mapper接口时参数传递方式,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧。
    2018-04-04
  • springboot+Quartz实现任务调度的示例代码

    springboot+Quartz实现任务调度的示例代码

    本篇文章主要介绍了springboot + Quartz 实现任务调度的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-02-02
  • 批量上传Jar包到Maven私服的工具的方法

    批量上传Jar包到Maven私服的工具的方法

    这篇文章主要介绍了批量上传Jar包到Maven私服的工具的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-12-12
  • Spring Boot 2.0 整合 Spring Security OAuth2的完整实现方案

    Spring Boot 2.0 整合 Spring Security&

    OAuth 2.0是一个行业标准的授权协议,它允许用户在不将用户名和密码提供给第三方应用的情况下,授权第三方应用访问用户存储在服务提供方的资源,本文给大家介绍Spring Boot 2.0 整合 Spring Security OAuth2的完整实现方案,感兴趣的朋友一起看看吧
    2026-03-03
  • 与众不同的 Java 日期格式化大全

    与众不同的 Java 日期格式化大全

    这篇文章主要介绍了与众不同的 Java 日期格式化大全,在 Java 中,经常要将时间字符串转换为日期,或者要将日期转换为时间字符串。,需要的朋友可以参考下
    2019-06-06
  • 使用Java增删改查数据库的操作方法

    使用Java增删改查数据库的操作方法

    这篇文章主要介绍了使用Java增删改查数据库的操作方法,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-12-12
  • java 关键字super详解及用法

    java 关键字super详解及用法

    这篇文章主要介绍了java 关键字super详解及用法的相关资料,需要的朋友可以参考下
    2017-03-03
  • 浅析Spring Security如何防止CSRF攻击

    浅析Spring Security如何防止CSRF攻击

    CSRF(Cross-Site Request Forgery)攻击,即跨站请求伪造攻击,本文主要为大家整理了Spring Security防止CSRF攻击的相关方法,大家可以根据需要进行选择
    2025-07-07
  • SpringBoot获取http数据、打印HTTP参数的4种方式

    SpringBoot获取http数据、打印HTTP参数的4种方式

    Java的话本地打断点可以调试获取rest入参,但是在生产环境可能我们获取入参(Http header/parameter)可能就没有那么的轻松了,所以本文给大家介绍了SpringBoot获取http数据、打印HTTP参数的4种方式,需要的朋友可以参考下
    2024-03-03
  • Spring框架构造注入type属性实例详解

    Spring框架构造注入type属性实例详解

    这篇文章主要介绍了Spring框架构造注入type属性实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12

最新评论