Redission中的Lua脚本写法、理解

对于Redission看门狗机制中的为了保证原子性的Lua脚本的写法规则是什么样的呢 ?
对于源码中的Lua脚本又是什么意思?

我们一起来看一下
首先,我们先基本的熟悉一下lua脚本的逻辑

在Lua脚本中,if (…) then … end 语句的执行过程详细说明:

    1. 条件表达式求值:首先,Lua会计算if语句中的条件表达式(位于括号(…)内的部分)。这个表达式可以是一个简单的比较(如a == b),也可以是一个更复杂的表达式,甚至是一个函数调用,只要这个表达式最终返回一个可以被解释为布尔值的结果(在Lua中,false和nil被视为假(false),而所有其他值都被视为真(true))。
    1. 条件判断:Lua根据条件表达式的求值结果来决定是否执行then后面的代码块。如果条件表达式的值为真(true),则执行then和end之间的代码块;如果条件表达式的值为假(false),则跳过该代码块,继续执行end之后的代码(如果有的话)。
    1. 执行代码块:如果条件为真,Lua会顺序执行then和end之间的所有语句,直到遇到end关键字。在这个代码块内,你可以使用各种Lua语句,包括变量赋值、函数调用、循环、条件语句等。
    1. 退出if语句:一旦end关键字被遇到,if语句的执行就结束了。程序的控制流会继续从end之后的下一条语句开始执行。

使用示例:

local a = 10  
local b = 20  
  
if a < b then  
    print("a is less than b")  
else  
    print("a is not less than b")  
end  
  
-- 输出: a is less than b

这个例子中,条件表达式a < b的值为真(true),因为10确实小于20。因此,Lua执行了then后面的print语句,输出了"a is less than b",然后遇到了end关键字,if语句的执行结束。

如果条件表达式的值为假(例如,如果我们将a的值改为30),则Lua会跳过then后面的代码块,直接执行else后面的代码块(如果提供了else部分的话)。如果没有提供else部分,并且条件为假,则if语句之后的代码将直接继续执行。

了解了基本的语法
我们来看下Lua脚本:

-- 检查键是否存在  
if (redis.call('exists', KEYS[1]) == 0)   
then   
    -- 如果键不存在,这里尝试对不存在的键进行hincrby操作是没问题的,如果不存在,则会自动的新建一个hash的对象并给其中的子key赋值
    -- 因为hincrby是操作哈希表中字段的命令,而键本身不存在时无法直接对其哈希表进行操作  
    redis.call('hincrby', KEYS[1], ARGV[2], 1);  -- 这行会失败,因为KEYS[1]不存在  
    redis.call('pexpire', KEYS[1], ARGV[1]);  -- 尝试设置过期时间,但由于前一行可能失败,这行的执行也可能不符合预期  
    return nil;  -- 返回nil,表示键不存在但尝试进行了操作  
end;   
  
-- 检查哈希字段是否存在  
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then   
    redis.call('hincrby', KEYS[1], ARGV[2], 1);  -- 如果字段存在,递增其值  
    redis.call('pexpire', KEYS[1], ARGV[1]);  -- 更新键的过期时间  
    return nil;  -- 返回nil,表示字段存在且已被更新  
end;  
  
-- 如果键存在但字段不存在,或者键和字段都检查过了(即上述两个if条件都不满足)  
return redis.call('pttl', KEYS[1]);  -- 返回键的剩余生存时间(以毫秒为单位)

对于redis中Hash的结构
在redission中也是支持锁重入的,他采用了hash结构来存储锁,其中大key标识这把锁是否存在,小key表示这把锁当前被谁持有。

key:锁的名称
value:
field:当前持有者的id(id+“:”+线程id,小key)
value:state(count)状态变量

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis引入Lua脚本是为了满足某些特定场景下对原子性操作的需求。 Redis提供了丰富的指令集,但对于某些需要扩展的指令原子性执行的场景,仅使用原生命令无法满足需求。为了解决这个问题,Redis在2.6版本引入了Lua脚本功能。通过使用Lua语言编写脚本并传输到Redis执行,可以实现以下好处: 1. 减少网络开销:通过将多个请求以脚本的形式一次性发送,可以减少网络时延。 2. 原子操作:Redis会将整个脚本作为一个整体执行,在执行过程不会被其他请求插入。因此,无需担心出现竞态条件,也无需使用事务。 3. 复用:客户端发送的脚本会在Redis永久存在,这样其他客户端可以复用该脚本,而无需使用代码完成相同的逻辑。 Redis官方命令参考:http://redisdoc.com/script/eval.html 《Redis设计与实现》-黄健宏著 掘金小册 -> Redis 深度历险:核心原理与应用实践<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Redis使用Lua脚本(一)](https://blog.csdn.net/lpf463061655/article/details/98971806)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值