Redis与Jedis客户端的交易异常 [英] Redis exception with transactions with Jedis client
问题描述
为了避免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屋!