springboot lua檢查redis庫存的實現(xiàn)示例
需求
最近需求需要實現(xiàn)檢查多個馬戲場次下的座位等席對應(yīng)庫存渠道的庫存余量,考慮到性能,決定采用Lua腳本實現(xiàn)庫存檢查。
數(shù)據(jù)結(jié)構(gòu)
庫存層級結(jié)構(gòu)

redis庫存hash類型結(jié)構(gòu)

實現(xiàn)
lua腳本
--- 字符串分割為數(shù)組
local function split(str, char)
local arr = {};
local pattern = string.format('([^%s]+)', char);
for item in string.gmatch(str, pattern) do
table.insert(arr, item);
end
return arr;
end
--- 數(shù)組轉(zhuǎn)成map
local function toMap(tb)
if (tb == nil) then
return {};
end
local map = {};
for i = 1, #tb do
if (i % 2 == 1) then
map[tb[i]] = tb[i+1];
end
end
return map;
end
--- 初始化數(shù)據(jù),入?yún)?1:1,02:2.01:3
local argArr = {};
for rowItem in string.gmatch(ARGV[1], '([^.]+)') do
local row = {};
for keyVal in string.gmatch(rowItem, '([^,]+)') do
-- 解析出每個key與value
local tempArr = split(keyVal, ':');
row[tempArr[1]] = tempArr[2];
end
table.insert(argArr, row);
end
--- 檢查庫存
for i = 1, #KEYS do
--local rData = redis.call("HMGET", KEYS[i], '01 02');
local rdsMap = toMap(redis.call("HGETALL", KEYS[i]));
for tier, quantity in pairs(argArr[i]) do
--redis.log(redis.LOG_NOTICE, string.format('key is:%s,tier is:%s,quantity is:%s', KEYS[i], tier, quantity));
if (rdsMap[tier] == nil or tonumber(quantity) > tonumber(rdsMap[tier])) then
return string.format("庫存key:%s,tier:%s不足", KEYS[i], tier);
end
end
end
return '';
遍歷鍵值對時需要使用pairs而不是ipairs,二者區(qū)別如下:
for k,v in pairs(argArr)的遍歷順序并非是table類型數(shù)據(jù)的排列順序,而是根據(jù)table中key的hash值排列的順序來遍歷的。
for k,v in ipairs(argArr)必須要求table中的key為有序的,而且必須是從1開始,ipairs只會從1開始按連續(xù)的key順序遍歷到key不連續(xù)為止。
- 入?yún)⒃O(shè)計
由于RedisTemplate直接傳入集合為參數(shù)序列化后會有中括號,而lua腳本table類型使用花括號定義,因此采用字符串作為入?yún)ⅲ趌ua腳本中解析字符串為table類型。例如參數(shù)01:1,02:2.01:3代表二維數(shù)組,第一行為01:1,02:2,其中01為渠道,1為渠道對應(yīng)的庫存,英文逗號作為渠道分隔符。 - springboot調(diào)用lua腳本
@Autowired
private StringRedisTemplate redisJsonTemplate;
@Test
public void checkInventory() {
List<String> keyList = List.of("stock:GZ7:433680411156197407", "stock:GZ7:433680411156197408");
// 執(zhí)行 lua 腳本
DefaultRedisScript<String> redisScript = new DefaultRedisScript<>();
// 指定 lua 腳本
redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("/lua/TheaterStockCheck.lua")));
// 指定返回類型
redisScript.setResultType(String.class);
Object result = redisJsonTemplate.execute(redisScript, keyList, "01:1,0101:2.01:3");
//01:1,02:2.01:3
System.out.println(result);
}
調(diào)用lua腳本需要使用string序列化方式,使用jdk序列化方式會導(dǎo)致序列化后的數(shù)據(jù)lua腳本無法解析
測試效果
redis庫存數(shù)據(jù)

調(diào)用效果

到此這篇關(guān)于springboot lua檢查redis庫存的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)springboot lua檢查redis庫存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot整合EasyCaptcha實現(xiàn)圖形驗證碼功能
這篇文章主要介紹了SpringBoot整合EasyCaptcha實現(xiàn)圖形驗證碼功能,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2024-02-02
基于spring?data?jpa?@query返回map的踩坑記錄
這篇文章主要介紹了基于spring?data?jpa?@query返回map的踩坑記錄,具有很好的參考價值,如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
Spring Boot的應(yīng)用啟動與關(guān)閉的方法
本篇文章主要介紹了Spring Boot的應(yīng)用啟動與關(guān)閉的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12
Spring Boot整合Spring Data Jpa代碼實例
這篇文章主要介紹了Spring Boot整合Spring Data Jpa代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-11-11
idea?compile項目正常啟動項目的時候build失敗報“找不到符號”等問題及解決方案
這篇文章主要介紹了idea?compile項目正常,啟動項目的時候build失敗,報“找不到符號”等問題,這種問題屬于lombok編譯失敗導(dǎo)致,可能原因是依賴jar包沒有更新到最新版本,需要的朋友可以參考下2023-10-10

