redis eval表达式1

 

Lua(发音类似 Loo-ah)是一门轻量级脚本语言,由巴西里约热内卢天主教大学开发。Redis 之所以选择 Lua,是因为它语法简单、运行速度快、容易嵌入到其他程序中

很多 Java 开发者接触 Lua,都是从 Redis 的 EVAL 开始的,所以这里我从 Java 开发者的视角 来介绍 Lua 的常用语法。


1. Lua 的基本特点

 
动态类型
解释执行
语法简单
支持函数式编程
支持面向过程编程
只有一种复杂数据结构:Table
 

Lua 类似于:

 
Java + JavaScript 的结合体
 

例如:

Java:

 
int a = 10;
 

Lua:

 
a = 10
 

不需要定义类型。


2. 变量定义

Lua 默认变量是全局变量。

 
name = "Tom"

print(name)
 

输出:

 
Tom
 

局部变量:

 
local age = 18

print(age)
 

Redis Lua 中几乎都会写:

 
local value = redis.call(...)
 

避免污染全局变量。


3. 数据类型

Lua 主要有:

 
nil
boolean
number
string
function
table
userdata
thread
 

Redis Lua 常见的是:

 
local a = 10
local b = true
local c = "hello"
local d = {}
 

nil

类似 Java 的 null

 
local a

print(a)
 

输出:

 
nil
 

number

Lua 中整数和小数都属于 number。

 
local a = 100

local b = 3.14
 

string

 
local name = "Jack"

local city = 'Beijing'
 

拼接:

 
print(name .. city)
 

输出:

 
JackBeijing
 

注意:

Lua 使用:

 
..
 

而不是:

 
+
 

4. 判断语句

Java:

 
if(age > 18){
...
}else{
...
}
 

Lua:

 
if age > 18 then
print("adult")
else
print("child")
end
 

Redis 最常见:

 
if redis.call('EXISTS', KEYS[1]) == 1 then
return 1
else
return 0
end
 

5. 循环

while

 
local i = 1

while i <= 5 do
print(i)

i = i + 1
end
 

for

Java:

 
for(int i=1;i<=5;i++)
 

Lua:

 
for i = 1,5 do
print(i)
end
 

输出:

 
1
2
3
4
5
 

步长:

 
for i = 1,10,2 do
print(i)
end
 

输出:

 
1
3
5
7
9
 

6. Table(最重要)

Lua 中没有:

 
List
Map
Set
对象
 

这些都是 Table 实现的。


当数组用

 
local arr = {1,2,3}

print(arr[1])
 

输出:

 
1
 

注意:

Lua 下标从 1 开始

不是 Java 的:

 
0
 

遍历:

 
for i,v in ipairs(arr) do
print(i,v)
end
 

输出:

 
1 1
2 2
3 3
 

当 Map 用

 
local user = {}

user["name"] = "Tom"

user["age"] = 18
 

访问:

 
print(user["name"])
 

或者:

 
print(user.name)
 

输出:

 
Tom
 

模拟对象

 
local person = {

name = "Jack",

age = 18
}

print(person.name)
 

输出:

 
Jack
 

7. 函数

定义:

 
function add(a,b)

return a+b

end
 

调用:

 
print(add(1,2))
 

输出:

 
3
 

匿名函数:

 
local f = function(a,b)

return a+b

end
 

8. 逻辑运算

 
and
or
not
 

类似 Java:

 
&&
||
!
 

例如:

 
if age > 18 and age < 60 then
print("成年人")
end
 

9. Redis Lua 中的特殊变量

执行:

 
EVAL script 2 key1 key2 arg1 arg2
 

Lua 中:

 
KEYS[1] = key1

KEYS[2] = key2

ARGV[1] = arg1

ARGV[2] = arg2
 

例如:

 
EVAL "
return KEYS[1] .. ':' .. ARGV[1]
" 1 user Tom
 

结果:

 
user:Tom
 

10. Redis Lua 常见写法

判断并删除

 
if redis.call('GET', KEYS[1]) == ARGV[1] then

return redis.call('DEL', KEYS[1])

end

return 0
 

扣减库存

 
local stock = tonumber(redis.call('GET', KEYS[1]))

if stock > 0 then

redis.call('DECR', KEYS[1])

return 1

end

return 0
 

限流

 
local count = redis.call('INCR', KEYS[1])

if count == 1 then

redis.call('EXPIRE', KEYS[1], ARGV[1])

end

if count > tonumber(ARGV[2]) then

return 0

end

return 1
 

11. Lua 和 Java 的对照

JavaLua
int a=1; a=1
String s="abc"; s="abc"
null nil
&& and
|| or
! not
+ 字符串拼接 ..
List Table
Map Table
数组下标 0 开始 数组下标 1 开始
for(int i=0;i<n;i++) for i=1,n do

12. Java 工程师学习 Lua 的重点

如果你的目标只是为了使用 Redis Lua,那么实际上只需要掌握下面这些内容:

 
✓ local
✓ if ... then ... end
✓ tonumber()
✓ tostring()
✓ Table 的基本使用
✓ KEYS 和 ARGV
✓ redis.call()
✓ return
 

大概 1~2 小时就足够应付 90% 的 Redis Lua 场景

例如下面这个分布式锁释放脚本:

 
if redis.call('GET', KEYS[1]) == ARGV[1] then
return redis.call('DEL', KEYS[1])
else
return 0
end
 

如果你能看懂这段代码,就已经具备在 Redis 中编写 Lua 脚本的能力了。

对于 Java 开发者来说,可以把 Lua 理解为:

一种运行在 Redis 内部、用于把多个 Redis 命令组合成原子操作的小型脚本语言。

 

posted on 2026-07-05 16:04  日思日睿  阅读(3)  评论(0)    收藏  举报