Lua脚本简单理解

news2024/11/17 11:00:15

目录

1.安装

2.语法

2.1Lua数据类型

2.2变量

2.3lua循环

2.4流程控制

2.5函数

2.6运算符

2.7关系运算符

3.lua脚本在redis中的使用

3.1lua脚本再redis简单编写

3.2普通锁Lua脚本

3.3可重入锁lua脚本


1.安装

centos安装

安装指令:

yum -y update

yum install lua

启动指令:

 

lua
print("hello world")

windos安装

Lua Binaries Download

解压后在环境变量配置

再cmd中尝试,安装成功

也可以在idea中使用

2.语法

2.1Lua数据类型

nil 表示无效值。相当于false

boolean 包含两个值:false,true

number 双精度浮点数

string 字符串由一对双引号或者单引号表示

function 由c或lua编写函数

table lua中的表(taboe) “关联数组“(associative arrays),数组的索引可以是数字、字符串或表类型。在lua里,table的创建是通过"构造表达式完成",最简单构造表达式是{}。

-- 变量
print(type(nil))
print(type(false))
print(type(1))
print(type(1.1))
print(type(type))
print(type("hello world"))
print(type({1,2}))

2.2变量

Lua变量有三种类型:全局类型局部变量表中的域

  1. 没有使用local进行修饰的变量都是全局变量,使用local修饰的则为局部变量
  2. 局部变量的作用域为从声明位置开始到所在语句块结束
  3. 变量默认值都为nil
--变量
a = 5 --全局变量
print(a) -- 5
local b = 6 --局部变量
print(b) -- 6

-- 查看变量、全局变量、局部变量
do
 local c = 4
 print(a) -- 5
 print(c) -- 4
end
print(c) -- nil

--对多个变量同时赋值 ..表示为字符串连接
a, b, c= 1,2 -- 没有值的变量,赋值nil
print(a .."-" .. b)
print(c)
a, b = 2,3,4 --多出来的值被省略
print(a .. "-" .. b)

-- table赋值 如果key值一样后面的会覆盖前面的值
tal = {"a", "b", "3"}
print(tal[1] .. tal[2] .. tal[3])
tal = {key = "xxddd", key1 = "yysss"}
print(tal["key"] .. tal["key1"])

2.3lua循环

--while 循环
a = 1
while(a < 5) do
 print(a)
 a = a + 1
end
--for 循环,从exp1开始循环到exp2, exp3是步⻓
for var=exp1, exp2, xep3 do
end
for i = 1, 5, 1 do
 print(i)
end
for i = 5, 1, -1 do
 print(i)
end
--打印数组
a = {"one", "two", "three"}
for i, v in ipairs(a) do
 print(i, v)
end

2.4流程控制

--流程控制
a = 9
if (a < 10) then
 print("⼩于10")
end
a = 11
if (a < 10) then
 print("⼩于10")
else
 print("⼤于等于10")
end
a = 10
if (a < 10) then
 print("⼩于10")
elseif (a == 10) then
 print("等于10")
else
 print("⼤于10")
end

2.5函数

--函数
function max(a, b)
 if (a < b) then
 print("a⼩于b")
 elseif(a == b) then
 print("a等于b")
 else
 print("a⼤于b")
 end
end
print(max(5, 5))

--函数作为参数传递给函数
myFunc = function(param)
 print("这是param" .. param)
end
function myFuncB (a, b, func)
 result = a + b
 func(result)
end
myFuncB(1, 2, myFunc)

--可变参数函数
function aa(...)
 local arg={...}
 for i, v in pairs(arg) do
 print(i .. v)
 end
end
aa("a", "b", "c")

2.6运算符

正常+ - * / % ^ -  特殊//整除运算符 比如5//2 输出结果为2

算数运算符号

--算术运算符
print(1 + 2)
print(2 - 1)
print(2 * 1)
print(-10)
print(10 / 6)
print(10 % 6)
print(10 // 6)
print(10 ^ 2)

2.7关系运算符

正常 == > < >=  <=

特殊:~=(不等于)

关系运算符

and or not

其他运算符号

..    连接两个字符串

# 一元运算符,返回字符串或表的长度

#“hello” 返回5

3.lua脚本在redis中的使用

3.1lua脚本再redis简单编写

redis中支持使用EVAL关键字来使用Lua脚本

eval指令中的1 表示key的个数,以下代码实例是表示keys[1]  等于在1的后面的key1,即keys[1]=key1,但是value中是不需要声明的。

EVAL script numkeys key [key …] arg [arg …]

127.0.0.1:6379> eval "return {KEYS[1],ARGV[1],ARGV[2]}" 1 key1 arg1 arg2
1) "key1"
2) "arg1"
3) "arg2"
127.0.0.1:6379>

