Redis(六) RedisTemplate客户端
前言 RedisTemplate客户端是spring对底层依赖Jedis、Lettuce的高度封装,在Springboot1.X版本默认使用Jedis进行自动装配,在Springboot2.X版本默认使用Lettuce进行自动装配。
1.依赖 1 2 3 4 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
2.序列化 2.1 序列化对象 RedisTemplate客户端在存取数据时,并不需要像Jedis、Lettuce那样通过硬代码手动序列化(比如json、java serialization等),spring提供了多种序列化对象,然后通过代码配置的方式制定序列化器:
GenericToStringSerializer(可以将任何对象泛化为字符串并序列化)
JacksonJsonRedisSerializer(序列化object对象为json字符串)
Jackson2JsonRedisSerializer(和JacksonJsonRedisSerializer一样)
JdkSerializationRedisSerializer(序列化java对象,需要实现Serializable接口)
StringRedisSerializer(简单的字符串序列化)
2.2 性能对比 JdkSerializationRedisSerializer属于JDK原生序列化对象,效率自然是最快的,缺点是序列化后的结果字符串最长,也就意味着占用内存相对多点。Jackson2JsonRedisSerializer是将数据转化为json字符串,需要解析结构因此最慢,但生成的字符串结果较为紧凑。
3.配置文件 由于Redis依赖基于springboot的自动装配,所以只需要配置文件参数即可。
3.1 单机版 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # redis数据库索引 spring.redis.database=0 # redis服务器IP spring.redis.host=127.0.0.1 # redis服务器端口 spring.redis.port=6379 # redis服务器密码 spring.redis.password=abcdef #连接池最大连接数(使用负值表示没有限制) jedis.pool.max-active=8 # 连接池最大阻塞等待时间(使用负值表示没有限制) jedis.pool.max-wait=-1 # 连接池中的最大空闲连接 jedis.pool.max-idle=8 # 连接池中的最小空闲连接 jedis.pool.min-idle=8 # 连接超时时间(毫秒) jedis.pool.timeout=10000
3.2 主从版 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # redis数据库索引 spring.redis.database=0 # redis服务器IP spring.redis.host=127.0.0.1 # redis服务器端口 spring.redis.port=6379 # redis服务器密码 spring.redis.password=abcdef #连接池最大连接数(使用负值表示没有限制) jedis.pool.max-active=8 # 连接池最大阻塞等待时间(使用负值表示没有限制) jedis.pool.max-wait=-1 # 连接池中的最大空闲连接 jedis.pool.max-idle=8 # 连接池中的最小空闲连接 jedis.pool.min-idle=8 # 连接超时时间(毫秒) jedis.pool.timeout=10000
3.3 哨兵版 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # redis数据库索引 spring.redis.database=0 # redis服务器IP spring.redis.host=127.0.0.1 # redis服务器端口 spring.redis.port=6379 # redis服务器密码 spring.redis.password=abcdef #连接池最大连接数(使用负值表示没有限制) jedis.pool.max-active=8 # 连接池最大阻塞等待时间(使用负值表示没有限制) jedis.pool.max-wait=-1 # 连接池中的最大空闲连接 jedis.pool.max-idle=8 # 连接池中的最小空闲连接 jedis.pool.min-idle=8 # 连接超时时间(毫秒) jedis.pool.timeout=10000
3.4 集群版 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 # redis数据库索引 spring.redis.database=0 # redis集群节点 spring.redis.cluster.nodes=175.24.30.43:7000,175.24.30.43:7001,175.24.30.43:7002 # 最大重定向次数(默认5) spring.redis.cluster.max-redirects=3 # redis服务器密码 spring.redis.password=paxos1990.. # 连接池最大连接数(默认8) spring.redis.jedis.pool.max-active=8 # 连接池最大空闲连接(默认8) spring.redis.jedis.pool.max-idle=8 # 连接池的最小空闲连接(默认0) spring.redis.jedis.pool.min-idle=0 # 连接池最大阻塞等待时间(默认-1,表示没有限制) spring.redis.jedis.pool.max-wait=-1
4.客户端对象 4.1 StringRedisTemplate 如果你对redis的操作仅涉及到字符串类型,那么直接使用Spring提供的StringRedisTemplate类即可,此类内部使用StringRedisSerializer序列化,代码方面直接注入:
1 2 @Autowired public StringRedisTemplate stringRedisTemplate;
4.2 自定义RedisTemplate 通常的项目中不可能只用Redis来存储字符串,也不可能把所有对象一股脑转成Json字符串存储,因此需要额外注入一个RedisTemplate用于对象的存储,并且可以针对不同的数据结构设置不同的序列化规则,配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate (RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate(); template.setConnectionFactory(factory); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); template.setKeySerializer(stringRedisSerializer); template.setHashKeySerializer(stringRedisSerializer); template.setValueSerializer(jackson2JsonRedisSerializer); template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); 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) { return redisTemplate.opsForZSet(); } }
5.Springboot自动装配 5.1 自动装配类
从RedisTemplate的自动装配类可以看出来,Springboot会自动向IOC注入RedisTemplate、StringRedisTemplate俩个类,但都是有前提条件且注入的操作都比较粗糙,很多属性都没有设置,所以这俩个类的注入只会在你没有手动注入的情况下生效。
另外RedisTemplate底层依赖Lettuce或Jedis,至于使用哪个完全依赖配置方法中的参数RedisConnectionFactory,这个类有LettuceConnectionConfiguration 、JedisConnectionConfiguration 俩个实现类,分别对应Lettuce和Jedis俩个客户端。
5.2 默认底层依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Configuration( proxyBeanMethods = false ) @ConditionalOnClass({RedisClient.class}) class LettuceConnectionConfiguration extends RedisConnectionConfiguration { @Bean @ConditionalOnMissingBean({RedisConnectionFactory.class}) LettuceConnectionFactory redisConnectionFactory (ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers, ClientResources clientResources) throws UnknownHostException { LettuceClientConfiguration clientConfig = this .getLettuceClientConfiguration(builderCustomizers, clientResources, this .getProperties().getLettuce().getPool()); return this .createLettuceConnectionFactory(clientConfig); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Configuration( proxyBeanMethods = false ) @ConditionalOnClass({GenericObjectPool.class, JedisConnection.class, Jedis.class}) class JedisConnectionConfiguration extends RedisConnectionConfiguration { @Bean @ConditionalOnMissingBean({RedisConnectionFactory.class}) JedisConnectionFactory redisConnectionFactory (ObjectProvider<JedisClientConfigurationBuilderCustomizer> builderCustomizers) throws UnknownHostException { return this .createJedisConnectionFactory(builderCustomizers); } }
从代码可以看出,Springboot会将这俩个客户端的配置类都尝试注册IOC(包括包含的RedisConnectionFactory),但是在Springboot2.X版本里默认只包含Lettuce的依赖,所以在@ConditionalOnClass 的注入限制条件下,默认使用的是Lettuce客户端。
5.3 Springboot2.X使用Jedis 如果想要在Springboot2.X的RedisTemplate使用Jedis客户端实现,就需要对依赖进行处理,排除包含的Lettuce依赖,再添加Jedis依赖。这样Lettuce注入时,就无法满足@ConditionalOnClass的条件,而Jedis正好满足。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <exclusions> <!-- 排除lettuce依赖 --> <exclusion> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency>
注:Springboot1.X版本仅支持Jedis底层依赖,有兴趣可以自己看源码。