redis lua 抽奖 PHP,通过redis+lua实现加减库存
一. 場景
下單后庫存校驗或者秒殺場景下,有很多利用“鎖”的方案來解決問題。但是加鎖其實是一件性價比很低的事,所以我們采用用redis+lua的方式來實現這個功能。
二. 思路
階段一:
在庫存加減邏輯中分為2個步驟:STEP1.讀取庫存,STEP2.讀取庫存。
利用其他方法例如"鎖"等,也就是想控制好STEP2一定要緊跟STEP1,本質上就是確保獲取的庫存的最新的數據為最新。
階段二:
在相對較高的并發場景下,redis被常用作庫存管理,我們需要通過最小成本的改動來實現庫存的限制。但是redis的讀取庫存+讀取庫存一般都是有上層應用代碼控制,有沒有辦法在一個函數調用中能串行執行這倆個步驟了?
階段三:
眾所周知,redis是單線程的,并且現在已經支持lua腳本,那是不是可以利用該組合實現我們的場景了?
三. 設計方案
這個方案就很簡單了,直接利用redistemplate執行lua腳本
四. 代碼
4.1 lua腳本代碼樣例
private static final String GET_COUPON_CODE =
"local values = redis.call('hmget',KEYS[1],'recvCnt','couponCnt');\n" + //lua返回value的數組
"if tonumber(values[1]) < tonumber(values[2]) then \n" + //lua的數組索引從1開始 values[1] = recvCnt,values[2] = couponCnt
" redis.call('hincrby',KEYS[1],'recvCnt',1);\n" +
" return true;\n" +
"else\n " +
" return false;\n" +
"end\n";
4.2 redis調用lua腳本
//執行調用
execute(GET_COUPON_CODE, keys);
//此處將數值類型轉化為Long
public Long execute(String redisScript,List keys){
RedisScript REDIS_SCRIPT = new DefaultRedisScript<>(redisScript, Long.class);
return redisTemplate.execute(REDIS_SCRIPT,keys);
}
4.3 lua基本用法
redis.call()
redis.pcall()
call與pcall基本上一樣。腳本報錯時,call會直接報錯,pcall不會報錯,會把錯誤信息放到lua table 的err字段中。
五. 說明
1.記得利用“\n”分行,也可以利用string的append拼接
2.values[n]對應有序數組keys,需要控制好各數據順序
3.lua的數組索引從1開始
六. 總結
我們先分析場景,通過多種方案對比,選用了redis+lua的組合來滿足我們的業務需要。利用redis單線程的特點,以及redis2.6版本后開始對lua的支持,我們采用redis執行lua腳本來確保我們查詢+修改的串行執行。后面我們展示了code的實現案例,以及介紹了lua腳本的一些注意事項,可以依葫蘆畫瓢形式自己實現自己的需求。綜合而言,我們分析場景應先分析其核心問題,然后利用一些更簡潔的方法或小技巧來落地。
總結
以上是生活随笔為你收集整理的redis lua 抽奖 PHP,通过redis+lua实现加减库存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 麻黄汤的组成及功效
- 下一篇: php post nginx 400,N