在redis中执行

eval 执行执行

这个keys和argv必须是大写,不然会报错

 eval "return redis.call('set',KEYS[1],ARGV[1])" 1 name xiaoming

也可以把指令进行缓存

script load ->evalsha 对应id

script load "return redis.call('set',KEYS[1],ARGV[1])"
返回:c686f316aaf1eb01d5a4de1b0b63cd233010e63d

evalsha c686f316aaf1eb01d5a4de1b0b63cd233010e63d 1 name1 zhangsan

evalsha c686f316aaf1eb01d5a4de1b0b63cd233010e63d 1 name2 zhangsan2

--判断指令是否存在
script exists c686f316aaf1eb01d5a4de1b0b63cd233010e63d

--删除指令
script flush c686f316aaf1eb01d5a4de1b0b63cd233010e63d

3.2简易锁Lua脚本

加锁

ps:lua脚本中指令要对应单引号

//判断redis中是否存在key
// 如果不存在,那么就使⽤set key value,并且增加过期时间,返回1.
// 如果存在,直接返回0,继续循环获取锁
//正常编写
if (redis.call('exists',lockName) == 0) then
 redis.call('set',lockName,uuid);
 redis.call('pexpire',lockName,30000)
 return 1;
else
 return 0;
end;

//替换成脚本
if (redis.call('exists',KEYS[1]) == 0) then
 redis.call('set',KEYS[1],ARGV[1]);
 redis.call('pexpire',KEYS[1],ARGV[2])
 return 1;
else
 return 0;
end;

在redis中跑一遍

eval "if (redis.call('exists',KEYS[1]) == 0) then redis.call('set',KEYS[1],ARGV[1]); redis.call('pexpire',KEYS[1],ARGV[2]) return 1; else return 0; end" 1 lockName uuid 30000

释放锁

//判断锁是否存在,如果不存在,直接返回0
//如果锁存在,判断value是否==当前线程的uuid
// 如果等于,执⾏delete
// 如果不等于,返回0
//正常写
if (redis.call('exists',lockName) == 0) then
 return 0;
end;
if (redis.call('get',lockName) == uuid) then
 redis.call('del',lockName)
 return 1;
else
 return 0;
end;


if (redis.call('exists',KEYS[1]) == 0) then
 return 0;
end;
if (redis.call('get',KEYS[1]) == ARGV[1]) then
 redis.call('del',KEYS[1])
 return 1;
else
 return 0;
end;

reids执行脚本

eval "if (redis.call('exists', KEYS[1]) == 0) then return 0; end; if (redis.call('get', KEYS[1]) == ARGV[1]) then redis.call('del', KEYS[1]); return 1; else return 0; end;" 1 lockName uuid

3.3可重入锁lua脚本

可以通过hash的数据结构进行对锁的添加次数,和扣减测试进行设置

加锁

//redis中执⾏可重⼊加锁lua脚本
eval "if(redis.call('exists',KEYS[1]) == 0) then redis.call('hincrby',KEYS
[1],ARGV[1],1); redis.call('pexpire',KEYS[1],ARGV[2]) return 1; end; if(re
dis.call('hexists',KEYS[1],ARGV[1]) == 1) then redis.call('hincrby',KEYS
[1],ARGV[1],1); redis.call('pexpire',KEYS[1],ARGV[2]) return 1; else retur
n 0; end;" 1 lockName uuid 30000
//可重⼊加锁lua脚本
 //判断锁是否存在
 //如果不存在,就加锁,设置过期时间
 //如果存在,判断加锁的线程是不是⾃⼰
 //如果是,重⼊次数+1
 //如果不是,加锁失败
if(redis.call('exists',KEYS[1]) == 0) then
 redis.call('hincrby',KEYS[1],ARGV[1],1);
 redis.call('pexpire',KEYS[1],ARGV[2])
 return 1;
end;
if(redis.call('hexists',KEYS[1],ARGV[1]) == 1) then
 redis.call('hincrby',KEYS[1],ARGV[1],1);
 redis.call('pexpire',KEYS[1],ARGV[2])
 return 1;
else
 return 0;
end; 

解锁

