From Spring Boot 2.x onwards Jedis has been replaced as the preferred Redis client. Of course, Spring Boot 2.x still supports Jedis, and you can switch clients at will.
Lettuce
Lettuce is a scalable thread-safe Redis client that supports synchronous, asynchronous and responsive modes. Multiple threads can share a connection instance without having to worry about multi-threaded concurrency. It is built on the excellent Netty NIO framework and supports advanced Redis features such as Sentinel, clustering, pipelining, automatic reconnection, and Redis data model
Jedis is implemented as a directly connected Redis Server. If it is not thread-safe in a multi-threaded environment, the only way to do this is to add physical connections to each Jedis instance using connection pooling.
The connection is Netty based, and StatefulRedisConnection can be accessed concurrently between multiple threads. The StatefulRedisConnection is thread-safe. Therefore, a StatefulRedisConnection can satisfy concurrent access in a multi-threaded environment. Of course, this is also a scalable design. If a connection instance is not enough, it can also be added as needed.
Spring Boot 2.0 integrates with Redis
It usually takes 4 steps
- Introduction of depend on
- Configure redis
- Custom RedisTemplate (recommended)
- Custom Redis action classes (recommended)
Introduction of depend on
<! --redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <! Commons -pool2</artifactId> Commons -pool2</artifactId> </dependency> <! --jackson--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency>Copy the code
- If you are using a lettuce client, you need to introduce commons-pool2 connection pool.
- If you want to serialize redis values using JSON, you need to introduce Jackson
Configure redis
# redis.host=localhost # port=6379 # redis.port=6379 Default is null spring.redis. Password = # database used, Database =0 # client timeout, default is 2000ms spring.redis.timeout=2000ms ## Jedis client configuration (from Spring Boot 2.x In the beginning, it is no longer recommended to use jedis client) ## The maximum waiting time for establishing a connection is 1ms by default. A value of -1 indicates an infinite wait until allocation is successful. # spring. Redis. Jedis. Pool. Max - dalian wait = 1 ms # # the most number of connections, the default is 8, negative said there is no limit to the # spring. Redis. Jedis. Pool. The Max - active = 8 # # the largest number of idle connections, 8 by default. Negative said there is no limit to the # spring. Redis. Jedis. Pool. The Max - idle = 8 # # the minimum number of idle connections, the default is 0. # spring. Redis. Jedis. Pool. Min - idle = 0 # lettuce client configuration (from spring Boot 2 x, it is recommended to use lettuce client) # connect maximum wait time, default 1 ms, beyond the time will throw exceptions. A value of -1 indicates an infinite wait until allocation is successful. Spring. Redis. Lettuce. Pool. Max - wait = # 1 ms dalian the most number of connections, the default is 8, negative said there is no limit to the spring. Redis. Lettuce. The pool. The Max - active = 8 # maximum number of idle connections, 8 by default. Negative said there is no limit to the spring. Redis. Lettuce. The pool. The Max - idle = 8 # minimum number of idle connections, the default is 0. Spring. Redis. Lettuce. Pool. Min - idle = 0 # set the closing of the connection timeout spring. Redis. Lettuce. The shutdown - timeout = 100 msCopy the code
Custom RedisTemplate
RedisTemplate is the Redis operation class provided by Spring, through which we can do most of the Redis operations.
As long as we import redis dependencies and have redis connection information configured correctly, SpringBoot will give us a default RedisTemplate based on our configuration.
But there are two things about the RedisTemplate generated by default that don’t quite fit into your daily development habits
- Default generated
RedisTemplate<K, V>
The receivedkey
andvalue
For generics, type conversion is often required, so direct use is not very convenient - Is generated by default RedisTemplate serialization, use JdkSerializationRedisSerializer, storage to redis, content of binary bytes, unfavorable to view the original content
For the first problem, the general convention is to replace RedisTemplate
with RedisTemplate
, So for the second problem, you usually serialize the data to JSON and store it in Redis, and the other nice thing about serializing to JSON is that across languages, Other languages can also read what you store in Redis
To achieve the above two purposes, we need to customize our own RedisTemplate.
As follows, create a Config class to configure your custom RedisTemplate
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
/ / configuration json serializer - Jackson2JsonRedisSerializer
Jackson2JsonRedisSerializer<Object> jacksonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper()
// Extend the serializer to add support for serialization and deserialization of time classes in java.time.* packages
.registerModule(new ParameterNamesModule())
.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule());
jacksonSerializer.setObjectMapper(objectMapper);
/ / create and configure a custom RedisTemplateRedisOperator
RedisTemplate<String, Object> template = new RedisTemplate<>();
// Serialize key to a string
template.setKeySerializer(new StringRedisSerializer());
// Serialize the hash key to a string
template.setHashKeySerializer(new StringRedisSerializer());
// Serialize value to JSON
template.setValueSerializer(jacksonSerializer);
// Serialize the hash value to JSON
template.setHashValueSerializer(jacksonSerializer);
// Set the connector
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
@Bean
public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForValue();
}
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
returnredisTemplate.opsForZSet(); }}Copy the code
Custom Redis action classes
Although RedisTemplate has encapsulated redis operations to a certain extent, it is still inconvenient to use it directly. In actual development, RedisTemplate is generally further encapsulated to form a simple and convenient REDis operation class.
Of course, you can choose not to wrap, depending on personal preference.
Refer to the custom Redis action class based on RedisTemplate for detailed encapsulation classes.
Spring Cache
Spring Cache is a Spring solution for caching scenarios. Use @cacheput, @cacheevict, and @cacheable annotations to store, query, and delete the cache
When spring-boot-starter-data-redis is introduced, using the @enablecaching annotation on the @Configuration class will “activate” the Spring Cache.
Spring Cache configures the default Cache manager and key generator for us, but the serialization of the Cache by the Cache manager and the keys generated by the key generator are not easy to read. Custom cache managers and key generators are recommended
If you don’t need Spring Cache, don’t bother.
Note: Spring Cache does not only use Redis as a Cache container, but other Cache middleware, such as MemCache, supports it.Copy the code
Configure Spring Cache
Type =redis # The expiration time of the cache added via the Spring cache annotation, in seconds (this is a custom attribute) cache.expireTime=60Copy the code
The most important thing is to specify the type of cache to use and a custom variable that the cache manager will use later
Configure the cache manager and key generator
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.KeyGenerator; 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.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.lang.reflect.Method; import java.time.Duration; @configuration @enablecaching Public class CacheConfig extends CachingConfigurerSupport { @value ("${cache.expireTime}") private int cacheExpireTime; @cacheable; @cacheevict; Key generation policy * This configuration applies to all caches managed by the cache manager * The final generated key is the cache class annotation specified by cacheNames:: class name: method name # Parameter value 1, parameter value 2... * * @return */ @Bean public KeyGenerator keyGenerator() { return new KeyGenerator() { @Override public Object generate(Object target, Method method, Object... params) { StringBuffer sb = new StringBuffer(); sb.append(target.getClass().getName()); sb.append(":"); sb.append(method.getName()); sb.append("#"); for (Object obj : params) { sb.append(obj.toString()); sb.append(","); } return sb.substring(0, sb.length() - 1); }}; } /** * configure the CacheManager */ @bean public CacheManager CacheManager (RedisConnectionFactory factory) {// configure the json serializer - Jackson2JsonRedisSerializer Jackson2JsonRedisSerializer<Object> jacksonSerializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jacksonSerializer.setObjectMapper(objectMapper); // The key point is that the serialization used by Spring Cache annotations comes from this. Without this configuration, the JDK's own serialization is not affected. Just print it out is not suitable for the human eye to identify RedisCacheConfiguration cacheConfig = RedisCacheConfiguration. DefaultCacheConfig () / / key serialization into a string SerializeKeysWith (RedisSerializationContext. SerializationPair. FromSerializer (new StringRedisSerializer ())) / / value Serialize to JSON SerializeValuesWith (RedisSerializationContext. SerializationPair. FromSerializer (jacksonSerializer)) / / / / value serialization way Sets the cache expiration time, the unit seconds. EntryTtl (Duration. OfSeconds (cacheExpireTime)) / / no cache a null value. DisableCachingNullValues (); return RedisCacheManager.builder(factory) .cacheDefaults(cacheConfig) .build(); }}Copy the code
conclusion
Most of the tutorials on integrating Redis with Spring Boot on the Internet are about configuring Redis and Spring Cache together, which can be misleading.
Redis and Spring Cache are two different things, so I purposely split the above tutorial into two configuration files.
You can use Redis without Spring Cache, or vice versa.
So why are they often discussed together? The reason is that there is also a link
From the perspective of Reids, Spring Cache provides a convenient way to manipulate REids and provides an excellent solution for caching scenarios.
From a Spring cache perspective, REIDS provide a cache container that can be placed in REids.
The cache manager’s manipulation of REids is also implemented through the redisTemplate.