当前位置: 首页 > 面试题库 >

Redis Lua脚本实现CAS(检查并设置)?

陆烨磊
2023-03-14
问题内容

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

我尝试实现非常简单的“ CAS”语义:使用单个键和两个参数来调用它。它将检查服务器上与该键关联的值是否 第一个参数 开头
,如果是,则将设置键的新值设置为第二个参数并返回1,否则返回0;否则返回0。如果键与字符串以外的其他某种类型的数据相关联,则Redis将返回并返回错误,就像您对这样的键/值组合尝试执行SET命令一样。如果在调用之前该键不存在,则该函数将返回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”(在 redis-cli中 )的键“ foo”上调用脚本的示例:

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

我认为这种用法模式可能是您想同时存储“围栏令牌”和带有键的值的情况……允许并发客户端在持有正确的围栏令牌的情况下尝试更新该值。

看起来这将是代替WATCH / MULTI /
EXEC语义的安全使用模式吗?(似乎您可以获取当前值,在本地代码中拆分防护令牌,构建新值,然后尝试在任何时候以比WATCH / MULTI /
EXEC调用少的语义来尝试更新密钥)。

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

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


问题答案:

根据Redis的文档,您在原子性方面会没事的:

Redis使用相同的Lua解释器来运行所有命令。另外,Redis保证以原子方式执行脚本:执行脚本时不会执行其他脚本或Redis命令。这种语义类似于MULTI
/ EXEC中的一种。从所有其他客户端的角度来看,脚本的效果还是不可见或已经完成。

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

您可能会遇到的另一个漏洞是,如果脚本在中间某种程度上失败了,尽管脚本将返回错误,但您所做的那些调用将无法回滚。

例如:您有一个如下脚本:

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


 类似资料:
  • 下面是一个在前缀值为“bar”的键“foo”上调用脚本的示例(在redis-cli中): 我认为这种使用模式可能是这样的情况:您希望同时存储一个“Geofence令牌”和一个带有键的值...如果并发客户端持有正确的Geofence令牌,则允许它们尝试更新该值。 这看起来像是代替watch/multi/exec语义的安全使用模式吗?(似乎您可以获取当前值,在本地代码中拆分隔离令牌,构建一个新值,然后

  • Booksleve是否支持CAS操作(即Redis WATCH命令)?例如,如何实现以下内容? 当多个线程试图用相同的数据修改相同的对象时,我需要这样做来避免竞争条件。

  • 本文向大家介绍python设置检查点简单实现代码,包括了python设置检查点简单实现代码的使用技巧和注意事项,需要的朋友参考一下 说检查点,其实就是对过去历史的记录,可以认为是log.不过这里进行了简化.举例来说,我现在又一段文本.文本里放有一堆堆的链接地址.我现在的任务是下载那些地址中的内容.另外因为网络的问题或者网站的问题,每次下载可能不会非常的成功.有可能出现断链或者socket异常错误。

  • 我使用nightwatchjs作为测试工具,需要测试注入的脚本是否正确显示在页面上,以及脚本是否正确填充。 因此,下面的脚本html将被测试(以确保它被正确显示): 所以首先,我想测试这个脚本是否出现在页面上,但是以一种尽可能不脆弱的方式。我可以测试 /html/head/script[13]/text(),但这真的很脆弱,远非理想。 脚本中有没有什么我可以参考的东西,这样测试就不会那么脆弱了?

  • 本文向大家介绍Shell脚本实现检查服务器安全状态(用户、登录IP、防火墙检查),包括了Shell脚本实现检查服务器安全状态(用户、登录IP、防火墙检查)的使用技巧和注意事项,需要的朋友参考一下 说明:大家平时对Linux服务器安全主要是对系统用户的检查,登陆服务器IP检查,以及防火墙状态检查! 1.需要把正确系统用户名存储在/root/liu_shell/local_user.txt文件中,然后

  • 本文向大家介绍shell实现自动adsl拨号并检测连接状况脚本分享,包括了shell实现自动adsl拨号并检测连接状况脚本分享的使用技巧和注意事项,需要的朋友参考一下 今天公司同事要我整个adsl自动重拨的shell,并检测是否连上了,这样才能保证内部测试服务器不掉网,好吧,下面我把脚本发出来. 系统:centos 5.x 脚本1: 脚本2: ps:脚本2的作用就是检测adsl拨号是否有连上.