当前位置: 首页 > news >正文

Lua脚本简单理解

目录

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-- 查看变量、全局变量、局部变量
dolocal c = 4print(a) -- 5print(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) doprint(a)a = a + 1
end
--for 循环,从exp1开始循环到exp2, exp3是步⻓
for var=exp1, exp2, xep3 do
end
for i = 1, 5, 1 doprint(i)
end
for i = 5, 1, -1 doprint(i)
end
--打印数组
a = {"one", "two", "three"}
for i, v in ipairs(a) doprint(i, v)
end

2.4流程控制

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

2.5函数

--函数
function max(a, b)if (a < b) thenprint("a⼩于b")elseif(a == b) thenprint("a等于b")elseprint("a⼤于b")end
end
print(max(5, 5))--函数作为参数传递给函数
myFunc = function(param)print("这是param" .. param)
end
function myFuncB (a, b, func)result = a + bfunc(result)
end
myFuncB(1, 2, myFunc)--可变参数函数
function aa(...)local arg={...}for i, v in pairs(arg) doprint(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])"
返回:c686f316aaf1eb01d5a4de1b0b63cd233010e63devalsha c686f316aaf1eb01d5a4de1b0b63cd233010e63d 1 name1 zhangsanevalsha 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) thenredis.call('set',lockName,uuid);redis.call('pexpire',lockName,30000)return 1;
elsereturn 0;
end;//替换成脚本
if (redis.call('exists',KEYS[1]) == 0) thenredis.call('set',KEYS[1],ARGV[1]);redis.call('pexpire',KEYS[1],ARGV[2])return 1;
elsereturn 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) thenreturn 0;
end;
if (redis.call('get',lockName) == uuid) thenredis.call('del',lockName)return 1;
elsereturn 0;
end;if (redis.call('exists',KEYS[1]) == 0) thenreturn 0;
end;
if (redis.call('get',KEYS[1]) == ARGV[1]) thenredis.call('del',KEYS[1])return 1;
elsereturn 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) thenredis.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) thenredis.call('hincrby',KEYS[1],ARGV[1],1);redis.call('pexpire',KEYS[1],ARGV[2])return 1;
elsereturn 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;

相关文章:

Lua脚本简单理解

目录 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安装 安装指令&#xff1a; yum -y update yum i…...

AutoSAR自适应平台架构总览--AP的初认识

AutoSAR自适应平台架构总览:AP 基础设施层&#xff08;Foundation Layer&#xff09;核心操作系统&#xff08;Core OS&#xff09;通信管理&#xff08;Communication Management&#xff09; 服务层&#xff08;Services Layer&#xff09;诊断服务&#xff08;Diagnostics S…...

GPT-4o Mini:探索最具成本效益的小模型在软件开发中的应用

随着人工智能技术的迅猛发展&#xff0c;自然语言处理&#xff08;NLP&#xff09;领域也取得了显著的进步。OpenAI 最新发布的 GPT-4o Mini 模型&#xff0c;以其卓越的性能和极具竞争力的价格&#xff0c;成为了广大开发者关注的焦点。作为一名长期关注人工智能及其在软件开发…...

{Spring Boot 原理篇} Spring Boot自动装配原理

SpringBootApplication 1&#xff0c;Spring Boot 应用启动&#xff0c;SpringBootApplication标注的类就是启动类&#xff0c;它去实现配置类中的Bean的自动装配 SpringBootApplication public class SpringbootRedis01Application {public static void main(String[] args)…...

QEMU源码全解析 —— CPU虚拟化(10)

接前一篇文章: 本文内容参考: 《趣谈Linux操作系统》 —— 刘超,极客时间 《QEMU/KVM》源码解析与应用 —— 李强,机械工业出版社 《深度探索Linux系统虚拟化原理与实现》—— 王柏生 谢广军, 机械工业出版社 特此致谢! 二、x86架构CPU虚拟化 3. VMX 上一回讲解了支…...

46、PHP实现矩阵中的路径

题目&#xff1a; PHP实现矩阵中的路径 描述&#xff1a; 请设计一个函数&#xff0c;用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。 路径可以从矩阵中的任意一个格子开始&#xff0c;每一步可以在矩阵中向左&#xff0c;向右&#xff0c;向上&#xff0c;向…...

c++笔记2

目录 2.2 栈底&#xff08;bottom&#xff09; } 大数乘大数 节点&#xff1a;包含一个数据元素及若干指向子树分支的信息 。 节点的度&#xff1a;一个节点拥有子树的数目称为节点的度 。 叶子节点&#xff1a;也称为终端节点&#xff0c;没有子树的节点或者度为零的节点…...

通过Lua脚本手写redis分布式锁

