柚子快報邀請碼778899分享:Lua腳本簡單理解
目錄
1.安裝
2.語法
2.1Lua數(shù)據(jù)類型
2.2變量
2.3lua循環(huán)
2.4流程控制
2.5函數(shù)
2.6運算符
2.7關(guān)系運算符
3.lua腳本在redis中的使用
3.1lua腳本再redis簡單編寫
3.2普通鎖Lua腳本
3.3可重入鎖lua腳本
1.安裝
centos安裝
安裝指令:
yum -y update
yum install lua
啟動指令:
?
lua
print("hello world")
windos安裝
Lua Binaries Download
解壓后在環(huán)境變量配置
再cmd中嘗試,安裝成功
也可以在idea中使用
2.語法
2.1Lua數(shù)據(jù)類型
nil 表示無效值。相當于false
boolean 包含兩個值:false,true
number 雙精度浮點數(shù)
string 字符串由一對雙引號或者單引號表示
function 由c或lua編寫函數(shù)
table lua中的表(taboe) “關(guān)聯(lián)數(shù)組“(associative arrays),數(shù)組的索引可以是數(shù)字、字符串或表類型。在lua里,table的創(chuàng)建是通過"構(gòu)造表達式完成",最簡單構(gòu)造表達式是{}。
-- 變量
print(type(nil))
print(type(false))
print(type(1))
print(type(1.1))
print(type(type))
print(type("hello world"))
print(type({1,2}))
2.2變量
Lua變量有三種類型:全局類型、局部變量、表中的域
沒有使用local進行修飾的變量都是全局變量,使用local修飾的則為局部變量局部變量的作用域為從聲明位置開始到所在語句塊結(jié)束變量默認值都為nil
--變量
a = 5 --全局變量
print(a) -- 5
local b = 6 --局部變量
print(b) -- 6
-- 查看變量、全局變量、局部變量
do
local c = 4
print(a) -- 5
print(c) -- 4
end
print(c) -- nil
--對多個變量同時賦值 ..表示為字符串連接
a, b, c= 1,2 -- 沒有值的變量,賦值nil
print(a .."-" .. b)
print(c)
a, b = 2,3,4 --多出來的值被省略
print(a .. "-" .. b)
-- table賦值 如果key值一樣后面的會覆蓋前面的值
tal = {"a", "b", "3"}
print(tal[1] .. tal[2] .. tal[3])
tal = {key = "xxddd", key1 = "yysss"}
print(tal["key"] .. tal["key1"])
2.3lua循環(huán)
--while 循環(huán)
a = 1
while(a < 5) do
print(a)
a = a + 1
end
--for 循環(huán),從exp1開始循環(huán)到exp2, exp3是步?
for var=exp1, exp2, xep3 do
end
for i = 1, 5, 1 do
print(i)
end
for i = 5, 1, -1 do
print(i)
end
--打印數(shù)組
a = {"one", "two", "three"}
for i, v in ipairs(a) do
print(i, v)
end
2.4流程控制
--流程控制
a = 9
if (a < 10) then
print("?于10")
end
a = 11
if (a < 10) then
print("?于10")
else
print("?于等于10")
end
a = 10
if (a < 10) then
print("?于10")
elseif (a == 10) then
print("等于10")
else
print("?于10")
end
2.5函數(shù)
--函數(shù)
function max(a, b)
if (a < b) then
print("a?于b")
elseif(a == b) then
print("a等于b")
else
print("a?于b")
end
end
print(max(5, 5))
--函數(shù)作為參數(shù)傳遞給函數(shù)
myFunc = function(param)
print("這是param" .. param)
end
function myFuncB (a, b, func)
result = a + b
func(result)
end
myFuncB(1, 2, myFunc)
--可變參數(shù)函數(shù)
function aa(...)
local arg={...}
for i, v in pairs(arg) do
print(i .. v)
end
end
aa("a", "b", "c")
2.6運算符
正常+ - * / % ^ -? 特殊//整除運算符 比如5//2 輸出結(jié)果為2
算數(shù)運算符號
--算術(shù)運算符
print(1 + 2)
print(2 - 1)
print(2 * 1)
print(-10)
print(10 / 6)
print(10 % 6)
print(10 // 6)
print(10 ^ 2)
2.7關(guān)系運算符
正常 == >?>= ?<=
特殊:~=(不等于)
關(guān)系運算符
and or not
其他運算符號
..? ? 連接兩個字符串
# 一元運算符,返回字符串或表的長度
#“hello” 返回5
3.lua腳本在redis中的使用
3.1lua腳本再redis簡單編寫
redis中支持使用EVAL關(guān)鍵字來使用Lua腳本
eval指令中的1 表示key的個數(shù),以下代碼實例是表示keys[1]? 等于在1的后面的key1,即keys[1]=key1,但是value中是不需要聲明的。
EVAL script numkeys key [key …] arg [arg …]
127.0.0.1:6379> eval "return {KEYS[1],ARGV[1],ARGV[2]}" 1 key1 arg1 arg2
1) "key1"
2) "arg1"
3) "arg2"
127.0.0.1:6379>
在redis中執(zhí)行
eval 執(zhí)行執(zhí)行
這個keys和argv必須是大寫,不然會報錯
eval "return redis.call('set',KEYS[1],ARGV[1])" 1 name xiaoming
也可以把指令進行緩存
script load ->evalsha 對應id
script load "return redis.call('set',KEYS[1],ARGV[1])"
返回:c686f316aaf1eb01d5a4de1b0b63cd233010e63d
evalsha c686f316aaf1eb01d5a4de1b0b63cd233010e63d 1 name1 zhangsan
evalsha c686f316aaf1eb01d5a4de1b0b63cd233010e63d 1 name2 zhangsan2
--判斷指令是否存在
script exists c686f316aaf1eb01d5a4de1b0b63cd233010e63d
--刪除指令
script flush c686f316aaf1eb01d5a4de1b0b63cd233010e63d
3.2簡易鎖Lua腳本
加鎖
ps:lua腳本中指令要對應單引號
//判斷redis中是否存在key
// 如果不存在,那么就使?set key value,并且增加過期時間,返回1.
// 如果存在,直接返回0,繼續(xù)循環(huán)獲取鎖
//正常編寫
if (redis.call('exists',lockName) == 0) then
redis.call('set',lockName,uuid);
redis.call('pexpire',lockName,30000)
return 1;
else
return 0;
end;
//替換成腳本
if (redis.call('exists',KEYS[1]) == 0) then
redis.call('set',KEYS[1],ARGV[1]);
redis.call('pexpire',KEYS[1],ARGV[2])
return 1;
else
return 0;
end;
在redis中跑一遍
eval "if (redis.call('exists',KEYS[1]) == 0) then redis.call('set',KEYS[1],ARGV[1]); redis.call('pexpire',KEYS[1],ARGV[2]) return 1; else return 0; end" 1 lockName uuid 30000
釋放鎖
//判斷鎖是否存在,如果不存在,直接返回0
//如果鎖存在,判斷value是否==當前線程的uuid
// 如果等于,執(zhí)?delete
// 如果不等于,返回0
//正常寫
if (redis.call('exists',lockName) == 0) then
return 0;
end;
if (redis.call('get',lockName) == uuid) then
redis.call('del',lockName)
return 1;
else
return 0;
end;
if (redis.call('exists',KEYS[1]) == 0) then
return 0;
end;
if (redis.call('get',KEYS[1]) == ARGV[1]) then
redis.call('del',KEYS[1])
return 1;
else
return 0;
end;
reids執(zhí)行腳本
eval "if (redis.call('exists', KEYS[1]) == 0) then return 0; end; if (redis.call('get', KEYS[1]) == ARGV[1]) then redis.call('del', KEYS[1]); return 1; else return 0; end;" 1 lockName uuid
3.3可重入鎖lua腳本
可以通過hash的數(shù)據(jù)結(jié)構(gòu)進行對鎖的添加次數(shù),和扣減測試進行設置
加鎖
//redis中執(zhí)?可重?加鎖lua腳本
eval "if(redis.call('exists',KEYS[1]) == 0) then redis.call('hincrby',KEYS
[1],ARGV[1],1); redis.call('pexpire',KEYS[1],ARGV[2]) return 1; end; if(re
dis.call('hexists',KEYS[1],ARGV[1]) == 1) then redis.call('hincrby',KEYS
[1],ARGV[1],1); redis.call('pexpire',KEYS[1],ARGV[2]) return 1; else retur
n 0; end;" 1 lockName uuid 30000
//可重?加鎖lua腳本
//判斷鎖是否存在
//如果不存在,就加鎖,設置過期時間
//如果存在,判斷加鎖的線程是不是??
//如果是,重?次數(shù)+1
//如果不是,加鎖失敗
if(redis.call('exists',KEYS[1]) == 0) then
redis.call('hincrby',KEYS[1],ARGV[1],1);
redis.call('pexpire',KEYS[1],ARGV[2])
return 1;
end;
if(redis.call('hexists',KEYS[1],ARGV[1]) == 1) then
redis.call('hincrby',KEYS[1],ARGV[1],1);
redis.call('pexpire',KEYS[1],ARGV[2])
return 1;
else
return 0;
end;
解鎖
//redis中執(zhí)?可重?解鎖lua腳本
eval "if(redis.call('hexists',KEYS[1],ARGV[1]) == 0) then return 0; end; l
ocal lockCount = redis.call('hincrby',KEYS[1],ARGV[1],-1) if(lockCount>0)t
hen redis.call('pexpire',KEYS[1],ARGV[2]); return 1; else redis.call('de
l',KEYS[1]) return 1; end;" 1 lockName uuid 30000
//可重?解鎖lua腳本
//判斷鎖是否存在且存在是否是本線程加的鎖。也就是加鎖線程是否本身
//如果不是本身,直接就return 0,解鎖失敗了。
//如果是本身,判斷當前重?次數(shù)是否?于1
//如果?于1,說明存在線程多次獲取?把鎖,此時只需要減1即可
//如果不?于0,說明鎖可以被刪除了。
if(redis.call('hexists',lockName,uuid) == 0) then
return 0;
end;
local lockCount = redis.call('hincrby',lockName,uuid,-1)
if(lockCount>0) then
redis.call('pexpire',lockName,time);
return 1;
else
redis.call('del',lockName) return 1;
end;
續(xù)約?
//redis執(zhí)?續(xù)約lua腳本
eval "if(redis.call('hexists',KEYS[1],ARGV[1])==0) then return 0; else red
is.call('pexpire',KEYS[1],ARGV[2]) return 1; end;" 1 lockName uuid 30000
//lua腳本
//判斷鎖是否是本線程加鎖,是的話,就?直延?時間
if(redis.call('hexists',KEYS[1],ARGV[1])==0) then
return 0;
else
redis.call('pexpire',KEYS[1],ARGV[2])
return 1;
end;
柚子快報邀請碼778899分享:Lua腳本簡單理解
相關(guān)文章
本文內(nèi)容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。