java.lang.ClassCastException: [使用 Redis 时,B 不能强制转换为 java.uti



我有以下代码:

jedis.mget(objects.toArray(new String[objects.size()]));

其中对象是字符串列表。代码在大多数情况下运行良好。但出乎意料地提出了以下异常。

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)

如果我再次运行相同的代码,它使用相同的数据运行良好。无法理解此类问题的原因。

TL;DR

Jedis 实例不是线程安全的,跨多个线程调用 Jedis 实例将导致这些类型的错误。尝试切换为使用JedisPool来管理连接的创建。

解释

我看到了这些完全相同的异常,在试图找出问题时,我在 Jedis 项目中遇到了类似的问题,解释 Jedis 不是线程安全的。

由于我在搜索相同的异常时发现了这个问题,我将分享我的特定案例的一些细节,以便对未来的读者有所帮助。

在我的特殊情况下,我使用 Spring Data Redis 中的RedisTemplate调用 SCAN 命令。我正在对连接生命周期之外生成的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();
    });
}

最新更新