gpt4 book ai didi

lua - 实现 CAS(检查和设置)的 Redis Lua 脚本?

转载 作者:IT王子 更新时间:2023-10-29 05:59:50 24 4
gpt4 key购买 nike

我只是想了解 Redis/Lua 脚本,我想知道是否有人发现以下代码有问题。

这是我实现非常简单的“CAS”语义的尝试:用一个键和两个参数调用它。它将检查服务器上与该键关联的值是否第一个参数开头,如果是,则将设置键的新值设置为第二个参数并返回 1,否则返回0;如果键与字符串以外的某种类型的数据相关联,则 Redis 将返回错误,就像您尝试对此类键/值组合执行 SET 命令一样。如果 key 在调用之前不存在,则该函数将返回 0(失败)。

这是脚本:

local x=string.len(ARGV[1]);
if redis.call('GETRANGE', KEYS[1], 0, x-1) == ARGV[1] then
redis.call('SET', KEYS[1], ARGV[2]);
return 1;
end;
return 0

以下是在前缀值为“bar”的键“foo”上调用脚本的示例(在 redis-cli 中):

eval "local x=string.len(ARGV[1]); if redis.call('GETRANGE', KEYS[1], 0, x-1) == ARGV[1] then redis.call('SET', KEYS[1], ARGV[2]); return 1; end; return 0" 1 foo bar barbazzle

我认为这种使用模式可能是您希望同时存储“防护 token ”和带有键的值的情况......如果并发客户端持有正确的防护,则允许并发客户端尝试更新该值 token 。

这看起来像是一种安全的使用模式来代替 WATCH/MULTI/EXEC 语义吗? (似乎您可以获取当前值,在本地代码中拆分防护 token ,构建一个新值,然后随时尝试使用似乎比 WATCH/MULTI/EXEC 调用更容易混淆的语义来更新 key )。

(我知道我的脚本的语义与 memcached CAS 命令略有不同;这是故意的)。

这确实通过了我的有限测试……所以我真的想问任何潜在的并发/原子性问题以及 Lua 中是否有任何愚蠢的东西——因为我过去几乎没有接触过 Lua)。

最佳答案

根据 Redis's documentation,您在原子性方面会很好:

Redis uses the same Lua interpreter to run all the commands. Also Redis guarantees that a script is executed in an atomic way: no other script or Redis command will be executed while a script is being executed. This semantic is similar to the one of MULTI / EXEC. From the point of view of all the other clients the effects of a script are either still not visible or already completed.

但是,如果脚本太慢,则会导致问题。因此脚本最适合需要一些逻辑和原子性的轻型操作。

您可能会陷入的另一个漏洞是,如果脚本在中间不知何故失败,您所做的那些调用将无法回滚,尽管脚本会返回错误。

例如:你有一个这样的脚本:

redis.call('set', 'foo', 1)
redis.call('rpush', 'foo', 2)

脚本执行会报错,但是foo已经在redis中设置为1


与您的问题无关的事情:我注意到您使用了

eval "your_raw_code" key_count keys argv

实际上您可以在终端中调用 eval 中的 lua 脚本文件:

> redis-cli eval "$(cat path/to/script/script_name.lua)" key_count keys argv

关于lua - 实现 CAS(检查和设置)的 Redis Lua 脚本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36441734/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com