springboot集成spring cache——缓存

目录

1.springboot集成spring cache

2.@cacheable标签使用

3.缓存一致性

4.spring cache的问题


1.springboot集成spring cache

本次主要基于redis使用spring cache,进行缓存管理。

首选导入相关依赖(此处未指定版本号,请自行选择):

        <!-- redis 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- spring cache 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

编写application.yml和application.properties配置文件,配置相关信息 :

spring:
  # redis配置连接配置
  redis:
    database: 0
    host: 127.0.0.1
    #redis默认端口
    port: 6379
    password:
    timeout: 5000ms
#指定spring-cache为 redis
spring.cache.type=redis
#指定spring-cache过期时间
spring.cache.redis.time-to-live= 60000
#允许缓存空值,避免缓存穿透
spring.cache.redis.cache-null-values=true

创建cache配置类,对redis存储数据进行序列化等操作:

import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
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.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@EnableConfigurationProperties(CacheProperties.class)
@EnableCaching
public class CacheConfig {

    @Bean
    RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){
        //获取redis cache管理器
        RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
        //redis序列化,json格式保存
        configuration = configuration.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
        configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));

        //使配置文件中生效
        CacheProperties.Redis redisProperties = cacheProperties.getRedis();
        if (redisProperties.getTimeToLive() != null) {
            configuration = configuration.entryTtl(redisProperties.getTimeToLive());
        }
        if (redisProperties.getKeyPrefix() != null) {
            configuration = configuration.prefixKeysWith(redisProperties.getKeyPrefix());
        }
        if (!redisProperties.isCacheNullValues()) {
            configuration = configuration.disableCachingNullValues();
        }
        if (!redisProperties.isUseKeyPrefix()) {
            configuration = configuration.disableKeyPrefix();
        }
        return configuration;
    }
}

然后,我们就可以在业务类中对spring cache进行使用了。

2.@cacheable标签使用

我们可以在对应的业务类中对应的方法上添加 @Cacheable 标签,来使用spring cache缓存。

@Cacheable 常用的主要是以下参数:
  • value:分区名;一般一种类型的数据指定统一分区
  • key:键值;和redis中的key相同,常用方法名替代

下面对一次查询进行缓存,来进行演示(此处key值为方法名):

    @Cacheable(value={"addressCache"},key="#root.methodName")
    @Override
    public Map<String, List<Address>> searchAllNew() {

        //mybatis-plus查询数据库
        List<Address> addressList = userAddressMapper.selectList(new QueryWrapper<>());

        Map<String,List<Address>> map = new HashMap<>();
        map.put("address",addressList);
        //自动将返回值缓存进redis中
        return map;
    }

在spring cache中,会自动查询缓存中是否有该数据:若有,直接返回缓存数据,不执行业务代码;若无,执行业务代码,并将结果缓存进redis中,以便下次查询使用。 

3.缓存一致性

关于缓存一致性问题(即数据库中数据和缓存中的数据一致性问题),我们通常通过两种方法来解决:

(1)双写模式:即修改数据时,同时把修改后的数据写入缓存,进行更新。

(2)失效模式:即修改数据时,直接把缓存进行删除。下次查询时,再把新数据存入缓存。

以上两种模式都可能因为网络卡顿等原因,形成脏数据。所以,怎么选择,还需要根据具体的业务情况及数据情况进行。

下面对spring cache中的两种模式进行演示:

(1)使用 @CachePut 标签实现双写模式(此处key值为实体类中的唯一id):

    @CachePut(value = {"addressCache"},key = "#address.id")
    public Address updateAddress(Address address) {
        userAddressMapper.updateById(address);
        return userAddressMapper.selectById(address.getId());
    }

此处需要注意的是 @CachePut 所标记的方法需要有返回值,否则会报错,无法进行缓存。

(2)使用 @CacheEvict 标签实现失效模式(此处key值为实体类中的唯一id)

    @CacheEvict(value = {"addressCache"},key = "#address.id")
    public void updateAddress(Address address) {
        userAddressMapper.updateById(address);
    }

在该模式下,无需返回值,spring cache会自动删除分区下对应的key下的缓存。

4.spring cache的问题

 需要注意的是,spring cache默认是不加锁的。因为其是根据标签来进行缓存,无法像我们手动使用redis进行缓存一样,使用redission等工具加上分布式锁。

spring cache提供了一个本地锁(即获取缓存时,给方法加上 synchronized),其使用方式为,在cacheable标签上,添加一个值sync:

//sync,调用redisCacheManage中的加锁(本地锁)的get方法,去查缓存
@Cacheable(value={"addressCache"},key="#root.methodName",sync = true)

 尽管如此,spring cache可以一定程度上解决缓存击穿的问题,但也只适用于读多写少(即时性要求不高的数据)的数据。如果读多写多的数据,不建议使用缓存,而是直接查询数据库。

具体缓存如何使用,还需要根据不同的业务要求来进行设计。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值