網(wǎng)站首頁(yè) 編程語言 正文
Redis扣庫(kù)存,主要目的是減少對(duì)數(shù)據(jù)庫(kù)的訪問,之前的減庫(kù)存,直接訪問數(shù)據(jù)庫(kù),讀取庫(kù)存,當(dāng)高并發(fā)請(qǐng)求到來的時(shí)候,大量的讀取數(shù)據(jù)有可能會(huì)導(dǎo)致數(shù)據(jù)庫(kù)的崩潰。
大家可以先讀一下《秒殺系統(tǒng)設(shè)計(jì)》對(duì)整體的秒殺流程有個(gè)了解之后,在來讀一下這篇文章。
本文只是解決秒殺系統(tǒng)中的一個(gè)場(chǎng)景即數(shù)據(jù)預(yù)加載,即把庫(kù)存數(shù)據(jù)事先加載到緩存,然后通過緩存來更新庫(kù)存。
使用思路:
- 系統(tǒng)初始化的時(shí)候,將商品庫(kù)存加載到Redis 緩存中保存。
- 收到請(qǐng)求的時(shí)候,先在Redis中拿到該商品的庫(kù)存值,進(jìn)行庫(kù)存預(yù)減,如果減完之后庫(kù)存不足,直接返回邏輯Exception就不需要訪問數(shù)據(jù)庫(kù)再去減庫(kù)存了,如果庫(kù)存值正確,進(jìn)行下一步。
- 將請(qǐng)求入隊(duì),立即給前端返回一個(gè)值,表示正在排隊(duì)中,然后進(jìn)行秒殺邏輯,后端隊(duì)列進(jìn)行秒殺邏輯,前端輪詢后端發(fā)來的請(qǐng)求,如果秒殺成功,返回秒殺,成功,不成功就返回失敗。
第一步:系統(tǒng)初始化后就將所有商品庫(kù)存放入緩存
/**
* 秒殺接口優(yōu)化之--- 第一步: 系統(tǒng)初始化后就將所有商品庫(kù)存放入 緩存
*/
@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);//先初始化 每個(gè)商品都是false 就是還有
}
}
第二步: 預(yù)減庫(kù)存從緩存中減庫(kù)存
/**秒殺接口優(yōu)化之 ----第二步: 預(yù)減庫(kù)存 從緩存中減庫(kù)存
* 利用 redis 中的方法,減去庫(kù)存,返回值為 減去1 之后的值
* */
long stock = redisService.decr(GoodsKey.getGoodsStock, "" + goodsId);
/*這里判斷不能小于等于,因?yàn)闇p去之后等于 說明還有是正常范圍*/
if (stock < 0) {
isOverMap.put(goodsId, true);//沒有庫(kù)存就設(shè)置 對(duì)應(yīng)id 商品的map 為true
return Result.error(CodeMsg.MIAO_SHA_NO_STOCK);
}
整體的邏輯如下:
1.先將所有數(shù)據(jù)讀出來,初始化到緩存中,并以 stock + goodid 的形成存入Redis。
2.在秒殺的時(shí)候,先進(jìn)行預(yù)減庫(kù)存檢測(cè),從redis中,利用decr 減去對(duì)應(yīng)商品的庫(kù)存,如果庫(kù)存小于0,說明此時(shí) 庫(kù)存不足,則不需要訪問數(shù)據(jù)庫(kù)。直接拋出異常即可。
我們上面還使用到了isOverMap,這個(gè)是內(nèi)存標(biāo)記。
內(nèi)存標(biāo)記
由于接口優(yōu)化很多基于Redis的緩存操作,當(dāng)并發(fā)很高的時(shí)候,也會(huì)給Redis服務(wù)器帶來很大的負(fù)擔(dān),如果可以減少對(duì)Redis服務(wù)器的訪問,也可以達(dá)到的優(yōu)化的效果。
于是,可以加一個(gè)內(nèi)存map,標(biāo)記對(duì)應(yīng)商品的庫(kù)存量是否還有,在訪問Redis之前,在map中拿到對(duì)應(yīng)商品的庫(kù)存量標(biāo)記,就可以不需要訪問Redis 就可以判斷沒有庫(kù)存了。
1.生成一個(gè)map,并在初始化的時(shí)候,將所有商品的id為鍵,標(biāo)記false 存入map中。
private Map<Long, Boolean> isOverMap = new HashMap<Long, Boolean>();
/**
* 秒殺接口優(yōu)化之--- 第一步: 系統(tǒng)初始化后就將所有商品庫(kù)存放入 緩存
*/
@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);//先初始化 每個(gè)商品都是false 就是還有
}
}
/**再優(yōu)化: 優(yōu)化 庫(kù)存之后的請(qǐng)求不訪問redis 通過判斷 對(duì)應(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);//沒有庫(kù)存就設(shè)置 對(duì)應(yīng)id 商品的map 為true
}
2.在預(yù)減庫(kù)存之前,從map中取標(biāo)記,若標(biāo)記為false,說明庫(kù)存
3.預(yù)減庫(kù)存,當(dāng)遇到庫(kù)存不足的時(shí)候,將該商品的標(biāo)記置為true,表示該商品的庫(kù)存不足。這樣,下面的所有請(qǐng)求,將被攔截,無需訪問redis進(jìn)行預(yù)減庫(kù)存。
所以利用緩存的整體思路如下:
將商品的庫(kù)存數(shù)據(jù)加載至內(nèi)存,同時(shí)初始化內(nèi)存標(biāo)記,即把每個(gè)產(chǎn)品的id存放至map,都是初始化為false,在每次需要執(zhí)行秒殺邏輯之前,在在內(nèi)存標(biāo)記中取值,如果仍有庫(kù)存即map里返回的為false,則 執(zhí)行秒殺邏輯,否則直接拋出異常。
同時(shí)扣減庫(kù)存時(shí),需要判斷緩存中的庫(kù)存數(shù)量是否仍然大于0,如果小于等于0,修改內(nèi)存標(biāo)記。
原文鏈接:https://blog.csdn.net/zhiyikeji/article/details/125050768
相關(guān)推薦
- 2022-07-11 Cadence中denalirc的用法總結(jié)
- 2022-11-19 React實(shí)現(xiàn)多個(gè)場(chǎng)景下鼠標(biāo)跟隨提示框詳解_React
- 2022-09-04 Golang?實(shí)現(xiàn)?RTP音視頻傳輸示例詳解_Golang
- 2022-11-30 Linux實(shí)現(xiàn)徹底清理空文件夾的方法詳解_linux shell
- 2022-05-18 opencv?canny邊緣檢測(cè)算法詳解_python
- 2023-12-18 Jedis和springboot集成redis
- 2023-05-12 Go異步任務(wù)解決方案之Asynq庫(kù)詳解_Golang
- 2022-07-12 CSS樣式:樣式的沖突 樣式的繼承 偽元素 偽類
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支