1、手写 Redis 分布式锁&#xff0c;包括上锁、解锁、自动续期。 此功能实现采用 Lua脚本实现&#xff0c;Lua脚本可以保证原子性。 setnx可以实现分布式锁&#xff0c;但是无法实现可重入锁&#xff0c;所以用hset来代替setnx实现可重入的分布式锁。 -- lock if redis.call…...

解析银行个人征信系统

银行个人征信系统&#xff0c;也被称为个人信用信息基础数据库或金融信用信息基础数据库&#xff0c;是我国社会信用体系的重要基础设施。该系统由中国人民银行组织国内相关金融机构建立&#xff0c;旨在依法采集、整理、保存、加工自然人&#xff08;法人&#xff09;及其他组…...

AttributeError: ‘list‘ object has no attribute ‘text‘

AttributeError: ‘list‘ object has no attribute ‘text‘ 目录 AttributeError: ‘list‘ object has no attribute ‘text‘ 【常见模块错误】 【解决方案】 示例代码 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英…...

Codeforces Round 874 (Div. 3)(A~D题)

A. Musical Puzzle 思路: 用最少的长度为2的字符串按一定规则拼出s。规则是&#xff1a;前一个字符串的尾与后一个字符串的首相同。统计s中长度为2的不同字符串数量。 代码: #include<bits/stdc.h> #include <unordered_map> using namespace std; #define N 20…...

[Python][基础语法]详细讲解

目录 1.顺序语句2.条件语句3.缩进和代码块4.空语句 pass5.循环语句1.while2.for3.continue4.break ∞.积累 1.顺序语句 默认情况下&#xff0c;Python的代码执行顺序是按照从上到下的顺序&#xff0c;依次执行# 输出结果&#xff1a;"123" print("1") pri…...

Layui---输入事件

输入实时监听 //监听表单单选框复选框选择 form.on(radio, function (data) {console.log(data.value); //得到被选中的值 });//监听表单下拉菜单选择form.on(select, function (data) //监听表单下拉菜单选择form.on(select, function (data) ​ //监听表单复选框选择form.…...

甄选范文“论软件测试中缺陷管理及其应用”软考高级论文,系统架构设计师论文

论文真题 软件缺陷指的是计算机软件或程序中存在的某种破坏正常运行能力的问题、错误,或者隐藏的功能缺陷。缺陷的存在会导致软件产品在某种程度上不能满足用户的需要。在目前的软件开发过程中,缺陷是不可避免的。软件测试是发现缺陷的主要手段,其核心目标就是尽可能多地找…...

spring框架实现滑动验证码功能

spring框架实现滑动验证码功能 1. 整体描述2. 具体实现2.1 滑动验证码实体类2.2 滑动验证码登录VO2.3 滑动验证码接口返回类2.4 滑动验证码工具类2.5 滑动验证码Service2.6 滑动验证码Controller 3 工程源码4 总结 1. 整体描述 之前项目需要在验证码模块&#xff0c;增加滑动验…...

Pytorch使用教学8-张量的科学运算

在介绍完PyTorch中的广播运算后&#xff0c;继续为大家介绍PyTorch的内置数学运算&#xff1a; 首先对内置函数有一个功能印象&#xff0c;知道它的存在&#xff0c;使用时再查具体怎么用其次&#xff0c;我还会介绍PyTorch科学运算的注意事项与一些实用小技巧 1 基本数学运算…...

[Spring Boot]登录密码三种加密方式

简述 介绍其三种密码加密方法 1.SM2加密与验签 2.随机密码盐加密 3.MD5加密 推荐使用方法1&#xff0c;其次使用方法2&#xff0c;最不推荐的是方法3。方法3极其容易被密码字典破解&#xff0c;如果项目进行安全测试&#xff0c;通常是不允许的加密方式。 SM2加密与验签 引入…...

前端面试项目细节重难点分享(十三)

面试题提问&#xff1a;分享你最近做的这个项目&#xff0c;并讲讲该项目的重难点&#xff1f; 答&#xff1a;最近这个项目是一个二次迭代开发项目&#xff0c;迭代周期一年&#xff0c;在做这些任务需求时&#xff0c;确实有很多值得分享的印象深刻的点&#xff0c;我讲讲下面…...

每天五分钟深度学习:向量化方式完成逻辑回归m个样本的前向传播

本文重点 我们已经知道了向量化可以明显的加速程序的运行速度,本节课程将使用向量化来完成逻辑回归的前向传播,不使用一个for循环。 逻辑回归的前向传播 我们先来回忆一下逻辑回归的前向传播,如果我们有m个训练样本,首先对第一个样本进行预测,我们需要计算z,然后计算预…...

以线程完成并发的UDP服务端

网络(九)并发的UDP服务端 以线程完成功能 客户端 // todo UDP发送端 #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/types.h> #include <stdlib.h> #include <string.h…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...

探索Selenium:自动化测试的神奇钥匙

目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...