(参考:https://www.runoob.com/lua/lua-tutorial.html)
一、基础
1、打印
print("Hello") print(123)
运行结果:
Hello
123
2、注释
--line mark,单行注释 --[[ 多行注释 many line mark ]]--
3、变量赋值
--默认是全局变量 print(b) b=10 print(b) html=[[ 1a 2bc 3def 4g qwe ]] print(html)
运行结果:
nil
10
1a
2bc
3def
4g
qwe
4、数字加和字符串连接
a='1' b=2 --+的都以数字处理 print(a+b) --这种才是字符串连接 print(a .. b)
运行结果:
3.0
12
5、数组、列表
--tab既可以当数组用,也可以当做map用
--lua的下标是从1开始的
tab1 = {"a","b","c"} for k in pairs(tab1) do print(k .. ":" .. tab1[k]) end
运行结果:
1:a
2:b
3:c
6、循环
--初始值,截止值,步长(默认是1) for i=10,1,-2 do print(i) end --除了pairs,ipairs也可以迭代 a = {"one","two","three"} --lua脚本可以“放在一行”,该加“;”就加分号 for i,v in ipairs(a) do print(i, v);print(i .. ":" .. v) end
运行结果:
10
8
6
4
2
1 one
1:one
2 two
2:two
3 three
3:three
7、if判断
--0是true if(0) then print("0 is true") end num = 100 --if else的使用 if(num<20) then print("num < 20") else print("num >= 20") end print("num value is :", num) --多重判断 -- if then elseif then else end
运行结果:
0 is true
num >= 20
num value is : 100
8、字符串查找
--返回值startIndex,endIndex,start 1 s,e=string.find("www.runoob.com", "run") print(s,e)
运行结果:
5 7
二、函数调用
1、定义函数,并调用
function max(num1, num2) if(num1 > num2) then result = num1 else result = num2 end return result end print("the max is:", max(10, 4)) print("the max is:", max(5,6))
运行结果:
the max is: 10
the max is: 6
2、函数作为参数传递
myprint = function(param) print("This is print function - ##", param, "##") end function add(num1, num2, funcPrint) result = num1 + num2 funcPrint(result) end myprint(100) add(2,5,myprint)
运行结果:
This is print function - ## 100 ##
This is print function - ## 7 ##
3、不定长参数传递
--not fix args num function add_many(...) local s = 0 for i,v in ipairs{...} do s = s+v end return s end print(add_many(1,2,3,4,5))
运行结果:
15
4、不定长参数长度
a、通过#arg获取长度
b、通过select("#",...)获取长度
function average(...) local res = 0 local arg = {...} for i,v in ipairs(arg) do res = res + v end --#arg or select("#", ...) print("arg num is:" .. #arg .. ".") return res/#arg end print(average(1,2,3,4,5))
运行结果:
arg num is:5.
3.0
三、理论实践
1、redis+lua
1)不使用lua的流程
2)使用lua的流程
因为redis单线程的特性,所以不需要再进行加锁的操作。
3)示例脚本,未被执行校验
local key,set_key,no_key,ttl=KEYS[1],KEYS[2],KEYS[3],ARGV[1] local save_val = redis.call('get', key) --key不存在 if(save_val == nil) then --取新编号 save_val = redis.call('incrby', no_key) --存储key和编号,并加过期时间 redis.call('set', key, save_val, 'EX', ttl) --将key放入列表 redis.call('LPUSH', set_key, key) end return save_val
单行:
local key,set_key,no_key,ttl=KEYS[1],KEYS[2],KEYS[3],ARGV[1];local save_val = redis.call('get', key);if(save_val == nil) then save_val = redis.call('incrby', no_key) redis.call('set', key, save_val, 'EX', ttl) redis.call('LPUSH', set_key, key) end return save_val
4)结论
对比流程可以发现,因为redis单线程的特性,加上lua被执行时的原子性,大大简化了代码的步骤,而且也减少网络传输(从6次变为2次)。
lua真好,值得学习。
至于线上能不能够大规模使用,我觉得类似于DB中的存储过程一样。因为是单线程的,如果lua逻辑较复杂,则可能导致redis的cpu负载较高。
线上使用前最好进行压测,对比一下。