Lua脚本语言快速上手(针对redis)

举报
yd_249383650 发表于 2023/05/23 09:47:55 2023/05/23
【摘要】 ​ 基本介绍Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能设计目的其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。Lua 特性轻量级:它用标准C语言编写并以源代码形式开放,编译后仅仅一百余K,可以很方便的嵌入别的程序里。可扩展:Lua提供了非常易于使用的扩展接口和机制:由宿...

 基本介绍

Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能

设计目的

其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。


Lua 特性

  1. 轻量级:它用标准C语言编写并以源代码形式开放,编译后仅仅一百余K,可以很方便的嵌入别的程序里。
  2. 可扩展:Lua提供了非常易于使用的扩展接口和机制:由宿主语言(通常是C或C++)提供这些功能,Lua可以使用它们,就像是本来就内置的功能一样。
  3. 其它特性:
  • 支持面向过程(procedure-oriented)编程和函数式编程(functional programming);自动内存管理;只提供了一种通用类型的表(table),用它可以实现数组,哈希表,集合,对象;
  • 语言内置模式匹配;闭包(closure);函数也可以看做一个值;提供多线程(协同进程,并非操作系统所支持的线程)支持;
  • 通过闭包和table可以很方便地支持面向对象编程所需要的一些关键机制,比如数据抽象,虚函数,继承和重载等

lua基本语法 

这里仅以redis中可能会用到的部分语法作介绍。

变量

a = 5 -- 全局变量
local b = 5 -- 局部变量, redis只支持局部变量
a, b = 10, 2*x -- 等价于 a=10; b=2*x

流程控制 

if( 布尔表达式 1)
then
--[ 在布尔表达式 1 为 true 时执行该语句块 --]
elseif( 布尔表达式 2)
then
--[ 在布尔表达式 2 为 true 时执行该语句块 --]
else
--[ 如果以上布尔表达式都不为 true 则执行该语句块 --]
end

redis执行lua脚本 - EVAL指令 

在redis中需要通过eval命令执行lua脚本。
格式:

EVAL script numkeys key [key ...] arg [arg ...]
script:lua脚本字符串,这段Lua脚本不需要(也不应该)定义函数。
numkeys:lua脚本中KEYS数组的大小
key [key ...]:KEYS数组中的元素
arg [art ...]:ARGV数组中的元素

案例1:基本案例

EVAL "return 10" 0

输出:(integer) 1 

案例2:动态传参

EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 5 10 20 30 40 50 60 70 80 90
# 输出:10 20 60 70
EVAL "if KEYS[1] > ARGV[1] then return 1 else return 0 end" 1 10 20
# 输出:0
EVAL "if KEYS[1] > ARGV[1] then return 1 else return 0 end" 1 20 10
# 输出:1

传入了两个参数10和20,KEYS的长度是1,所以KEYS中有一个元素10,剩余的一个20就是ARGV数组的元素。 

redis.call()中的redis是redis中提供的lua脚本类库,仅在redis环境中可以使用该类库。

 案例3:执行redis类库方法

set aaa 10 -- 设置一个aaa值为10
EVAL "return redis.call('get', 'aaa')" 0
## 通过return把call方法返回给redis客户端,打印:"10"

注意:脚本里使用的所有键都应该由 KEYS 数组来传递。但并不是强制性的,代价是这样写出的脚本不能被 Redis 集群所兼容。 

案例4:给redis类库方法动态传参

EVAL "return redis.call('set', KEYS[1], ARGV[1])" 1 bbb 20

编辑

学到这里基本可以应付redis分布式锁所需要的脚本知识了。

案例5:pcall函数的使用(了解) 

-- 当call() 在执行命令的过程中发生错误时,脚本会停止执行,并返回一个脚本错误,输出错误信息
EVAL "return redis.call('sets', KEYS[1], ARGV[1]), redis.call('set', KEYS[2],
ARGV[2])" 2 bbb ccc 20 30
-- pcall函数不影响后续指令的执行
EVAL "return redis.pcall('sets', KEYS[1], ARGV[1]), redis.pcall('set',
KEYS[2], ARGV[2])" 2 bbb ccc 20 30

注意:set方法写成了sets,肯定会报错。

编辑

性能优化 - EVALSHA指令

EVAL 命令要求你在每次执行脚本的时候都发送一次脚本主体(script body)。Redis 有一个内部的缓存机制,因此它不会每次都重新编译脚本,不过在很多场合,付出无谓的带宽来传送脚本主体并不是最佳选择。为了减少带宽的消耗, Redis 实现了 EVALSHA命令,它的作用和 EVAL 一样,都用于执行lua脚本,但它接受的第一个参数不是脚本,而是脚本的 SHA1 编码。
EVALSHA 命令的表现如下:
如果服务器存在SHA1编码对应的的脚本,那么就会执行这个脚本;如果服务器不存在SHA1编码对应的脚本,那么会返回一个特殊的错误,提醒用户使用 EVAL 代替 EVALSHA

-- script load会对redis脚本进行sha1加密生成加密字符串,无论脚本多长,密文长度固定,会以密文为key缓存lua基本
SCRIPT LOAD "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}"
-- 通过密文方式执行缓存的lua脚本
EVALSHA a42059b356c875f0717db19a51f6aaca9ae659ea 2 aa bb cc dd
-- 判断缓存中是否存在某个lua脚本,有返回1,无返回0
SCRIPT EXISTS a42059b356c875f0717db19a51f6aaca9ae659ea
-- 删除缓存中的lua脚本
SCRIPT FLUSH

编辑


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。