lua学习记录

(参考: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负载较高。

线上使用前最好进行压测,对比一下。

原文地址:https://www.cnblogs.com/shuimutong/p/12497952.html