一、前言:为什么先学变量和循环?
在 Redis 中编写 Lua 脚本时,你最常写的代码就是:
- 定义变量存储 key 或参数
- 用循环遍历多个 key 执行操作
变量和循环是 Lua 脚本的"地基"。掌握它们,你就能写出安全、高效的原子操作!
本文将带你彻底搞懂 Lua 的变量作用域、数据类型、三大循环结构,并结合 Redis 场景实战演示。
二、Lua 变量:简单但有"坑"
2.1 变量无需声明,直接赋值
Lua
name = "Alice" -- 字符串
count = 100 -- 数字(整数/浮点统一)
isOk = true -- 布尔值
empty = nil -- 空值
✅ 动态类型:变量类型由值决定,运行时可变。
2.2 全局变量 vs 局部变量(重点!)
全局变量(不推荐)
Lua
x = 10 -- 默认是全局变量,所有脚本共享
局部变量(强烈推荐!)
Lua
local y = 20 -- 仅在当前作用域有效
⚠️ Redis 脚本最佳实践 :始终用
local声明变量 !原因:
- 避免污染全局环境
- 提升性能(局部变量访问更快)
- 防止多脚本间意外干扰
2.3 特殊值:nil 和 false
Lua 中只有两个"假"值:
nil(未定义)false
💡 注意:0、空字符串
""、空表{}都是"真"!
Lua
if 0 then print("0 是真") end --> 输出
if "" then print('"" 是真') end --> 输出
三、Lua 循环:三种方式全解析
Lua 提供三种循环结构:while、repeat-until、for。其中 for 最常用。
3.1 while 循环:条件为真时重复
Lua
local i = 1
while i <= 3 do
print(i)
i = i + 1
end
-- 输出:1 2 3
🔧 适用场景:不确定循环次数,依赖动态条件。
3.2 repeat-until 循环:至少执行一次
Lua
local j = 5
repeat
print(j)
j = j - 1
until j < 3
-- 输出:5 4 3
🔁 特点:先执行,再判断(类似 C/Java 的 do-while)。
3.3 for 循环:最常用!分两种
(1) 数值 for(推荐用于计数)
Lua
-- 语法:for 变量 = 起始, 结束 [, 步长] do ... end
for i = 1, 5 do
print(i)
end
-- 输出:1 2 3 4 5
-- 带步长(递减)
for k = 10, 1, -2 do
print(k)
end
-- 输出:10 8 6 4 2
✅ 优点:简洁、高效、自动管理变量生命周期。
(2) 泛型 for(用于遍历 table)
Lua
-- 遍历数组(注意:Lua 数组索引从 1 开始!)
local fruits = {"apple", "banana", "orange"}
for index, value in ipairs(fruits) do
print(index, value)
end
-- 输出:
-- 1 apple
-- 2 banana
-- 3 orange
-- 遍历字典(无序)
local user = {name = "Bob", age = 30}
for key, value in pairs(user) do
print(key, value)
end
🔑 关键区别:
ipairs():只遍历连续数字索引(1,2,3...)pairs():遍历所有键值对(包括字符串 key)
四、Redis 脚本实战:变量 + 循环的典型用法
场景:批量删除以 "temp:" 开头的 key
错误写法(在 Lua 中不能用 KEYS 模糊匹配!)
Lua
-- ❌ Redis 不支持在 Lua 中执行 KEYS * 命令!
正确做法:客户端传入 key 列表
Lua
-- 脚本:delete_keys.lua
for i = 1, #KEYS do
redis.call('DEL', KEYS[i])
end
return #KEYS
在 Java 中调用(Spring Boot)
java
List<String> keysToDelete = Arrays.asList("temp:1", "temp:2", "temp:3");
Long deleted = redisTemplate.execute(
new DefaultRedisScript<>("for i=1,#KEYS do redis.call('DEL',KEYS[i]) end return #KEYS", Long.class),
keysToDelete
);
System.out.println("删除了 " + deleted + " 个 key");
✅ 关键点:
#KEYS表示 KEYS 表的长度(Lua 中#用于获取数组长度)- 循环从
1到#KEYS(因为 Lua 数组索引从 1 开始!)
五、常见误区与避坑指南
❌ 误区 1:数组索引从 0 开始
- 错误 :
for i = 0, #KEYS-1 do ... KEYS[i] ... - 正确 :
for i = 1, #KEYS do ... KEYS[i] ...
❌ 误区 2:忘记用 local
- 危险 :
i = 1→ 全局变量,可能被其他脚本修改 - 安全 :
local i = 1
❌ 误区 3:在循环中修改 table 长度
- 问题:边遍历边删除元素,可能导致跳过或崩溃
- 建议:先收集要删除的 key,再统一处理
六、小结:核心要点速记
| 主题 | 关键规则 |
|---|---|
| 变量 | 用 local 声明;只有 nil 和 false 为假 |
| 数组索引 | 从 1 开始!不是 0 |
| 数值 for | for i = 1, 10 do ... end |
| 遍历数组 | 用 ipairs() |
| 遍历字典 | 用 pairs() |
| Redis 脚本 | KEYS 和 ARGV 是 table,索引从 1 开始 |
七、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!