springboot integration redis to cache some knowledge

Foreword

Recently doing smart home platform, taking into account the need to control home fast response he intended to use redis cache. Database while reducing the pressure on the other hand can increase the response speed. The technology stack used in the project are basically familiar springboot family bucket, operating redis client at a later springboot2.x recommended lettuce (lettuce) replaced jedis.

jedis disadvantage lies in direct redis, we can not do elastic contraction.

First, the configuration file

Content application.yml file

the Spring: 
  the Application: 
    name: the Simple - Lettuce 
  Cache: 
    of the type: Redis 
    Redis: 
      # cache timeout MS 
      Time -to-Live: 60000 
      # null if the cache 
      Cache - null -values: to true 
  Redis: 
    Host: 127.0 . 0.1 
    Port: 6379 
    password: 123456 
    # connection time (ms) 
    timeout: 60000 
    # 16 has the Redis fragments default case, this particular configuration fragment used, the default is 0 
    Database: . 1 
    # spring2.x Redis Client uses lettuce (lettuce) renounce the use jedis  
    Lettuce:
      # timeout for turning off
      the shutdown -timeout: 30000 
      the pool: 
        # connection pool maximum number of connections (negative values no limit) by default . 8 
        max -active: 30 
        # latency connection pool maximum blocking (negative values no limit) Default - . 1 
        max - the wait : - . 1 
        # connection pool default maximum idle connection . 8 
        max -idle: . 8 
        # minimum connection pool idle connections default 0 
        min -idle: 0

Description:

  • spring.cache.type: redis

It has been shown using the project as a cache using redis way.

  • spring.cache.redis.cache-null-values: true

Null value indicating whether the cache, under normal circumstances is permitted. Because it involves three major issues to the cache: Cache penetration, avalanche cache, the cache breakdown.

If you set false cache which does not allow null values, this will cause a lot of data requests to the database do not, and will not be cached redis cause every time a request to the database. This situation namely: cache penetration.

Specific want a preliminary understanding of these concepts can refer to the article: cache three major issues and solutions!

Two, config configuration class


@Configuration
@EnableCaching
public class RedisTemplateConfig extends CachingConfigurerSupport {

    private static Map<String, RedisCacheConfiguration> cacheMap = Maps.newHashMap();

    @Bean(name = "stringRedisTemplate")
    @ConditionalOnMissingBean(name = "stringRedisTemplate") //表示:如果容器已经有redisTemplate bean就不再注入
    public StringRedisTemplate stringRedisTemplate(LettuceConnectionFactory redisConnectionFactory) {return new StringRedisTemplate(redisConnectionFactory);
    }

