場景分析
這里以搶紅包場景為例,需求如下:
1.紅包有個數限制,假設紅包的個數限制為X。 2.紅包金額上線限制,假設金額上線為Y。 3.要求用戶搶紅包的時候,不超過紅包的個數限制X。 4.要求用戶搶紅包的時候,不超過紅包的金額Y。 5.每個用戶一次紅包活動只能搶一個。
常規(guī)思路
這里提一下最常見的思路:
1.在用戶搶紅包時,檢查當前發(fā)出去紅包數量和金額,并加鎖。 2.檢查紅包數量和金額正常的后,隨機用戶紅包金額。 3.然后修改紅包發(fā)出去的數量和金額,并給用戶贈送紅包,然后解鎖。
常規(guī)思路的優(yōu)缺點
首先是優(yōu)點
1.思路簡單 2.編不下去了。。。
然后是缺點
1.鎖數據回造成大量進程等待,造成浪費資源。 2.鎖造成的等待,用戶體驗奇差。 3.對于鎖機制不太了解的同學會產生一定的危險性。
優(yōu)化思路
先分析,為什么常規(guī)思路會慢?
1.在搶紅包的時候,每次都需要檢查紅包的上限 X 和 Y。 2.鎖會造成大量進程卡頓。 3.生成紅包的金額時還需要檢查與上限 X 跟 Y 是否有沖突。
優(yōu)化解決方案
紅包生成前置
例如紅包個數上限為X,金額上限為Y。
那么,我在活動進行前就把這 X 個紅包插入到數據庫
并生成序號:HB1、HB2、HB3。。。。HBX
那么實際上,到時候用戶就只需要按照先后順序去領取這個有序的紅包隊列了。
這個操作減少了到時候線上所產生的很多的計算量。最重要的是,能夠簡單且有效的保證了整個活動的可控性。
利用ID自增保證排隊順序
這里利用到了一個ID生成表,通過建立 user_id 的唯一索引,保證每個人只能拿到一個序號。
搶紅包步驟如下
1.活動創(chuàng)建之前,創(chuàng)建一張ID生成表,ID從 1 開始自增,且 user_id 唯一。 2.活動開始,用戶開始搶紅包操作。 3.搶紅包之前,先插入ID表,獲取插入ID,如果ID > X,通知用戶已被搶完。 4.如果 ID <= X,那么恭喜了,去紅包表領取序號為 ID 的紅包,并走異步發(fā)紅包過程。 5.活動結束之后,把相關用戶領取信息存儲在紅包表,刪除ID生成表。
方案優(yōu)點
1.不需要代碼實現鎖機制。 2.邏輯簡單。 3.mysql保證每個用戶只能拿到一個,且有序。
更多思考
有些朋友提到,可以用 redis 隊列存儲紅包信息,但是實際上 redis 比較占用內存,需要長期存儲數據最好還是放在mysql。實際上,這里可以使用 redis 的 incr 命令,得到類似在上面提到的 ID 生成表的功能,更加快速且嚴格遞增,能夠使整個項目的并發(fā)性更高。
【相關推薦】
? 版權聲明
文章版權歸作者所有,未經允許請勿轉載。
THE END