資料內(nèi)容:
Redis分布式鎖存在的問題
在購票軟件的情境中,當(dāng)僅剩一張或幾張票時(shí),眾多用戶同時(shí)嘗試購買。在不考慮任何外部干擾的情況下,
邏輯上,系統(tǒng)應(yīng)首先檢查是否還有余票。如果仍有余票,用戶可以順利購買并導(dǎo)致庫存相應(yīng)減少;如果沒有
余票,系統(tǒng)會(huì)提示用戶票數(shù)不足,購買失敗。偽代碼如下:
void buyTicket() {
int stockNum = byTicketMapper.selectStockNum();
if(stockNum>0){
//TODO 買票流程....
byTicketMapper.reduceStock(); // 扣減庫存
}else{
log.info("=====>票賣完了<====");
}
}
這段代碼在邏輯上沒有問題,但是在并發(fā)場(chǎng)景下,可能會(huì)存在一個(gè)嚴(yán)重的問題。當(dāng)剩余票數(shù)為1時(shí),有A,B兩
個(gè)用戶同時(shí)點(diǎn)擊了購買按鈕,A用戶通過了庫存大于0的校驗(yàn)并開始執(zhí)行購票邏輯,但是由于一些原因造成A
用戶的購票線程有短暫的阻塞。而在這個(gè)阻塞的過程中,用戶B發(fā)起了購買請(qǐng)求,并且也通過了庫存大于0的
校驗(yàn),直到整個(gè)購買流程執(zhí)行完成并且扣減了庫存。那么這個(gè)時(shí)候剩余庫存剛好為0,不會(huì)再有用戶發(fā)起購
買請(qǐng)求,這時(shí)用戶A的購買請(qǐng)求阻塞被喚醒,因?yàn)樵诖酥耙呀?jīng)校驗(yàn)過庫存大于0,所以執(zhí)行完購買流程后,
庫存還會(huì)被扣減一次。那么此時(shí)的庫存為-1,這就是常聽到的超賣問題。