Preface
Recently, we are working on a smart home platform. Considering that the control of home needs fast response, we plan to use redis cache. On the one hand, it can reduce the pressure of database, on the other hand, it can improve the response speed. The technology stack used in the project is basically the familiar springboot family bucket. After springboot2.x, the client operating redis recommends lettuce (lettuce) instead of jedis.
The disadvantage of jedis lies in its direct connection with redis and its inability to achieve elastic contraction.
I. configuration file
Content in the application.yml file
spring: application: name: simple-lettuce cache: type: redis redis: # Cache timeout ms time-to-live: 60000 # Whether to cache null values cache-null-values: true redis: host: 127.0.0.1 port: 6379 password: 123456 # Connection timeout (MS) timeout: 60000 # Redis has 16 partitions by default. The specific partition is configured here. The default is 0 database: 1 # Spring 2. X redis client uses lettuce (lettuce) instead of jedis lettuce: # Shutdown timeout shutdown-timeout: 30000 pool: # Connection pool maximum connections (negative for no limit) default 8 max-active: 30 # Connection pool maximum block wait time (use a negative value to indicate no limit) default -1 max-wait: -1 # Maximum free connections in connection pool default 8 max-idle: 8 # Minimum free connections in connection pool default 0 min-idle: 0
Explain:
- spring.cache.type: redis
It has been shown that redis is used as the caching method.
- spring.cache.redis.cache-null-values: true
Indicates whether to cache null values, which is generally allowed. Because this involves three major issues of cache: cache penetration, cache avalanche, and cache breakdown.
If you set false, you will not be allowed to cache null values, which will result in many requests for data that the database does not have, and will not cache to redis, resulting in requests to the database every time. This is the case: cache penetration.
For a preliminary understanding of these concepts, please refer to the article: Cache three major problems and solutions!
II. config configuration class
@Configuration @EnableCaching public class RedisTemplateConfig extends CachingConfigurerSupport { private static Map<String, RedisCacheConfiguration> cacheMap = Maps.newHashMap(); @Bean(name = "stringRedisTemplate") @ConditionalOnMissingBean(name = "stringRedisTemplate") //If the container already has redisTemplate bean No more injection 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 Serialization of StringRedisSerializer template.setKeySerializer(keySerializer()); template.setHashKeySerializer(keySerializer()); // value Value serialization takes fastJsonRedisSerializer template.setValueSerializer(valueSerializer()); //Use fastjson serialize template.setHashValueSerializer(valueSerializer()); //Use fastjson serialize template.setConnectionFactory(lettuceConnectionFactory); return template; } /** * Add custom cache exception handling * Ignore exception when cache read / write exception * Reference resources:https://blog.csdn.net/sz85850597/article/details/89301331 */ @Override public CacheErrorHandler errorHandler() { return new IgnoreCacheErrorHandler(); } @SuppressWarnings("Duplicates") @Bean @Primary//When there are multiple managers, the annotation must be used on one manager to indicate that the manager is the default Manager public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) { // Default configuration RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(keyPair()) .serializeValuesWith(valuePair()) .entryTtl(Duration.ofSeconds(DEFAULT_TTL_SECS)) //Set expiration time .disableCachingNullValues(); // Other configurations for(MyCaches cache : MyCaches.values()) { cacheMap.put(cache.name(), RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(keyPair()) .serializeValuesWith(valuePair()) .entryTtl(cache.getTtl()) // .disableCachingNullValues() // Indicates that caching null values is not allowed .disableKeyPrefix() // Do not use default prefix // .prefixKeysWith("mytest") // Add custom prefix ); } /** Traverse MyCaches to add cache configuration*/ RedisCacheManager cacheManager = RedisCacheManager.builder( RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory) ) .cacheDefaults(defaultCacheConfig) .withInitialCacheConfigurations(cacheMap) .transactionAware() .build(); ParserConfig.getGlobalInstance().addAccept("mypackage.db.entity."); return cacheManager; } /** * key Serialization method * @return */ private RedisSerializationContext.SerializationPair<String> keyPair() { RedisSerializationContext.SerializationPair<String> keyPair = RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()); return keyPair; } private RedisSerializer<String> keySerializer() { return new StringRedisSerializer(); } /** * value Serialization method * @return */ private RedisSerializationContext.SerializationPair<Object> valuePair() { RedisSerializationContext.SerializationPair<Object> valuePair = RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()); return valuePair; } /** * Using fastjson serialization * @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; } /** Failure time */ private Duration ttl = Duration.ofHours(1); } }
Explanation
1. Annotation @ EnableCaching on class
Indicates that caching is enabled.
2. extends CachingConfigurerSupport
This class is very rich. In fact, if there is no special operation, you can not inherit this class.
This class can support dynamic selection of caching methods. For example, there are more than one caching scheme in the project, and ehcache is possible. Then you can customize the use of ehcache when redis is used. There are also some exceptions to deal with. I don't know very well. Please refer to:
3. Use of stringredistemplate and RedisTemplate
3. Use of cache annotations
@Cacheable used in query methods
@CachePut is used in update and save methods
@CacheEvict used on delete methods
Note that the @ Cacheable, @ CachePut methods must return the cached object. Because the AOP facet used by annotation indicates that the cache object is null if there is no return value.
@CacheConfig annotation on the class, you can choose which cache, cache manager and Key generator to use
Well, the above is a summary of some knowledge points in the project recently. If I have new experience in using cache in the future, I will update it synchronously.