场景:
两个服务A和B使用同一个redis cluster,
服务A使用redisTemplate 将key和value set进去
服务B使用redisTemplate get key
发现服务B在get key为nil
原因:
服务A中使用的是spring data redis默认的redisTemplate
而服务B中自定义了redisTemplate Bean,override了spring data redis默认的redisTemplate
先看服务A使用的默认的RedisTemplate的情况
通过这个类的说明,可以看到
By default, it uses Java serialization for its objects (through {@link JdkSerializationRedisSerializer}* ). For String intensive operations consider the dedicated {@link StringRedisTemplate}.
这就是问题所在,默认其会使用JdkSerializationRedisSerializer
通过redis-cli可以看到其key为
"\xac\xed\x00\x05t\x00\x13user:authcode:11111"
如果我get的时候仍然使用JdkSerializationRedisSerializer,那么是可以正常get的
服务B的情况
RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer);
但是如果我get的时候自定义了redisTemplate,并且使用了StringRedisSerializer,那么get key就得不到了
解决方案
统一两个项目使用的redisTemplate
JedisCluster
是一个smart客户端,而且性能很好
在spring boot中使用JedisCluster是比较好的选择
// 直接使用JedisPoolConfig,那就直接将检测idle开启 默认GenericObjectPoolConfig并没有开启
JedisPoolConfig config = new JedisPoolConfig();
// 需要密码连接的创建对象方式
JedisCluster jedisCluster = new JedisCluster(jedisClusterNodes, 2000, 2000, 5, "redis-pass",
config);
当redisTemplate和JedisCluster在项目中混合使用的时候,要清楚其使用的Serializer
1. redisTemplate默认使用JdkSerializationRedisSerializer,可以自定义redisTemplate,使其使用StringRedisSerializer
2. JedisCluster当key和value都为String的时候,使用StringRedisSerializer
如果你
set key-value是使用JedisCluster,
而get key是使用redisTemplate,其中key使用StringRedisSerializer,value使用默认的JdkSerializationRedisSerializer
那么是能够识别到这个key的,但是无法解析value,会报错:
StreamCorruptedException: invalid stream header
使用JedisCluster比redisTemplate的比较
JedisCluster的好处
1. 如上所述,JedisCluster默认使用StringRedisSerializer,key及value可读性更好
2. redisTemplate并没有返回值,而JedisCluster是可以获取到redis的返回值的
为什么redisTemplate没有返回值呢?
看一下源码
org.springframework.data.redis.connection.jedis.JedisClusterConnection#setEx
在这里可以看到,其实
redis.clients.jedis.BinaryJedisCluster#setex是有返回值的
但是cluster.setex这里并没有返回这个返回值
导致我们业务代码中
void set(K key, V value, long timeout, TimeUnit unit);
这里也没有返回值了
redisTemplate的好处
其是spring data 提供的,屏蔽掉了底层实现,比如说我想使用jedis实现,也可以使用Lettuce