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

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

實(shí)現(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
-- 解析出每個(gè)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 '';
遍歷鍵值對(duì)時(shí)需要使用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只會(huì)從1開始按連續(xù)的key順序遍歷到key不連續(xù)為止。
- 入?yún)⒃O(shè)計(jì)
由于RedisTemplate直接傳入集合為參數(shù)序列化后會(huì)有中括號(hào),而lua腳本table類型使用花括號(hào)定義,因此采用字符串作為入?yún)?,在lua腳本中解析字符串為table類型。例如參數(shù)01:1,02:2.01:3代表二維數(shù)組,第一行為01:1,02:2,其中01為渠道,1為渠道對(duì)應(yīng)的庫存,英文逗號(hào)作為渠道分隔符。 - 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序列化方式會(huì)導(dǎo)致序列化后的數(shù)據(jù)lua腳本無法解析
測(cè)試效果
redis庫存數(shù)據(jù)

調(diào)用效果

到此這篇關(guān)于springboot lua檢查redis庫存的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)springboot lua檢查redis庫存內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用JWT如何實(shí)現(xiàn)對(duì)API的授權(quán)訪問詳解
這篇文章主要給大家介紹了關(guān)于利用JWT如何實(shí)現(xiàn)對(duì)API的授權(quán)訪問的相關(guān)資料,需要的朋友可以參考下2018-09-09
Java實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04
springboot中json對(duì)象中對(duì)Long類型和String類型相互轉(zhuǎn)換
與前端聯(lián)調(diào)接口時(shí),后端一些字段設(shè)計(jì)為L(zhǎng)ong類型,這樣就有可能導(dǎo)致前端缺失精度,這時(shí)候我們就需要將Long類型返回給前端時(shí)做數(shù)據(jù)類型轉(zhuǎn)換,本文主要介紹了springboot中json對(duì)象中對(duì)Long類型和String類型相互轉(zhuǎn)換,感興趣的可以了解一下2023-11-11
在SpringBoot中集成H2數(shù)據(jù)庫的完整指南
Spring Boot是一個(gè)簡(jiǎn)化企業(yè)級(jí)Java應(yīng)用程序開發(fā)的強(qiáng)大框架,H2數(shù)據(jù)庫是一個(gè)輕量級(jí)的、開源的SQL數(shù)據(jù)庫,非常適合用于開發(fā)和測(cè)試,本文將指導(dǎo)您如何在Spring Boot應(yīng)用程序中集成H2數(shù)據(jù)庫,并探索一些高級(jí)配置選項(xiàng),需要的朋友可以參考下2024-10-10
Java刷題之最小k個(gè)數(shù)的思路及具體實(shí)現(xiàn)
這篇文章主要介紹了Java刷題之最小k個(gè)數(shù)的思路及具體實(shí)現(xiàn),最小K個(gè)數(shù)是一個(gè)經(jīng)典的top-K問題,可以通過整體排序、建立小根堆或大根堆的方式解決,排序方式時(shí)間復(fù)雜度較高,適合數(shù)據(jù)量小的場(chǎng)景,小根堆適合k較小的情況,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-10-10

