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

本文分析了在Spring Data Redis与JedisCluster混用时,因串行化方式不同导致的数据读取问题。服务A使用默认的JdkSerializationRedisSerializer存储数据,而服务B使用StringRedisSerializer尝试读取,导致读取失败。文章提供了统一串行化策略的解决方案,建议使用JedisCluster以提高性能和可读性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

场景:

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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值