//redis中执⾏可重⼊解锁lua脚本
eval "if(redis.call('hexists',KEYS[1],ARGV[1]) == 0) then return 0; end; l
ocal lockCount = redis.call('hincrby',KEYS[1],ARGV[1],-1) if(lockCount>0)t
hen redis.call('pexpire',KEYS[1],ARGV[2]); return 1; else redis.call('de
l',KEYS[1]) return 1; end;" 1 lockName uuid 30000 

//可重⼊解锁lua脚本
 //判断锁是否存在且存在是否是本线程加的锁。也就是加锁线程是否本身
 //如果不是本身,直接就return 0,解锁失败了。
 //如果是本身,判断当前重⼊次数是否⼤于1
 //如果⼤于1,说明存在线程多次获取⼀把锁,此时只需要减1即可
 //如果不⼤于0,说明锁可以被删除了。
if(redis.call('hexists',lockName,uuid) == 0) then
return 0;
end;
local lockCount = redis.call('hincrby',lockName,uuid,-1)
if(lockCount>0) then
redis.call('pexpire',lockName,time);
 return 1;
else
redis.call('del',lockName) return 1;
end;

续约 

//redis执⾏续约lua脚本
eval "if(redis.call('hexists',KEYS[1],ARGV[1])==0) then return 0; else red
is.call('pexpire',KEYS[1],ARGV[2]) return 1; end;" 1 lockName uuid 30000
//lua脚本
//判断锁是否是本线程加锁,是的话,就⼀直延⻓时间
if(redis.call('hexists',KEYS[1],ARGV[1])==0) then
return 0;
else
redis.call('pexpire',KEYS[1],ARGV[2])
return 1;
end;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1949390.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5. System Design 5.2. 身份验证框架和信任链

快速链接: . &#x1f449;&#x1f449;&#x1f449; 个人博客笔记导读目录(全部) &#x1f448;&#x1f448;&#x1f448; 付费专栏-付费课程 【购买须知】我的联系方式-自建交流群-学习群 【必看/必看&#xff01;&#xff01;】ATF架构开发精讲-专题目录&#x1f448;…

Unity Android接入SDK 遇到的问题

1. buildtools、platformtools、commandline tools 以及compiled sdk version、buildtools sdk version、target sdk version 的说明 Android targetSdkVersion了解一下 - 简书 2. 查看.class 和.jar文件 jd_gui 官网地址&#xff1a; 下载jd_gui 工具 &#xff0c;或者 idea 下…

全方位数据管理:一站式爬虫服务解决方案

摘要 面对互联网信息爆炸的时代&#xff0c;如何高效地收集、整理并分析海量数据&#xff0c;成为企业与开发者面临的一大挑战。本文将深入探讨一站式爬虫服务解决方案&#xff0c;揭示如何通过全方位数据管理策略&#xff0c;助力企业轻松驾驭大数据海洋&#xff0c;实现数据…

事务和函数索引

事务 事务的定义 事务&#xff08;Transaction&#xff09;&#xff0c;就是将一组SQL语句放在同一批次内去执行&#xff0c;如果一个SQL语句出错&#xff0c;则该批次内 的所有SQL都将被取消执行。 事务的特点 一个事务中如果有一个数据库操作失败&#xff0c;那么整个 事务…

光明乳业:以科技赋能品质,引领乳业绿色新未来

近日&#xff0c;光明乳业再次成为行业焦点&#xff0c;其在科技创新与绿色发展方面的卓越表现赢得了广泛赞誉。作为中国乳制品行业的领军企业&#xff0c;光明乳业始终坚守品质至上的原则&#xff0c;不断探索科技创新之路&#xff0c;致力于为消费者提供更高品质、更健康的乳…

芯片的计算能力由什么决定

芯片的计算能力由什么决定 芯片的计算能力由多个因素决定。 包括但不限于&#xff1a; 架构设计&#xff1a; 芯片的架构设计决定了其计算单元的数量和类型&#xff0c;以及它们之间的连接方式和通信方式。不同的架构可以提供不同的计算能力和性能。处理器速度&#xff1a; 处…

Linux下普通用户无法执行sudo指令

当执行sudo指令时出现&#xff1a; xxx&#xff08;普通用户名字&#xff09; is not in the sudoers file 说明在/etc/sudoers文件中没有把xxx加入到可执行sudo指令的名单中&#xff0c;因此需要修改sudoers文件。 解决方法&#xff1a;1、vim /etc/sudoers &#xff08;要…

【图像标签转换】XML转为TXT图像数据集标签

引言 该脚本用于将包含对象标注的 XML 文件转换为 YOLO&#xff08;You Only Look Once&#xff09;对象检测格式的 TXT 文件。脚本读取 XML 文件&#xff0c;提取对象信息&#xff0c;规范化边界框坐标&#xff0c;并将数据写入相应的 TXT 文件。此外&#xff0c;它还生成一个…

深度学习1-简介

人工智能&#xff08;AI&#xff09;旨在打造模仿智能行为的系统。它覆盖了众多方法&#xff0c;涵盖了基于逻辑、搜索和概率推理的技术。机器学习是 AI 的一个分支&#xff0c;它通过对观测数据进行数学模型拟合来学习决策制定。这个领域近年来迅猛发展&#xff0c;现在几乎&a…

谷粒商城实战笔记-64-商品服务-API-品牌管理-OSS前后联调测试上传

文章目录 1&#xff0c;拷贝文件到前端工程2&#xff0c;局部修改3&#xff0c;在品牌编辑界面使用上传组件4&#xff0c;OSS配置允许跨域5&#xff0c;测试multiUpload.vue完整代码singleUpload.vue完整代码policy.js代码 在Web应用开发中&#xff0c;文件上传是一项非常常见的…

基于PaddleClas的人物年龄分类项目

目录 一、任务概述 二、算法研发 2.1 下载数据集 2.2 数据集预处理 2.3 安装PaddleClas套件 2.4 算法训练 2.5 静态图导出 2.6 静态图推理 三、小结 一、任务概述 最近遇到个需求&#xff0c;需要将图像中的人物区分为成人和小孩&#xff0c;这是一个典型的二分类问题…

设计模式笔记(一)

目录 设计模式共有23种&#xff0c;也可称为GOF23 单例模式&#xff08;重点&#xff0c;常用&#xff09; 工厂模式 代理模式&#xff1a;&#xff08;SpringAOP的底层原理&#xff09; 静态代理模式&#xff1a;&#xff08;写死一个代理类Proxy&#xff09; 动态代理模…

【Java版数据结构】初识泛型

看到这句话的时候证明&#xff1a;此刻你我都在努力 加油陌生人 br />个人主页&#xff1a;Gu Gu Study专栏&#xff1a;Java版数据结构 喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 作者&#xff1…

学习笔记:MySQL数据库操作5

1. 触发器&#xff08;Triggers&#xff09; 触发器是数据库的一种高级功能&#xff0c;它允许在执行特定数据库操作&#xff08;如INSERT、UPDATE、DELETE&#xff09;之前或之后自动执行一段代码。 1.1 创建商品和订单表 商品表&#xff08;goods&#xff09; gid: 商品编号…

navicat15安装破解

下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/19RlXTArDfNxT5n98A0GbvQ 提取码&#xff1a;qtew 破解教程 1、运行注册机&#xff0c;勾选Backup、Host和Navicat v15&#xff0c;如图所示。然后点击Patch按钮&#xff0c;找到Navicat Premium 15安装路径下的…

什么是模型无关方法?

「AI秘籍」系列课程&#xff1a; 人工智能应用数学基础人工智能Python基础人工智能基础核心知识人工智能BI核心知识人工智能CV核心知识AI 进阶&#xff1a;企业项目实战 可直接在橱窗里购买&#xff0c;或者到文末领取优惠后购买&#xff1a; 可以与任何模型一起使用的所有强…

破局产品同质化:解锁3D交互式营销新纪元!

近年来&#xff0c;随着数字体验经济的蓬勃发展&#xff0c;3D交互式营销作为一种创新手段迅速崛起&#xff0c;它巧妙地解决了传统产品展示中普遍存在的缺乏差异性和互动性的问题&#xff0c;使您的产品在激烈的市场竞争中独树一帜&#xff0c;脱颖而出。 若您正面临产品营销…

抖音直播弹幕数据逆向:websocket和JS注入

&#x1f50d; 思路与步骤详解 &#x1f575;️‍♂️ 思路介绍 首先&#xff0c;我们通过抓包工具进入的直播间&#xff0c;捕获其网络通信数据&#xff0c;重点关注WebSocket连接。发现直播弹幕数据通过WebSocket传输&#xff0c;这种方式比传统的HTTP更适合实时数据的传输。…

昇思25天学习打卡营第24天 | Pix2Pix实现图像转换

昇思25天学习打卡营第24天 | Pix2Pix实现图像转换 文章目录 昇思25天学习打卡营第24天 | Pix2Pix实现图像转换Pix2Pix模型cGANCGAN的损失函数 数据网络构建生成器判别器Pix2Pix网络 总结打卡 Pix2Pix模型 Pix2Pix是基于条件生成对抗网络&#xff08;cGAN, Condition Generativ…

如何在测试中保护用户隐私!

在当今数据驱动的时代&#xff0c;用户隐私保护成为了企业和开发团队关注的焦点。在软件测试过程中&#xff0c;处理真实用户数据时保护隐私尤为重要。本文将介绍如何在测试中保护用户隐私&#xff0c;并提供具体的方案和实战演练。 用户隐私保护的重要性 用户隐私保护不仅是法…