使用spring data redis默认redisTemplate带来的序列化问题

场景:

两个服务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

扫描二维码关注公众号,回复: 8641753 查看本文章

通过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

发布了442 篇原创文章 · 获赞 222 · 访问量 115万+

猜你喜欢

转载自blog.csdn.net/u013905744/article/details/102893327
今日推荐