關于抽獎,需要考慮的點有很多,這里稍微整理了下主要需要考慮以下三點:
用戶抽獎次數限制
獎品數量限制
獎品發放的分布
中獎的概率的可控性
用戶抽象次數限制
一個用戶必須限制抽獎的次數,而同一個用戶的并發幾率其實是很小的,所以這里可以用悲觀鎖來控制用戶的抽獎次數。
獎品數量限制
因為并發修改一個獎品的數量可能性是很大的,特別是一些安慰獎,如果這里我們再用悲觀鎖的話,很容易造成鎖超時。所以這里我選擇用樂觀鎖來解決可能出現的并發臟讀的情況。
獎品發放的分布
為了防止用腳本來刷抽獎,所以這里需要控制一下獎品發放的一個分布,中大獎需要一個時間間隔,當然這里通過代碼來控制是很容易實現的(當然這里也需要考慮一下并發中到兩個大獎的情況,也可以通過樂觀鎖來控制)
中獎的概率的可控性
當我們開始估計抽獎大概會有10W人參加,所以我在設計概率的時候是按照10w來設計的,但是突然發現活動開始一個小時候以后抽獎人數就達到了5W,這個時候就需要可以動態來調整中獎的概率了。這里最好的方式是,不要把中獎概論寫死在數據庫,而是通過中獎次數/參加人數來計算出來,這樣就可以方便的動態的改變中獎概率了。
關于優化
如果并發量實在是太大,導致數據庫的QPS異常的高。那么可以在數據庫前面加一層緩存來擋一下,把需要寫進數據庫的數據放入隊列。當使用了這種架構架構,就需要考慮一些數據一致性的問題了,比如說
怎么保證數據庫的數據和緩存的數據是一致的
如果隊列掛掉了,怎么保證緩存的數據能夠及時更新到數據庫中。如果緩存掛掉了,怎么保證抽獎能夠繼續進行下去(當然這里可以進行業務妥協,如果緩存掛掉整個抽獎掛掉,如果來不及寫進數據庫的數據,就當做這些事情沒有發生,這就會導致某些人抽獎次數超過限定次數,或者某些獎中獎次數超過了限定次數)
關于優化中我對一些異常情況的解決方法不是很了解,希望懂的朋友可以指教一下
附錄(簡單流程圖)