網站首頁 編程語言 正文
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.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,說明此時 庫存不足,則不需要訪問數據庫。直接拋出異常即可。
我們上面還使用到了isOverMap,這個是內存標記。
內存標記
由于接口優化很多基于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進行預減庫存。
所以利用緩存的整體思路如下:
將商品的庫存數據加載至內存,同時初始化內存標記,即把每個產品的id存放至map,都是初始化為false,在每次需要執行秒殺邏輯之前,在在內存標記中取值,如果仍有庫存即map里返回的為false,則 執行秒殺邏輯,否則直接拋出異常。
同時扣減庫存時,需要判斷緩存中的庫存數量是否仍然大于0,如果小于等于0,修改內存標記。
原文鏈接:https://blog.csdn.net/zhiyikeji/article/details/125050768
相關推薦
- 2022-10-27 Python?Pandas中布爾索引的用法詳解_python
- 2022-04-27 為ABP框架配置數據庫_基礎應用
- 2022-12-23 Android用注解與反射實現Butterknife功能_Android
- 2022-08-21 Caffe卷積神經網絡視覺層Vision?Layers及參數詳解_python
- 2023-02-15 sql查詢一個數組中是否包含某個內容find_in_set問題_MsSql
- 2022-10-26 Python?Numpy教程之排序,搜索和計數詳解_python
- 2022-03-15 使用axios出現跨域問題Response to preflight request doesn‘t
- 2022-05-18 Python3的正則表達式詳解_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支