spring-boot (1.5.x & 2.x) integrates redis to achieve cache comparison

Abstract: 1. In this case, we assume that user information (user) and product information (product) need to be cached. The cached data is prefixed with user and product as the key, and the id of the user and the id of the product are used as the suffix of the key. The user cache time is 30 minutes, and the product information cache time is 10 minutes.

1. This case

We assume that user information (user) and product information (product) need to be cached. The cached data is prefixed with user and product as the key, and the id of the user and the id of the product are used as the suffix of the key. The user cache time is 30 minutes, and the product information cache time is 10 minutes.

2. Redis client configuration

No matter which version of spring-boot is used, we need to configure the redis connection first. The two versions of the redis client connection pool use different.

spring-boot version Default client type
1.5.x jedis
2.x lettuce

In 1.5.x, we only need to configure the jedis connection pool to configure the configuration starting with spring.redis.pool. *, the following configuration

spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
spring.redis.pool.min-idle=0
spring.redis.pool.max-idle=8

However, in the 2.x version, due to the introduction of different clients, it is necessary to specify which connection pool to configure, as follows:

#jedis客户端
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-wait=-1ms
spring.redis.jedis.pool.min-idle=0
spring.redis.jedis.pool.max-idle=8
#lettuce客户端
spring.redis.lettuce.pool.min-idle=0
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.shutdown-timeout=100ms

In addition, you can also see that the time configuration also needs to bring the corresponding unit.

3. Directly configure the cache parameters

There are very few configurations for cache provided under version 1.5.x. The configuration of auto-wired redis cache that we can use is as follows

#缓存的名称集合,多个采用逗号分割
spring.cache.cache-names=
#缓存的类型,官方提供了很多,这里我们填写redis
spring.cache.type=

In the 2.x version, the official added more configurations

#缓存的名称集合,多个采用逗号分割
spring.cache.cache-names=
#缓存的类型,官方提供了很多,这里我们填写redis
spring.cache.type=
#是否缓存null数据,默认是false
spring.cache.redis.cache-null-values=
#redis中缓存超时的时间,默认60000ms
spring.cache.redis.time-to-live=
#缓存数据key是否使用前缀,默认是true
spring.cache.redis.use-key-prefix=
#缓存数据key的前缀,在上面的配置为true时有效,
spring.cache.redis.key-prefix=

Four, JavaConfig configuration

The general configuration method can only satisfy the way that all caches of the whole program use the same public configuration method. If special processing is required, such as our case, you need to configure it by yourself.
In the way of code, as long as CacheMananger needs to be configured, when using Redis, we need to use its subclass RedisCacheMananger for configuration.

4.1, spring-boot 1.5.x version

CacheManager configuration

@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
    RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate);
    //默认超时时间,单位秒
    redisCacheManager.setDefaultExpiration(60);
    //缓存超时时间Map,key为cacheName,value为超时,单位是秒
    Map<String, Long> expiresMap = new HashMap<>();
    //缓存用户信息的cacheName和超时时间
    expiresMap.put("user", 1800L);
    //缓存产品信息的cacheName和超时时间
    expiresMap.put("product", 600L);
    redisCacheManager.setExpires(expiresMap);
    return redisCacheManager;
}

cache call code

@Cacheable(value = "user", key = "'user:'+#id", unless = "#result==null")
public String getUser(int id) {
    //逻辑操作
}
@Cacheable(value = "product", key = "'product:'+#id", unless = "#result==null")
public String getProduct(int id) {
    //逻辑操作
}

4.2, spring-boot 2.x version

CacheManager configuration

Since version 2.x, the code configuration has changed a lot, and more configuration parameters have been added at the same time.

@Bean
CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
    //user信息缓存配置
    RedisCacheConfiguration userCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(30)).disableCachingNullValues().prefixKeysWith("user");
    //product信息缓存配置
    RedisCacheConfiguration productCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10)).disableCachingNullValues().prefixKeysWith("product");
    Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
    redisCacheConfigurationMap.put("user", userCacheConfiguration);
    redisCacheConfigurationMap.put("product", productCacheConfiguration);
    //初始化一个RedisCacheWriter
    RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);


    //设置CacheManager的值序列化方式为JdkSerializationRedisSerializer,但其实RedisCacheConfiguration默认就是使用StringRedisSerializer序列化key,JdkSerializationRedisSerializer序列化value,所以以下注释代码为默认实现
    //ClassLoader loader = this.getClass().getClassLoader();
    //JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer(loader);
    //RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(jdkSerializer);
    //RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);


    RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig();
    //设置默认超过期时间是30秒
    defaultCacheConfig.entryTtl(Duration.ofSeconds(30));
    //初始化RedisCacheManager
    RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig, redisCacheConfigurationMap);
    return cacheManager;
}

The RedisCacheConfiguration class in the above code is a new configuration class in 2.x, adding several configuration items. The strange thing here is that every time the configuration method is called, a configuration object will be regenerated instead of directly modifying the parameter value on the original object. I don't understand why the author chose this method.

cache call code

@Cacheable(value = "user", key = "#id", unless = "#result==null")
public String getUser(int id) {
    //逻辑操作
}
@Cacheable(value = "product", key = "#id", unless = "#result==null")
public String getProduct(int id) {
    //逻辑操作
}

Two points to note here

  • 1. You do not need to configure the prefix yourself in the key attribute of Cacheable, you can configure it in RedisCacheConfiguration.
  • 2. If the unless = "#result==null" attribute is not configured in Cacheable, and the disableCachingNullValues() is called in RedisCacheConfiguration to configure the null result not to be cached, an exception will be reported when a null result occurs, which is inconsistent with my initial understanding. Too the same, not both of them work. Personally understand that the configuration of unless #result==null can determine whether the null value is lost to the cacheManager, and the disableCachingNullValues() of RedisCacheConfiguration only plays a verification role before storing, and will not directly skip the saving of null because this value is set . If it is really designed like this, it feels a bit tasteless, and I don't know if it is a bug.

summary

spring-boot has just released the official version 2.0.0. Except for the relatively large webflux, many components may have detailed changes. When upgrading, you need to pay attention to changes. It is recommended to verify the usage of commonly used functions before upgrading. plan arrangement.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326773895&siteId=291194637