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

Lua语言

在黑马点评项目实战中,在提到确保分布式锁的获取锁和释放锁的时候提到了Redis的Lua脚本,本文来简单介绍一下Lua语言和简单语法。

​一、Redis 的 Lua 脚本是什么?​

Redis 支持通过 ​​Lua 脚本​​在服务端直接执行一系列操作,这些脚本会被 Redis 解释器原子性地执行(即执行期间不会被其他命令打断)。其核心价值是:

  • ​原子性​​:多个 Redis 命令被打包成一个脚本执行,避免多次网络往返和中间状态的不一致。
  • ​高效性​​:减少客户端与 Redis 服务器的网络交互次数(单次请求完成多步操作)。
  • ​灵活性​​:支持复杂逻辑(如条件判断、循环、函数封装),弥补 Redis 原生命令的不足。

​二、Lua 语言简介​

Lua 是一种​​轻量级、嵌入型、跨平台的脚本语言​​,由巴西里约热内卢天主教大学(PUC-Rio)的开发团队于 1993 年设计。它的设计目标是“简单、高效、可嵌入”,因此被广泛用于游戏引擎(如《魔兽世界》)、嵌入式系统、数据库(如 Redis)等场景。

​Lua 的核心特点​
  1. ​轻量级​​:解释器仅几百 KB,内存占用极低。
  2. ​快速高效​​:运行速度接近 C 语言(基于寄存器的虚拟机设计)。
  3. ​可嵌入性​​:能轻松集成到 C/C++、Java 等语言的程序中(Redis 即通过 C 语言实现了 Lua 解释器)。
  4. ​弱类型​​:变量无需声明类型,动态类型转换灵活。
  5. ​表(Table)为核心​​:所有数据结构(数组、字典、对象)均基于 table 实现。

​三、Lua 简单语法入门​

Lua 的语法简洁,学习成本低。以下是最基础的常用语法:

​1. 注释​
  • 单行注释:-- 这是注释
  • 多行注释:--[[ 这是多行注释 --]]
​2. 变量与数据类型​

Lua 是弱类型语言,变量无需声明类型,常用类型包括:

  • ​数值(Number)​​:整数或浮点数(如 10, 3.14)。
  • ​字符串(String)​​:用单引号 ' ' 或双引号 " " 包裹(如 'hello', "world")。
  • ​布尔值(Boolean)​​:truefalse(注意:Lua 没有 nil 以外的“假值”,nil 表示“无值”)。
  • ​表(Table)​​:唯一的复合数据类型,用 {} 定义(类似 JSON 对象或数组)。
  • ​函数(Function)​​:可赋值给变量,支持匿名函数。
​3. 变量声明​
  • 全局变量:直接赋值(无需 var/let)。
    name = "Redis"  -- 全局变量 name
  • 局部变量:用 local 声明(推荐,避免污染全局作用域)。
    local age = 10  -- 局部变量 age
​4. 条件判断(if-elseif-else)​
local score = 85
if score >= 90 thenprint("优秀")
elseif score >= 80 thenprint("良好")
elseprint("加油")
end
​5. 循环(for)​
-- 遍历数组(索引从 1 开始)
local fruits = {"apple", "banana", "orange"}
for i = 1, #fruits do  -- #fruits 是数组长度(3)print(fruits[i])
end-- 数值范围循环(i 从 1 到 5)
for i = 1, 5 doprint(i)
end
​6. 函数(Function)​
-- 定义函数(计算两数之和)
local function add(a, b)return a + b
end-- 调用函数
print(add(3, 5))  -- 输出 8-- 匿名函数(赋值给变量)
local multiply = function(a, b)return a * b
end
print(multiply(2, 4))  -- 输出 8
​7. 表(Table):Lua 的“万能容器”​

表是 Lua 中唯一的数据结构,可模拟数组、字典、对象等:

