設計一個電商秒殺系統(tǒng)氮发,至少包含導購榜旦、交易和庫存系統(tǒng)的全鏈路簡易的整體方案,特別對于庫存處理細節(jié)上竟闪,希望給出比較完整的關(guān)鍵細節(jié)處理离福,需要有代碼配合的可以用偽代碼示例。方案上可以講大的設計炼蛤,也可以有小的解決方案妖爷,例如導購頁面如何為下游交易和庫存系統(tǒng)減壓,交易和庫存系統(tǒng)如何處理高并發(fā)問題理朋,也可以有部分細節(jié)處理絮识,如減庫存如何保證正確等等。
方案一
針對并發(fā)量比較大的情況嗽上,比如100萬用戶搶一個iphone次舌,要扛 100 萬的 TPS,需要非常多的機器兽愤,不太現(xiàn)實彼念。必須采用前端限流的辦法。
1. 靜態(tài)資源存放于CDN緩存
2.ngnix+lua限流浅萧,可根據(jù)在線人數(shù)計算概率逐沙,比如100萬請求只放過1萬人進入搶購系統(tǒng),其他請求返回搶購失敗洼畅。
3.利用CDN邊緣計算能力(此方法相當于要跟運營商定制服務)
方案二
1.把秒殺系統(tǒng)獨立出來吩案,部署單獨的秒殺服務器,以避免影響正常的交易系統(tǒng)帝簇。
2.秒殺活動持續(xù)時間短徘郭,瞬時數(shù)據(jù)量大。為了不影響現(xiàn)有數(shù)據(jù)庫的正常業(yè)務丧肴,可以建立新的庫或者表來處理
3.這種方式比較麻煩残揉,秒殺活動結(jié)束后,需要把數(shù)據(jù)同步回主業(yè)務庫
方案三
采用異步處理的方式闪湾,總體流程分為三步:接收請求冲甘、異步篩選绩卤、前端展示
1.因為是異步篩選的方式途样,可以采用隊列對洪峰請求進行過濾、排隊濒憋、篩選何暇,避免后端系統(tǒng)瞬時并發(fā)壓力
2.缺點是用戶體驗不好,搶購后需等待一段時間才能查詢到搶購結(jié)果
并發(fā)扣減庫存方案
一凛驮、采用數(shù)據(jù)庫行鎖
1.采用數(shù)據(jù)庫的行鎖機制裆站,庫存扣到?jīng)]有為至,應用根據(jù)更新行數(shù)判斷是否扣庫存成功
UPDATE inventory SET qty= qty- xxx where id=? and qty-xxx>0;
這種方式不能先把庫存查出來,再去計算宏胯,否則會有并發(fā)問題羽嫡;
2.另一種辦法是直接設置數(shù)據(jù)庫的字段數(shù)據(jù)為無符號整數(shù),當庫存數(shù)小于零時會執(zhí)行 SQL 語句失敗肩袍,通過攔截異常判斷
UPDATE inventory SET qty= qty- xxx where id=??
二杭棵、采用數(shù)據(jù)庫悲觀鎖
1.使用select .. for update語句查詢最新庫存
2.檢查庫存是否足夠
3.更新庫存提交事務
三、庫存放入redis緩存
1.庫存放到redis緩存中氛赐,在redis中進行庫存的查詢魂爪、扣減
2.扣減時需要加并發(fā)鎖,獲取鎖成功后才能扣減庫存
3.缺點是如果有比較復雜的減庫存邏輯艰管,或者需要使用事務滓侍,就需要數(shù)據(jù)庫中完成減庫存。
加鎖方式:使用set nx命令 key為要扣減的商品編號牲芋,value為當前時間+鎖超時時間(比如3秒)執(zhí)行業(yè)務扣減庫存后撩笆,需要釋放鎖。
釋放鎖邏輯(delete key): 判斷一下value - 當前時間是否已超過配置的鎖超時時間(比如3秒)街图,如果超過則不刪除浇衬。
為什么要執(zhí)行以上判斷? ?由于key是有超時時間的餐济,當delete還沒有到達redis的時候(已經(jīng)發(fā)出了)耘擂,key已經(jīng)由于超時delete掉。如果
這個時候有其他線程來獲取鎖絮姆,就會導致這個鎖會被delete掉