【问题标题】:ERR EXEC without MULTI - Vertx-Redis 3.7.0没有 MULTI 的 ERR EXEC - Vertx-Redis 3.7.0
【发布时间】:2019-05-16 15:55:32
【问题描述】:

我正在尝试用vertx-redis-client 执行multi,版本是3.7.0。文档非常糟糕,我什至不知道如何使用multi。我以某种方式尝试了以下代码。输出非常不一致。有时它会正常执行,有时会抛出错误说ERR EXEC without MULTI

代码:

        Map<String,String> keyFields =  new HashMap<>();
        keyFields.put("{test}:t1", "f1");
        keyFields.put("{test}:t2", "f2");
        redisAPI.multi(ar1 -> {
            for (Map.Entry<String, String> e: keyFields.entrySet()) {
                redisAPI.hget(e.getKey(), e.getValue(), ar2 -> {
                    if ("QUEUED".equals(ar2.result().toString())) {
                        System.out.println("its queued");
                        redisAPI.exec(execEvent -> { 
                            System.out.println(execEvent);
                            System.out.println("Result is: "+ execEvent.result());
                        });
                    } else {
                        System.out.println("Result is: "+ ar2.result());
                    }
                });
            }
        });

输出错误:

its queued
Future{cause=ERR EXEC without MULTI}
Result is: null
its queued
Future{cause=ERR EXEC without MULTI}
Result is: null

没有错误:

Result is: v2
Result is: v1

代码有什么问题?

【问题讨论】:

    标签: vert.x


    【解决方案1】:

    这段代码有一个小错误。让我们看看它在 redis 命令方面发生了什么:

    MULTI // Line 4
    HGET "{test}:t1", "f1" // Line 6 (inside loop)
    EXEC // Line 9 (because the response is immediate the callback gets called here)
    HGET "{test}:t2", "f2" // Line 6 (second iteration of the loop)
    EXEC // Line 9 Fail since there's no multi
    

    即使事情会有点延迟,也会有错误:

    MULTI // Line 4
    HGET "{test}:t1", "f1" // Line 6 (inside loop)
    HGET "{test}:t2", "f2" // Line 6 (second iteration of the loop)
    EXEC // Line 9
    EXEC // Line 9 Fail since there's no multi
    

    最后,预期的结果与测试不匹配,因为您调用 HGET 时没有填充初始哈希(可能为了简化示例而省略了它)。

    我会推荐一种不同的方法:

    redis.batch(Arrays.asList(
      cmd(MULTI),
      cmd(HGET).arg("{test}:t1").arg("f1"),
      cmd(HGET).arg("{test}:t2").arg("f2");
      cmd(EXEC)
    ), batch -> {
      // At this moment you have all responses
    });
    

    这种方法可以避免您与异步循环作斗争。而且确实没有按应有的记录。

    【讨论】:

    • 我试过批处理。我在同一个插槽中拥有所有钥匙。仍然收到错误:Future{cause=RedisClusterClient does not handle batching commands with keys across different slots. TODO: Split the command into slots and then batch.}
    • redis 客户端不支持分布式事务,你应该连接到你知道拥有所有密钥的节点并在那里运行事务。
    • 谢谢 Paulo,我们什么时候可以期待在集群模式下对 batch 的支持
    • 可能我们需要为这种情况添加一个检查,所有命令都在同一个插槽上或不需要特定的插槽。但真正的分布式事务由于其复杂性而超出了范围。
    • @rmn.nish 这个github.com/vert-x3/vertx-redis-client/pull/156 实现了这一点并将在 4.0
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 1970-01-01
    • 2020-11-08
    • 2013-03-24
    • 2012-06-24
    • 2012-08-17
    • 2013-12-22
    相关资源
    最近更新 更多