【问题标题】:Decrement score in Redis or remove if 0在 Redis 中减少分数,如果为 0,则删除
【发布时间】:2020-11-13 02:47:42
【问题描述】:

如何将排序集中的一个 Redis 元素的分数减 1,或者如果它的值为 0,则将其删除?目前我正在使用$redis.zincrby user_cart, -1, params[:product_id](Rails 4.1.4),但我得到了负值。

提前致谢!

【问题讨论】:

    标签: redis


    【解决方案1】:

    ZINCRBY 的回复是新分数,因此您可以查看它,如果它是 ZREM。

    【讨论】:

      【解决方案2】:

      您可以编写一个在 Redis 服务器端执行此操作的 LUA 脚本。 你可以用这个:

      local ans = redis.call('ZINCRBY', KEYS[1], ARGV[1], ARGV[2])
      if   tonumber(ans) < 1 then
          redis.call('ZREM', KEYS[1], ARGV[2]) 
      end
      return (tonumber(ans) < 1 and '-1' or ans)
      

      任何删除都会返回-1,否则会返回新的会员分数。

      这是一个来自测试运行的 sinnpet:

      evalsha 6e8a61a2367772383f535587ce75e92d4e047fcf 1 myzset 3 blah
      "3"
      zrank myzset blah
      (integer) 0
      evalsha 6e8a61a2367772383f535587ce75e92d4e047fcf 1 myzset -3 blah
      "-1"
      zrank myzset blah
      (nil)
      evalsha 6e8a61a2367772383f535587ce75e92d4e047fcf 1 myzset -3 blah
      "-1"
      zrank myzset blah
      (nil)
      

      【讨论】:

      • 不错。删除元素时为什么不返回“0”而不是“-1”?
      • @EduardoParejaTobes 没有理由。 0 也是一个很好的答案。但是将更难更改逻辑以允许 0 并且稍后仅删除负数。
      • 如果您在客户端使用流水线并想要像这样的特定行为,这个答案比接受的答案更有意义。
      【解决方案3】:

      您询问了排序集,但这个问题也与 INCR/DECR 键有关。这是一个使用 Lua 脚本和 PHP Predis 的示例:

      $lua = <<<LUA
          local c = redis.call('DECR', KEYS[1])
          if c == 0 then 
              redis.call('DEL', KEYS[1]) 
          end
          return c
      LUA;
      
      // Argument 1 is the Lua script.
      // Argument 2 is the number of keys being passed to the script (always 1 for this script).
      // Argument 3 is the key to decrement/delete.
      $count = $predisClient->eval($lua, 1, 'foo-bar-key');
      

      另一种方法是使用 WATCH + MULTI + EXEC 事务,但 Redis 社区似乎更喜欢 Lua。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-10
        • 1970-01-01
        • 1970-01-01
        • 2014-04-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多