springboot lua檢查redis庫存的實(shí)現(xiàn)示例
需求
最近需求需要實(shí)現(xiàn)檢查多個(gè)馬戲場次下的座位等席對(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)ⅲ趌ua腳本中解析字符串為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腳本無法解析
測試效果
redis庫存數(shù)據(jù)
調(diào)用效果
到此這篇關(guān)于springboot lua檢查redis庫存的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)springboot lua檢查redis庫存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot整合EasyCaptcha實(shí)現(xiàn)圖形驗(yàn)證碼功能
這篇文章主要介紹了SpringBoot整合EasyCaptcha實(shí)現(xiàn)圖形驗(yàn)證碼功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-02-02Java中的MapStruct知識(shí)點(diǎn)總結(jié)
這篇文章主要介紹了Java中的MapStruct知識(shí)點(diǎn)總結(jié),MapStruct是一個(gè)Java注解處理器,用于生成類型安全的映射代碼,它可以自動(dòng)處理源對(duì)象和目標(biāo)對(duì)象之間的映射,減少了手動(dòng)編寫重復(fù)的映射代碼的工作量,需要的朋友可以參考下2023-10-10基于spring?data?jpa?@query返回map的踩坑記錄
這篇文章主要介紹了基于spring?data?jpa?@query返回map的踩坑記錄,具有很好的參考價(jià)值,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11Spring Boot的應(yīng)用啟動(dòng)與關(guān)閉的方法
本篇文章主要介紹了Spring Boot的應(yīng)用啟動(dòng)與關(guān)閉的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-12-12Spring Boot整合Spring Data Jpa代碼實(shí)例
這篇文章主要介紹了Spring Boot整合Spring Data Jpa代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11idea?compile項(xiàng)目正常啟動(dòng)項(xiàng)目的時(shí)候build失敗報(bào)“找不到符號(hào)”等問題及解決方案
這篇文章主要介紹了idea?compile項(xiàng)目正常,啟動(dòng)項(xiàng)目的時(shí)候build失敗,報(bào)“找不到符號(hào)”等問題,這種問題屬于lombok編譯失敗導(dǎo)致,可能原因是依賴jar包沒有更新到最新版本,需要的朋友可以參考下2023-10-10SpringBoot整合Drools的實(shí)現(xiàn)步驟
Drools是一個(gè)易于訪問企業(yè)策略、易于調(diào)整以及易于管理的開源業(yè)務(wù)規(guī)則引擎,符合業(yè)內(nèi)標(biāo)準(zhǔn),速度快、效率高。業(yè)務(wù)分析師或?qū)徍巳藛T可以利用它輕松查看業(yè)務(wù)規(guī)則,從而檢驗(yàn)是否已編碼的規(guī)則執(zhí)行所需的業(yè)務(wù)規(guī)則。本文將講述SpringBoot整合Drools的步驟2021-05-05