You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

多线程环境下Spring-Data-Redis集成Jedis遇类型转换异常求助

解决多线程环境下Jedis结合Spring-Data-Redis的ClassCastException问题

你碰到的这个ClassCastException: [B cannot be cast to java.lang.Long异常,是调用rPush操作时触发的,结合你的环境配置和代码,我来帮你定位问题并给出可行的解决方案。

你的环境信息

  • Jedis版本:2.9.0
  • Spring-Data-Redis版本:1.8.12.RELEASE
  • Redis服务器版本:3.0.6

异常根源分析

从栈信息里的redis.clients.jedis.Connection.getIntegerReply(Connection.java:265)可以看出,Jedis试图把Redis返回的二进制数据([B就是byte数组)转换成Long类型时失败了。结合多线程场景,主要有两个核心原因:

  1. 连接池复用导致的响应污染:JedisPool是连接复用机制,多线程下如果某个线程没处理完之前的命令响应,或者连接归还池时没清理干净状态,后续线程复用这个连接执行rPush时,可能读到上一个命令遗留的二进制响应——而rPush本来应该返回Long类型的列表长度,自然就会触发类型转换错误。
  2. Redis key的类型不匹配:如果你执行rPush的key在Redis中不是list类型(比如是string),执行rPush会返回错误,但客户端序列化层可能把错误响应转换成了byte数组,最终导致类型转换异常。

具体解决方案

方案1:优化连接池配置,避免脏连接复用

调整你的JedisPoolConfig,增加归还连接时的有效性检查,确保脏连接不会被复用:

jedisPoolConfig.setTestOnReturn(true); // 新增这行
jedisPoolConfig.setTestOnBorrow(true); // 你已有的配置

另外,如果你在代码中手动获取过JedisConnection(比如直接调用jedisConnectionFactory.getConnection()),一定要在finally块中关闭连接,避免连接状态残留:

JedisConnection conn = null;
try {
    conn = jedisConnectionFactory.getConnection();
    // 执行Redis操作
} finally {
    if (conn != null) {
        conn.close();
    }
}

注:你的RedisTemplate本身会自动管理连接,但开启了事务支持,要确保事务使用流程正确,避免连接被长时间占用。

方案2:检查Redis中目标key的类型

登录Redis服务器,用TYPE命令检查你执行rPush的key类型:

redis-cli TYPE your-target-key

如果返回的不是list,说明这个key之前被用其他类型的命令操作过(比如SET),需要先删除该key:

redis-cli DEL your-target-key

之后再执行rPush操作,就能保证类型一致了。

方案3:升级版本修复兼容性bug

你当前使用的Spring-Data-Redis 1.8.12.RELEASE和Jedis 2.9.0虽然理论兼容,但该版本分支存在一些连接复用相关的已知小bug。可以尝试升级到同分支的稳定版:

  • 将Spring-Data-Redis升级到1.8.23.RELEASE(1.8.x分支最新稳定版)
  • 将Jedis升级到2.9.3(2.9.x分支最新稳定版)

方案4:排查事务支持的影响

你开启了redisTemplate.setEnableTransactionSupport(true),多线程下如果事务使用不当,可能导致连接状态异常。可以暂时关闭事务支持,观察异常是否消失,以此排查是否是事务导致的问题:

redisTemplate.setEnableTransactionSupport(false);

内容的提问来源于stack exchange,提问作者zhaokun

火山引擎 最新活动