小编典典

与Jedis客户进行交易时的Redis例外

redis

为了避免在Redis通道中出现重复,我通过在Redis中设置索引来检查消息是否已经存在。以下是我的实现。但是,这是一个例外。

redis.clients.jedis.exceptions.JedisDataException: Please close pipeline or multi block before calling this method.
    at redis.clients.jedis.Response.get(Response.java:23)

这是实现。

          Jedis jedis = pool.getResource();

          String id = message.getId();
          Transaction transaction = jedis.multi();
          redis.clients.jedis.Response<java.lang.Boolean> response = transaction.sismember(ID_SET_REDIS_KEY, id);
          if (response != null && !response.get().booleanValue()) {
                //add it to the 
                transaction.sadd(ID_SET_REDIS_KEY, id);
                transaction.publish(redisChannelName, message);
            }
            transaction.exec();
            pool.returnResource(jedis);

我需要在事务内部进行获取,因为有多个发布者可能会发布完全相同的消息。


阅读 290

收藏
2020-06-20

共1个答案

小编典典

结束交易之前,您 无法获得获取 结果。

如果使用Redis> 2.6.X,则可以使用Lua脚本通过逻辑来创建函数。参见Redis
Lua

这正是我为保证项目中的并发性所做的事情。

编辑:包括一个更完整的示例

您应该创建类似PUBLISHNX脚本(未经测试)的内容:

local shouldPublish = redis.call('SISMEMBER', KEYS[1], ARGV[1])

if shouldPublish == 0
    redis.call('SADD', KEYS[1], ARGV[1])
    redis.call('PUBLISH', ARGV[2], ARGV[3])
end

然后传递所有必需的参数,即channel,messageId,message,controlKey。

PS。Wei Li是正确的,在并发的情况下,您可以使用WATCH和循环进行重试来实现相同的结果,但是我仍然更喜欢使用Lua脚本。

2020-06-20