-- 数组(索引从 1 开始)
local arr = {10, 20, 30}
print(arr[1])  -- 输出 10-- 字典(键值对)
local user = {name = "张三",age = 25,isStudent = false
}
print(user.name)  -- 输出 "张三"-- 混合表(数组+字典)
local info = {{"北京", "上海"},  -- 索引 1: 数组部分city = "广州",     -- 索引 "city": 字典部分population = 1500  -- 索引 "population": 字典部分
}
print(info[1][1])    -- 输出 "北京"
print(info.city)     -- 输出 "广州"

​四、Redis 中使用 Lua 脚本的示例​

回到之前的分布式锁场景,用 Lua 脚本实现“原子性解锁”:

​Lua 脚本逻辑​
-- KEYS[1]: 锁的键(如 "order:userId")
-- ARGV[1]: 当前线程的标识(如 "thread:123")
if redis.call("GET", KEYS[1]) == ARGV[1] thenreturn redis.call("DEL", KEYS[1])  -- 锁归属匹配,删除锁
elsereturn 0  -- 锁已被其他线程持有,不操作
end
​Java 中调用 Lua 脚本(以 Spring Data Redis 为例)​
public void unlock(String lockKey, String threadId) {// 定义 Lua 脚本String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +"   return redis.call('del', KEYS[1]) " +"else " +"   return 0 " +"end";// 执行脚本(KEYS 参数是锁的键,ARGV 参数是线程 ID)Long result = stringRedisTemplate.execute(new DefaultRedisScript<>(script, Long.class),Collections.singletonList(lockKey),threadId);// result 为 1 表示删除成功,0 表示锁已被其他线程持有
}

​五、总结​

  • ​Redis 的 Lua 脚本​​:在服务端原子性执行多条命令,解决分布式场景下的原子性问题(如分布式锁)。
  • ​Lua 语言​​:轻量、高效、可嵌入,核心特点是“表”和“函数”,语法简单易学。
  • ​实际应用​​:通过 Lua 脚本可以将多个 Redis 操作合并为一个原子操作,避免网络开销和中间状态不一致的问题(如分布式锁的解锁、库存扣减等)。
http://www.xdnf.cn/news/1169767.html

相关文章:

  • web登录页面
  • Elasticsearch Java 8.x 的聚合 API 及子聚合的用法
  • 外网访问内部私有局域网方案,解决运营商只分配内网IP不给公网IP问题
  • iOS加固工具有哪些?从零源码到深度混淆的全景解读
  • DearMom以“新生儿安全系统”重塑婴儿车价值,揽获CBME双项大奖
  • vue2.0 + elementui + i18n:实现多语言功能
  • fuse低代码工作流平台概述【已开源】-自研
  • Java中关于线程池的解析
  • Qt 事件处理机制深入剖析
  • 厌氧菌数据挖掘可行性评估报告
  • 深入理解 Qt 中的 QImage 与 QPixmap:底层机制、差异、优化策略全解析
  • PyQt5在Pycharm上的环境搭建 -- Qt Designer + Pyuic + Pyrcc组合,大幅提升GUI开发效率
  • stm32 智能小车
  • [2025CVPR-小目标检测方向]基于特征信息驱动位置高斯分布估计微小目标检测模型
  • AI视频-剧本篇学习笔记
  • LeetCode 633.平方数之和
  • Leetcode力扣解题记录--第73题(矩阵置零)
  • RabbitMQ-交换机(Exchange)
  • 【大模型记忆实战Demo】基于SpringAIAlibaba通过内存和Redis两种方式实现多轮记忆对话
  • Arraylist与LinkedList区别
  • STM32-SPI全双工同步通信
  • LWIP学习记录2——MAC内核
  • mybatis多对一一对多的关联及拼接操作以及缓存处理
  • 【学习路线】Python全栈开发攻略:从编程入门到AI应用实战
  • Custom SRP - Draw Calls
  • Claude Code Kimi K2 环境配置指南 (Windows/macOS/Ubuntu)
  • python小工具:测内网服务器网速和延迟
  • Qt资源系统:如何有效管理图片和文件
  • Canmv k230 DAC案例——TLV5638
  • 104.二叉树的最大深度