Exception 与Jedis客户端进行交易的Redis异常

Exception 与Jedis客户端进行交易的Redis异常,exception,redis,jedis,Exception,Redis,Jedis,为了避免在我的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) 下面是实现

为了避免在我的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);
绝地武士=pool.getResource(); String id=message.getId(); 事务处理=jedis.multi(); redis.clients.jedis.Response Response=transaction.sismember(ID\u SET\u redis\u KEY,ID); if(response!=null&&!response.get().booleanValue()){ //将其添加到 transaction.sadd(ID\u SET\u REDIS\u KEY,ID); 事务发布(名称、消息); } transaction.exec(); 返回资源池(绝地);
我需要进入事务,因为有多个发布者可能发布完全相同的消息

在结束交易之前,您不能得到您的get的结果

如果您使用的是Redis>2.6.X,那么您可以使用Lua脚本创建一个带有逻辑的函数。看

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

编辑:包括更完整的示例

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

然后传递所有必要的参数,channel,messageId,message,controlKey


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

根据@Axexandre上面的评论,我使用下面的代码执行该操作

导入redis.clients.jedis.jedis

public class RedisLuaDemo {

    public static void main(String args[])
    {
        Jedis jedis = new Jedis("localhost");
        jedis.sadd("a", "b");
        int numberOfKeys = 1 //we are using only one Redis set 'setvar' 
        jedis.eval("if redis.call('sismember', KEYS[1], ARGV[1]) == 1 then return ARGV[2] else redis.call('sadd', KEYS[1], ARGV[1]); redis.call('publish', 'channel.mychannel', ARGV[2])  end", numberOfKeys, "setvar", "joe", "message from joe!");

    }
}
下面是关于脚本的更多信息。理解语法花了一些时间

if redis.call('sismember',key[1],ARGV[1])==1
eqvalent to
sismember setvar joe

redis.call('sadd', KEYS[1], ARGV[1]);
出于某种原因,如果我没有这个绝地武士行我得到一个异常(见下文)


实际上,您可以使用“WATCH”获得进入事务的结果。我认为没有必要在这里编写lua脚本@西曼塔苏美亚酒店
redis.call('sadd', KEYS[1], ARGV[1]);
Exception in thread "main" java.lang.NullPointerException
    at redis.clients.jedis.Connection.setTimeoutInfinite(Connection.java:41)
    at redis.clients.jedis.Jedis.eval(Jedis.java:2763)
    at redis.RedisLuaDemo.main(RedisLuaDemo.java:13)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)