秒殺場景:如何通過 Redis 減庫存?
點擊關(guān)注公眾號,Java干貨及時送達
Redis預(yù)減庫存
主要思路減少對數(shù)據(jù)庫的訪問,之前的減庫存,直接訪問數(shù)據(jù)庫,讀取庫存,當高并發(fā)請求到來的時候,大量的讀取數(shù)據(jù)有可能會導(dǎo)致數(shù)據(jù)庫的崩潰。
思路:
系統(tǒng)初始化的時候,將商品庫存加載到Redis 緩存中保存 收到請求的時候,現(xiàn)在Redis中拿到該商品的庫存值,進行庫存預(yù)減,如果減完之后庫存不足,直接返回邏輯Exception就不需要訪問數(shù)據(jù)庫再去減庫存了,如果庫存值正確,進行下一步 將請求入隊,立即給前端返回一個值,表示正在排隊中,然后進行秒殺邏輯,后端隊列進行秒殺邏輯,前端輪詢后端發(fā)來的請求,如果秒殺成功,返回秒殺,成功,不成功就返回失敗。
(后端請求 單線程 出隊,生成訂單,減少庫存,走邏輯)前端同時輪詢
第一步:預(yù)減庫存
/**
?*?秒殺接口優(yōu)化之---???第一步:??系統(tǒng)初始化后就將所有商品庫存放入?緩存
?*/
@Override
public?void?afterPropertiesSet()?throws?Exception?{
????List?goods?=?goodsService.getGoodsList();
????if?(goods?==?null)?{
????????return;
????}
????for?(GoodsVo?goodsVo?:?goods)?{
????????redisService.set(GoodsKey.getGoodsStock,?""?+?goodsVo.getId(),?goodsVo.getStockCount());
????????isOverMap.put(goodsVo.getId(),?false);//先初始化?每個商品都是false?就是還有
????}
}
/**秒殺接口優(yōu)化之?----第二步:?預(yù)減庫存?從緩存中減庫存
?*?利用?redis?中的方法,減去庫存,返回值為?減去1?之后的值
?*?*/
long?stock?=?redisService.decr(GoodsKey.getGoodsStock,?""?+?goodsId);
/*這里判斷不能小于等于,因為減去之后等于?說明還有是正常范圍*/
if?(stock?0)?{
????isOverMap.put(goodsId,?true);//沒有庫存就設(shè)置?對應(yīng)id?商品的map?為true
????return?Result.error(CodeMsg.MIAO_SHA_NO_STOCK);
}
預(yù)減庫存:
1.先將所有數(shù)據(jù)讀出來,初始化到緩存中,并以 stock + goodid 的形成存入Redis,最新面試題整理好了,大家可以在Java面試庫小程序在線刷題。
2.在秒殺的時候,先進行預(yù)減庫存檢測,從redis中,利用decr 減去對應(yīng)商品的庫存,如果庫存小于0,說明此時 庫存不足,則不需要訪問數(shù)據(jù)庫。直接拋出異常即可。
內(nèi)存標記:
于是,可以加一個內(nèi)存map,標記對應(yīng)商品的庫存量是否還有,在訪問Redis之前,在map中拿到對應(yīng)商品的庫存量標記,就可以不需要訪問Redis 就可以判斷沒有庫存了。
1.生成一個map,并在初始化的時候,將所有商品的id為鍵,標記false 存入map中。
private?Map?isOverMap?=?new?HashMap();
/**
?*?秒殺接口優(yōu)化之---???第一步:??系統(tǒng)初始化后就將所有商品庫存放入?緩存
?*/
@Override
public?void?afterPropertiesSet()?throws?Exception?{
????List?goods?=?goodsService.getGoodsList();
????if?(goods?==?null)?{
????????return;
????}
????for?(GoodsVo?goodsVo?:?goods)?{
????????redisService.set(GoodsKey.getGoodsStock,?""?+?goodsVo.getId(),?goodsVo.getStockCount());
????????isOverMap.put(goodsVo.getId(),?false);//先初始化?每個商品都是false?就是還有
????}
}
????/**再優(yōu)化:?優(yōu)化?庫存之后的請求不訪問redis 通過判斷?對應(yīng) map 的值
?????*?*/
????boolean?isOver?=?isOverMap.get(goodsId);
????if?(isOver)?{
????????return?Result.error(CodeMsg.MIAO_SHA_NO_STOCK);
????}
????if?(stock?0)?{
????????isOverMap.put(goodsId,?true);//沒有庫存就設(shè)置?對應(yīng)id?商品的map?為true
2.在預(yù)減庫存之前,從map中取標記,若標記為false,說明庫存
3.預(yù)減庫存,當遇到庫存不足的時候,將該商品的標記置為true,表示該商品的庫存不足。這樣,下面的所有請求,將被攔截,無需訪問redis進行預(yù)減庫存。
原文鏈接:https://blog.csdn.net/weixin_38035852/article/details/81174986
版權(quán)聲明:本文為CSDN博主「Dandy1awcoder」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。

關(guān)注Java技術(shù)棧看更多干貨


