【问题标题】:Can redis pipeline multiple commands that depend on previous ones?redis 可以管道多个依赖于先前命令的命令吗?
【发布时间】:2012-03-25 15:29:57
【问题描述】:

我对 redis 非常陌生,并且仍在使用它。我想测试它是否与我的项目相关,但我不确定我正在运行的特定命令。 SO 上的用户让我确信使用管道和事务的性能优势,所以我想我会问如何做到这一点。

基本上我有两个语句,我只想发布,而不必等待结果(似乎是管道衬里的一个很好的候选者。它看起来像这样:

Does valueX exist?
If it does insert valueY

它非常简单,但到目前为止,我一直在研究它的所有方法似乎都在等待 ValueX 是否存在的响应,并且因为我正在执行超过 10 亿次程序循环,它会使其停止运行。

这可能吗?如果它有帮助,我正在使用 Java,但还没有确定哪个客户端库(jedis 或 jredis,仍在测试)。实际上,我什至还没有完全确定 redis,但非常倾向于它(似乎对我在速度方面所做的事情有好处),所以任何建议都是可以接受的。

【问题讨论】:

    标签: database redis jedis


    【解决方案1】:

    不,目前不可能完成这样的事情。您需要的是目前缺少的功能,但它将在 2.6 版本的 Redis 中提供。这称为 LUA 脚本。您可以一并执行依赖于先前命令的服务器命令,而无需在客户端获取它们。更多详情请见here

    【讨论】:

    • 非常感谢您的回答。很高兴看到它的到来,但我真的不想等待,所以我想我可以在我的程序中自己构建这样的东西。这是逻辑,我有一个方法可以发送成对的查找/写入值,它将请求排队并在事务中运行它们?所以我的程序的其余部分可以在这部分排队时继续进行吗?
    • 您可以流水线一批查找命令,等待结果,然后流水线一些写命令。您可以在单独的线程/进程中执行此操作,以免在结果可用之前阻塞。
    【解决方案2】:

    Redis 不直接支持这一点,但在很多情况下这通常是需要的。更广义的“原子”模式是:

    Check multiple conditions
    If all satisfied, run multiple commands
    

    这可以通过简单的 lua 脚本来实现

    -- Validate conditions and exec commands if ok
    
    local params = cjson.decode(ARGV[1])
    
    -- Check conditions
    for __, check in pairs(params["if"]) do
        if #check == 2 then
            if check[1] ~= redis.call(unpack(check[2])) then return 0 end
        elseif check[2] == "==" then
            if check[1] ~= redis.call(unpack(check[3])) then return 0 end
        elseif check[2] == "!=" then
            if check[1] == redis.call(unpack(check[3])) then return 0 end
        elseif check[2] == ">" then
            if check[1] <= redis.call(unpack(check[3])) then return 0 end
        elseif check[2] == "<" then
            if check[1] >= redis.call(unpack(check[3])) then return 0 end
        else
            error('invalid operator "'..tostring(check[2])..'" (expected "==", "!=", ">" or "<")')
        end
    end
    
    -- Eval redis commands
    for __, exec in pairs(params["exec"]) do
        redis.call(unpack(exec))
    end
    
    return 1
    

    那么交易明细就可以简单的传递JSON.stringify(object):

    {
      // Conditions. All must be satisfied
      if: [
        [ 'initialized', '==', [ 'sget', 'custom-state' ] ]
      ],
      // Commands to execute if all conditions are satisfied
      exec: [
        [ 'set', 'custom-state', 'finished' ],
        [ 'incr', 'custom-counter' ]
      ]
    }
    

    在许多情况下,此类“条件事务”无需自定义脚本。

    查看https://github.com/nodeca/redis-if了解更多样本/测试/src。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-03
      • 2021-07-19
      • 2012-06-18
      相关资源
      最近更新 更多