    @Bean(name = "redisTemplate")
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
        System.out.println("RedisTemplateConfig.RedisTemplate");
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // key的序列化采用StringRedisSerializer
        template.setKeySerializer(keySerializer());
        template.setHashKeySerializer(keySerializer());
        // value值的序列化采用fastJsonRedisSerializer
        template.setValueSerializer(valueSerializer());use serialization fastjson//
        template.setHashValueSerializer (ValueSerializer ()); // Use fastjson serialization 
        template.setConnectionFactory (lettuceConnectionFactory);
         return Template; 
    } 

    / ** 
     * add custom exception handler buffer 
     * When the cache read and write abnormal, abnormality is ignored 
     * Reference: HTTPS : //blog.csdn.net/sz85850597/article/details/89301331 
     * / 
    @Override 
    public CacheErrorHandler the errorHandler () {
         return  new new IgnoreCacheErrorHandler (); 
    } 

    @SuppressWarnings ( "Duplicates" ) 
    @Bean 
    @Primary // when there are a plurality of Manager, you must use the annotation comment on a Manager: indicates that the manager is the default manager
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        // 默认配置
        RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig()
                .serializeKeysWith(keyPair())
                .serializeValuesWith(valuePair())
                .entryTtl(Duration.ofSeconds(DEFAULT_TTL_SECS)) //设置过期时间
                .disableCachingNullValues();

        // 其它配置
        for(MyCaches cache : MyCaches.values()) {
            cacheMap.put(cache.name(),
                    RedisCacheConfiguration.defaultCacheConfig()
                            .serializeKeysWith (KeyPair ())
                            .serializeValuesWith (valuePair ()) 
                            .entryTtl (cache.getTtl ()) 
                             
                .cacheDefaults (defaultCacheConfig)// .disableCachingNullValues () // cache is not allowed null values 
                            .disableKeyPrefix () // do not use the default prefix
                     // .prefixKeysWith ( "mytest") / / User prefix 
            ); 
        } 

        / ** traverse MyCaches adding configure the cache * / 
        RedisCacheManager CacheManager = RedisCacheManager.builder ( 
                RedisCacheWriter.nonLockingRedisCacheWriter (The connectionFactory) 
        ) 
                .withInitialCacheConfigurations (CacheMap) 
                .transactionAware () 
                .build ();

        ParserConfig.getGlobalInstance().addAccept("mypackage.db.entity.");
        return cacheManager;
    }

    /**
     * key序列化方式
     * @return
     */
    private RedisSerializationContext.SerializationPair<String> keyPair() {
        RedisSerializationContext.SerializationPair<String> keyPair =
                RedisSerializationContext.SerializationPair.fromSerializer(keySerializer());
        return keyPair;
    }

    private RedisSerializer<String> keySerializer() {
        return new StringRedisSerializer();
    }

    /**
     * value序列化方式
     * @return
     */
    private RedisSerializationContext.SerializationPair<Object> valuePair() {
        RedisSerializationContext.SerializationPair<Object> valuePair =
                RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer());
        return valuePair;
    }

    /**
     * 使用fastjson序列化
     * @return
     */
    private RedisSerializer<Object> valueSerializer() {
        MyFastJsonRedisSerializer<Object> fastJsonRedisSerializer = new MyFastJsonRedisSerializer<>(Object.class);
        return fastJsonRedisSerializer;
    }

    @Getter
    private enum MyCaches {
        defaultCache(Duration.ofDays(1)),
        MyCaches(Duration.ofMinutes(10));

        MyCaches(Duration ttl) {
            this.ttl = ttl;
        }
        /** 失效时间 */
        private Duration ttl = Duration.ofHours(1);
    }
}

 Explanation

1. annotations on class @EnableCaching

Show open the cache function.

2. extends CachingConfigurerSupport

This class is very rich, in fact, if nothing special operations can not inherit this class.

This class can support dynamic cache selection methods, such as projects in more than one cache scheme, there may ehcache you can customize using the following redis use ehcache use under what circumstances. There are also dealing with exceptions. I do not really understand specifically refer to:

3. StringRedisTemplate and RedisTemplate use

(1) The main difference between the two is: If you just want a simple string selection StringRedisTemplate cache is a wise move. If you want to use redis to cache some data objects must be to choose RedisTemplate.
 
(2) RedisTemplate point to note is how to select the serialization tool. Default jdk serialization cache data value can not be read after the value of direct and save binary data.
Normally we choose jackson fastjson or that objects are serialized, converted into an object format json. After two objects are serialized object class in the header plus a path such as: @type com.mypackage.entity.User. This can be considered a security policy.
Such as the use of the specified sequence will fastjosn object package is located in the position cacheManager whitelist: ParserConfig.getGlobalInstance () addAccept. ( "Mypackage.db.entity." ;)
fastjson official description: https: //github.com/alibaba/fastjson/wiki/enable_autotype
 
(3) There should be noted that if the value is of type string. RedisTemplate double quotes will be added to the periphery of the string, such as "" abc "". If you use RedisTemplate read it to get abc, but I read the Jedis use in the project became "abc" This leads to these strings can not be deserialized.
 
(4)StringRedisTemplate和RedisTemplate两者数据是相互隔离的,如果使用StringRedisTemplate存入的数据使用RedisTemplate是无法读取、删除的。
 
 

三、缓存注解使用

@Cacheable 使用在查询方法上

@CachePut 使用在更新、保存方法上

@CacheEvict 使用在删除方法上

需要注意的是@Cacheable@CachePut方法一定要有返回被缓存对象。因为注解使用的AOP切面如果没有返回值表示缓存对象为空值。

@CacheConfig注解在类上,可以选择使用哪个缓存、缓存管理器、Key生成器

 

好了以上就是最近在项目中的一些知识点总结,如果以后使用缓存有新的体会我会同步更新的。

Guess you like

Origin www.cnblogs.com/backnow/p/11824061.html