對紅包系統的一些我的想法,有問題歡迎補充交流redis
正常流程:
發紅包-> 搶紅包 -> 拆紅包sql
發紅包:邏輯簡單,建立一個紅包,無高併發的情形。
搶紅包:邏輯複雜,高併發更新情形。複雜點:高併發狀況下,剩餘紅包數量如何原子性的維護? 高併發狀況下,紅包數據如何落盤?接口性能如何保證?
拆紅包:查詢搶到紅包的金額,高併發查詢,並不複雜。數據庫
搶紅包特色:緩存
1 併發請求高。(紅包場景的特色-->併發搶)
2 系統安全性要求高。(不能出現錢金額超發,紅包數量超發的狀況)
併發請求高:安全
主要流程能夠以下所示:
併發
設計想法:
高併發請求,該接口設計必定要輕量。搶紅包階段,只須要明確是否搶到紅包,紅包金額等在該接口不涉及。用戶搶到紅包最重要的前提有三個。異步
a. 根據緩存判斷是否存在庫存 b. 緩存中庫存數量自減成功 c. 發送異步mq消息成功
正常邏輯只會請求redis以及發送一個mq,十分輕量。高併發
接口的穩定性強依賴mq的穩定性; 緣由是redis掛掉的狀況下,其實能夠走正常sql落盤數據庫的方式,只更新庫存數量便可(這裏又併發強鎖的問題,比較耗時)。 性能
計算紅包大小,以及插入搶紅包記錄,更新紅包記錄放在異步操做,緣由是這樣的操做比較重,若是放在同步裏面,在高併發狀況下,增長了服務異常的機率。放在mq的好處,最重要的是能夠以固定速率消費,避免了高併發的場景。若是出現隊列中消息過多的狀況。 只有兩個緣由:1. 消費機器數目過少。 2. 存儲數據庫更新操做出現瓶頸。 對於第一個,暴力簡單,增長消費機器的數量。 第二個來講比較麻煩,底層數據分庫分表,增長更新查詢速率。spa
問題:發送mq失敗怎麼辦?
問題:返回成功後,服務宕機怎麼辦?
已經發送mq成功,這裏須要mq來保證,在宕機狀況下,消息也不會丟失。 另外就算mq不能恢復,也能夠根據發送mq成功的日誌進行後續的補償邏輯,也不會形成多發的狀況。
問題:存在這樣的場景,讀取到紅包剩餘N個,而後這裏按照搶到紅包的操做,將紅包數量更新到N-1個,在讀取和更新期間,其餘請求對庫存發生了更新操做怎麼辦?即將紅包數量更新到N-1的時候,庫存已是N-1了,這裏會出現少減的狀況。
redis的watch命令。經過redis的watch命令,能夠知道更新這個數字的時候,這個數字有沒有被改過。
這樣設計有個缺點就是紅包數量比較多,另外同時多人搶紅包狀況下,會出現屢次以下的循環 (如何避免這種狀況?) 思考了一下,其實屢次這樣循環對性能影響不大,並且理論上不會出現屢次循環,最多可能兩三次。
經過sql語句, 更新庫存將庫存做爲條件放入where後
update table set N=N-1 where N=N
依舊避免不了出現屢次 獲取紅包數量 <-> 更新失敗 的循環。
若有其餘內容,歡迎補充~