【发布时间】:2020-11-13 02:47:42
【问题描述】:
如何将排序集中的一个 Redis 元素的分数减 1,或者如果它的值为 0,则将其删除?目前我正在使用$redis.zincrby user_cart, -1, params[:product_id](Rails 4.1.4),但我得到了负值。
提前致谢!
【问题讨论】:
标签: redis
如何将排序集中的一个 Redis 元素的分数减 1,或者如果它的值为 0,则将其删除?目前我正在使用$redis.zincrby user_cart, -1, params[:product_id](Rails 4.1.4),但我得到了负值。
提前致谢!
【问题讨论】:
标签: redis
ZINCRBY 的回复是新分数,因此您可以查看它,如果它是 ZREM。
【讨论】:
您可以编写一个在 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)
【讨论】:
您询问了排序集,但这个问题也与 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。
【讨论】: