Redis預減庫存 主要思路減少對資料庫的訪問,之前的減庫存,直接訪問資料庫,讀取庫存,當高併發請求到來的時候,大量的讀取數據有可能會導致資料庫的崩潰。 思路: 系統初始化的時候,將商品庫存載入到Redis 緩存中保存 收到請求的時候,現在Redis中拿到該商品的庫存值,進行庫存預減,如果減完之後庫 ...
Redis預減庫存
主要思路減少對資料庫的訪問,之前的減庫存,直接訪問資料庫,讀取庫存,當高併發請求到來的時候,大量的讀取數據有可能會導致資料庫的崩潰。
思路:
- 系統初始化的時候,將商品庫存載入到Redis 緩存中保存
- 收到請求的時候,現在Redis中拿到該商品的庫存值,進行庫存預減,如果減完之後庫存不足,直接返回邏輯Exception就不需要訪問資料庫再去減庫存了,如果庫存值正確,進行下一步
- 將請求入隊,立即給前端返回一個值,表示正在排隊中,然後進行秒殺邏輯,後端隊列進行秒殺邏輯,前端輪詢後端發來的請求,如果秒殺成功,返回秒殺,成功,不成功就返回失敗。
(後端請求 單線程 出隊,生成訂單,減少庫存,走邏輯)前端同時輪詢
- 前端顯示
第一步:預減庫存
/**
* 秒殺介面優化之--- 第一步: 系統初始化後就將所有商品庫存放入 緩存
*/
@Override
public void afterPropertiesSet() throws Exception {
List<GoodsVo> 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 就是還有
}
}
/**秒殺介面優化之 ----第二步: 預減庫存 從緩存中減庫存
* 利用 redis 中的方法,減去庫存,返回值為 減去1 之後的值
* */
long stock = redisService.decr(GoodsKey.getGoodsStock, "" + goodsId);
/*這裡判斷不能小於等於,因為減去之後等於 說明還有是正常範圍*/
if (stock < 0) {
isOverMap.put(goodsId, true);//沒有庫存就設置 對應id 商品的map 為true
return Result.error(CodeMsg.MIAO_SHA_NO_STOCK);
}
預減庫存:
1.先將所有數據讀出來,初始化到緩存中,並以 stock + goodid 的形成存入Redis,
2.在秒殺的時候,先進行預減庫存檢測,從redis中,利用decr 減去對應商品的庫存,如果庫存小於0,說明此時 庫存不足,則不需要訪問資料庫。直接拋出異常即可
記憶體標記:
由於介面優化很多基於Redis的緩存操作,當併發很高的時候,也會給Redis伺服器帶來很大的負擔,如果可以減少對Redis伺服器的訪問,也可以達到的優化的效果。
於是,可以加一個記憶體map,標記對應商品的庫存量是否還有,在訪問Redis之前,在map中拿到對應商品的庫存量標記,就可以不需要訪問Redis 就可以判斷沒有庫存了。
1.生成一個map,併在初始化的時候,將所有商品的id為鍵,標記false 存入map中。
private Map<Long, Boolean> isOverMap = new HashMap<Long, Boolean>();
/**
* 秒殺介面優化之--- 第一步: 系統初始化後就將所有商品庫存放入 緩存
*/
@Override
public void afterPropertiesSet() throws Exception {
List<GoodsVo> 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 就是還有
}
}
/**再優化: 優化 庫存之後的請求不訪問redis 通過判斷 對應 map 的值
* */
boolean isOver = isOverMap.get(goodsId);
if (isOver) {
return Result.error(CodeMsg.MIAO_SHA_NO_STOCK);
}
if (stock < 0) {
isOverMap.put(goodsId, true);//沒有庫存就設置 對應id 商品的map 為true
2.在預減庫存之前,從map中取標記,若標記為false,說明庫存,還有,
3.預減庫存,當遇到庫存不足的時候,將該商品的標記置為true,表示該商品的庫存不足。這樣,下麵的所有請求,將被攔截,無需訪問redis進行預減庫存。
原文鏈接:https://blog.csdn.net/weixin_38035852/article/details/81174986
版權聲明:本文為CSDN博主「Dandy1awcoder」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!
覺得不錯,別忘了隨手點贊+轉發哦!