如何在Redis中仅在键存在时执行HSET操作?

5

我想运行一个HSET命令,但仅在键存在时。类似于HSETNX,但使用exists而不是not exists

我已经阅读了关于使用WATCH或其他东西的可能性,但到目前为止,我仍然无法弄清楚。我会感激指点正确的方向。我唯一看到的是这个,但考虑到这些甚至不是有效的redis命令,我不知道这是如何工作的。

HSET if key exist

此外,在阅读关于WATCH的内容后,我担心如果有另一个请求,我不想中止事务。

我基本上正在尝试HGETALL,之后立即发出第二条HSET命令,说它已经被读取了一次。

之后,我希望所有后续请求都知道它已经被读取过了。

问题是,当我对不存在的键调用HSET时,它不会失败,而是在redis数据库中创建一个新条目,这不是我想要的。我只想在无需先检查是否存在的情况下更新记录。

根据这个,对于高争用(将有大量请求关键字)该方法无论如何都不起作用。

https://github.com/antirez/redis/issues/441

它说我可以以某种方式使用脚本,但我不确定

1个回答

7
是的。您可以通过运行 EVAL 命令在 Redis 中执行 Lua 脚本。自 Redis 是单线程服务器,因此在 EVAL 完成之前,EVAL 之后的所有命令都将被阻塞。
文档中写道:
“从版本2.6.0开始,使用内置于Redis中的Lua解释器评估脚本的EVAL和EVALSHA。”
因此,要实现简单的HSETX命令,只需运行以下lua脚本: eval "if redis.call('exists',KEYS[1]) == 1 then redis.call('hset', KEYS[1], ARGV[1], 0) end" 1 test_key test_field

哥们儿太棒了,谢谢。你能告诉我如何在这里链式调用第二个命令吗?实际上,我想要在exists之后立即调用hgetallhset,所以如果存在,则执行hgetallset,否则不执行任何操作。 - Tallboy
2
@Tallboy eval "if redis.call('exists',KEYS[1]) == 1 then local ret = redis.call('hgetall', KEYS[1]); redis.call('hset', KEYS[1], ARGV[1], 1) return ret end" 1 test_key test_field - llinvokerl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接