Redis与Jedis客户端的交易异常 [英] Redis exception with transactions with Jedis client

查看:447
本文介绍了Redis与Jedis客户端的交易异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  redis.clients.jedis.exceptions.JedisDataException:在调用此方法之前,请关闭管道或多个块。 
在redis.clients.jedis.Response.get(Response.java:23)

这是实现。

  Jedis jedis = pool.getResource(); 

String id = message.getId();
事务事务= jedis.multi();
redis.clients.jedis.Response< java.lang.Boolean> response = transaction.sismember(ID_SET_REDIS_KEY,id);
if(response!= null&!response.get()。booleanValue()){
//将其添加到
transaction.sadd(ID_SET_REDIS_KEY,id);
transaction.publish(redisChannelName,message);
}
transaction.exec();
pool.returnResource(jedis);

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

解决方案

在结束交易之前,您不能获得获取的结果。 p>

如果您使用的是Redis> 2.6.X,您可以使用Lua Script创建一个带有逻辑的函数。请参阅 Redis Lua



这正是我在我的项目中保证并发。



编辑:包含更完整的示例



您应该创建一个像PUBLISHNX脚本(未测试)的东西:

  local shouldPublish = redis.call('SISMEMBER' KEYS [1],ARGV [1])$ ​​b 
$ b如果shouldPublish == 0
redis.call('SADD',KEYS [1],ARGV [1])$ ​​b $ b redis .call('PUBLISH',ARGV [2],ARGV [3])
end

你传递所有必要的参数,channel,messageId,message,controlKey。



PS。魏立是对的,你可以使用WATCH和一个循环来实现相同的结果,以便在并发的情况下重试,但是我仍然喜欢使用Lua脚本。


In order to avoid duplicates in my redis channel I'm checking if the message is already there by keeping an index in Redis set. Following is my implementation. However, it is giving an exception.

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

Here is the implementation.

          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);

I need to do the get inside the transaction because there are multiple publishers who may publish the exact same message.

解决方案

You can't have the result of your get before you end the transaction.

If you are using Redis > 2.6.X, what you can do is use a Lua Script to create a function with you logic. See Redis Lua

This is exactly what I did to guarantee concurrency in my project.

Edit: Including a more complete example

You should create something like a PUBLISHNX script (not tested):

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

And you pass all the arguments necessary, channel, messageId, message, controlKey.

PS. Wei Li is right, you could accomplish the same result using WATCH and a loop for retrying in case of concurrency, but I still prefer using a Lua script.

这篇关于Redis与Jedis客户端的交易异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