我有以下代码:
jedis.mget(objects.toArray(new String[objects.size()]));
其中objects是一个字符串列表。代码在大多数情况下运行良好。但是出现意外情况后会出现异常情况。
java.lang.ClassCastException: [B cannot be cast to java.util.List
at redis.clients.jedis.Connection.getBinaryMultiBulkReply(Connection.java:221)
at redis.clients.jedis.Connection.getMultiBulkReply(Connection.java:214)
at redis.clients.jedis.Jedis.mget(Jedis.java:383)
如果我再次运行相同的代码,它会运行相同的数据。无法理解此类问题的原因。
答案 0 :(得分:-1)
TL; DR
Jedis实例不是线程安全的,跨多个线程对Jedis实例的调用将导致这些类型的错误。尝试切换为使用JedisPool
来管理连接的创建。
说明
我看到了这些完全相同的异常,并且在试图找出问题时,我遇到了类似的issue on the Jedis project解释杰迪斯不是线程安全的。
由于我在搜索同一例外时发现了这个问题,因此我将分享我的特殊情况的一些细节,以便为将来的读者提供帮助。
在我的特定情况下,我使用Spring Data Redis中的SCAN
调用RedisTemplate
命令。我正在连接生命周期之外调用生成的Cursor
。
我的原始代码如下。
public Long size() {
Cursor<byte[]> scan = redisTemplate.execute((RedisConnection connection) -> connection.scan(ScanOptions.scanOptions().match(prefix + "*").build()));
AtomicLong count = new AtomicLong();
scan.forEachRemaining(bytes -> count.getAndIncrement());
return count.get();
}
稍作更改后,我发现执行此操作的正确方法是简单地将光标交互移动到执行lambda内。
public Long size() {
return redisTemplate.execute((RedisConnection connection) -> {
Cursor<byte[]> scan = connection.scan(ScanOptions.scanOptions().match(prefix + "*").build());
AtomicLong count = new AtomicLong();
scan.forEachRemaining(bytes -> count.getAndIncrement());
return count.get();
});
}