解决Jedis异常之 java.lang.ClassCastException: java.lang.Long cannot be cast to [B

问题描述

使用jedis sdk访问redis时,有时会抛如下异常

java.lang.ClassCastException: java.lang.Long cannot be cast to [B
	at redis.clients.jedis.Connection.getBinaryBulkReply(Connection.java:259)
	at redis.clients.jedis.Connection.getBulkReply(Connection.java:248)
	at redis.clients.jedis.Jedis.hget(Jedis.java:674)

有时可能还会伴随着超时异常:

redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out
	at redis.clients.util.RedisInputStream.ensureFill(RedisInputStream.java:202)
	at redis.clients.util.RedisInputStream.readByte(RedisInputStream.java:40)
	at redis.clients.jedis.Protocol.process(Protocol.java:151)
	at redis.clients.jedis.Protocol.read(Protocol.java:215)
	at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:340)
	at redis.clients.jedis.Connection.getBinaryBulkReply(Connection.java:259)
	at redis.clients.jedis.Connection.getBulkReply(Connection.java:248)
	at redis.clients.jedis.Jedis.hget(Jedis.java:674)

原因&解决

主要有以下三类原因:

  1. 一个jedis连接在使用时抛出异常(如超时异常)后被返回连接池,这个连接下次使用时就可能跑类似异常,具体跟sockt buffer有上次请求数据的有关,参考链接1。

    针对这种情况,需要将jedis正确close,有些文章可能会说需要调用returnBrokenResource方法,这已经是个远古方法了,至少在2.9.0以上,直接close即可,如果进行了异常捕获,则需要在finally中进行close。

  2. 多线程访问jedis对象

    根据jedis的文档,JedisPool线程安全而Jedis非线程安全,检查代码是否有多线程逻辑。

  3. redis集群资源负载重、写满等

    我这里就是这个原因,代码中对redis先读后写,不停抛这个异常。如果注释掉写,只读运行没问题。注释掉读,就开始抛下面的异常,这种负载重抛异常的情况在链接2的issue也有人提及。

    redis.clients.jedis.exceptions.JedisDataException: ERR 
    	at redis.clients.jedis.Protocol.processError(Protocol.java:127)
    	at redis.clients.jedis.Protocol.process(Protocol.java:161)
    	at redis.clients.jedis.Protocol.read(Protocol.java:215)
    	at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:340)
    	at redis.clients.jedis.Connection.getOne(Connection.java:322)
    	at redis.clients.jedis.ShardedJedisPipeline.sync(ShardedJedisPipeline.java:44)
    

    最后找运维申请了个新redis就正常读写了,如果你们redis是自己的维护的,就检查下日志吧。

参考资料:

  1. https://*.com/questions/40769135/jedis-java-lang-long-cannot-be-cast-to-b

  2. https://github.com/redis/jedis/issues/186

  3. https://www.pianshen.com/article/70711745627/