高并發(fā)下的抽獎(jiǎng)優(yōu)化

來源:rrd.me/fS8yz

一. 項(xiàng)目思考

由于項(xiàng)目發(fā)起了一個(gè)抽獎(jiǎng)活動(dòng)瓤球,發(fā)起活動(dòng)之前給所有用戶發(fā)短信提示他們購(gòu)買了我們的產(chǎn)品有抽獎(jiǎng)權(quán)益。然后用戶上來進(jìn)入抽獎(jiǎng)頁面點(diǎn)擊爆增耳胎,過了一會(huì)兒頁面就打不開了悼粮。后面查看了下各種日志掀淘,發(fā)現(xiàn)了瓶頸在數(shù)據(jù)庫竖席,由于讀寫沖突嚴(yán)重耘纱,導(dǎo)致響應(yīng)變慢,有不少連接都超時(shí)了毕荐。后面看到監(jiān)控和日志留下的數(shù)據(jù)揣炕,發(fā)現(xiàn)負(fù)責(zé)抽獎(jiǎng)的微服務(wù)集群qps暴漲12倍,db的qps也漲了10倍东跪。這很明顯是一個(gè)高并發(fā)下如何擺脫數(shù)據(jù)庫讀寫,I/O瓶頸的問題。

整點(diǎn)開搶后瞬時(shí)巨量的請(qǐng)求同時(shí)涌入虽填,即使我們Nginx端做過初步限流丁恭,整個(gè)業(yè)務(wù)邏輯校驗(yàn)階段運(yùn)作良好,但是系統(tǒng)的瓶頸就轉(zhuǎn)移到其他環(huán)節(jié):大量的讀寫請(qǐng)求斋日,導(dǎo)致后面的請(qǐng)求全部排隊(duì)等待牲览,等前面一個(gè)update完成釋放行鎖后才能處理下一個(gè)請(qǐng)求,大量請(qǐng)求等待恶守,占用了數(shù)據(jù)庫的連接第献。一旦數(shù)據(jù)庫同一時(shí)間片內(nèi)的連接數(shù)被打滿,就會(huì)導(dǎo)致這個(gè)時(shí)間片內(nèi)其他后來的全部請(qǐng)求因拿不到連接而超時(shí)兔港,導(dǎo)致訪問此數(shù)據(jù)庫的其他環(huán)節(jié)也出現(xiàn)問題庸毫,所以RT就會(huì)異常飆高

于是我們?cè)谒伎贾趺磧?yōu)化這個(gè)高并發(fā)下的抽獎(jiǎng)問題

二. 優(yōu)化思路

聽了經(jīng)驗(yàn)豐富的師兄的經(jīng)驗(yàn),也借鑒了下網(wǎng)上的一些思路衫樊,能采用的有效措施主要是:降級(jí)飒赃,限流,緩存科侈,消息隊(duì)列载佳。主要原則是:盡量不暴露db,把大部分請(qǐng)求在服務(wù)的系統(tǒng)上層處理了。

三. 優(yōu)化細(xì)節(jié)

\1. 抽獎(jiǎng)詳情頁

a. 線上開啟緩存

線上已寫緩存邏輯臀栈,但是沒有用switch開啟蔫慧。開啟后可以減少數(shù)據(jù)庫的并發(fā)IO壓力,減少鎖沖突权薯。

b. 關(guān)于本地緩存淘汰策略的細(xì)節(jié)處理

緩存超過或等于限制大小全部清空姑躲。建議等于時(shí)不清空,而使用緩存淘汰算法:比如LRU,LFU,NRU等,這樣不會(huì)出現(xiàn)緩存過大清空后崭闲,從數(shù)據(jù)庫更新數(shù)據(jù)到緩存肋联,緩存里數(shù)據(jù)依舊很大。導(dǎo)致緩存清空頻率過高刁俭,反而降低系統(tǒng)的吞吐量橄仍。例如guava cache中的參數(shù)是

//設(shè)置緩存容器的初始容量為10

initialCapacity(10)

//設(shè)置緩存最大容量為100,超過100之后就會(huì)按照LRU最近雖少使用算法來移除緩存項(xiàng)

maximumSize(100)

\2. 抽獎(jiǎng)邏輯

a.隊(duì)列削峰

用額外的單進(jìn)程處理一個(gè)隊(duì)列牍戚,下單請(qǐng)求放到隊(duì)列里侮繁,一個(gè)個(gè)處理,就不會(huì)有qps的高并發(fā)問題了如孝。場(chǎng)景中抽獎(jiǎng)用戶會(huì)在到點(diǎn)的時(shí)間涌入宪哩,DB瞬間就接受暴擊壓力,hold不住就會(huì)宕機(jī)第晰,然后影響整個(gè)業(yè)務(wù)锁孟。隊(duì)列的長(zhǎng)度保持固定彬祖,對(duì)于如果請(qǐng)求排隊(duì)在隊(duì)伍中靠后,比如獎(jiǎng)品100個(gè)的情況下品抽,中獎(jiǎng)率10%储笑,隊(duì)列里請(qǐng)求任務(wù)超過1000時(shí),就直接將后續(xù)的抽獎(jiǎng)?wù)埱蠓祷夭恢歇?jiǎng)圆恤。用tair記錄排隊(duì)數(shù)突倍,如果獎(jiǎng)品沒發(fā)完,再請(qǐng)空tair,允許請(qǐng)求繼續(xù)入隊(duì)列盆昙。這樣隊(duì)列起到了降級(jí)和削峰的作用羽历。

b.將事務(wù)和行級(jí)悲觀鎖改成樂觀鎖

原來的代碼是通過悲觀鎖來控制超發(fā)的情況。(比如一共有100個(gè)商品淡喜,在最后一刻秕磷,我們已經(jīng)消耗了99個(gè)商品,僅剩最后一個(gè)拆火。這個(gè)時(shí)候跳夭,系統(tǒng)發(fā)來多個(gè)并發(fā)請(qǐng)求,這批請(qǐng)求讀取到的商品余量都是99個(gè)们镜,然后都通過了這一個(gè)余量判斷币叹,最終導(dǎo)致超發(fā)。)

在原來的代碼中用的是for update行鎖模狭,在高并發(fā)的情況下會(huì)很多這樣的修改請(qǐng)求颈抚,每個(gè)請(qǐng)求都需要等待鎖,某些線程可能永遠(yuǎn)都沒有機(jī)會(huì)搶到這個(gè)鎖嚼鹉,這種請(qǐng)求就會(huì)死在那里贩汉。同時(shí),這種請(qǐng)求會(huì)很多锚赤,瞬間增大系統(tǒng)的平均響應(yīng)時(shí)間匹舞,結(jié)果是可用連接數(shù)被耗盡,系統(tǒng)陷入異常线脚。

可以采用樂觀鎖赐稽,是相對(duì)于“悲觀鎖”采用更為寬松的加鎖機(jī)制,大都是采用帶版本號(hào)(Version)更新浑侥。實(shí)現(xiàn)就是姊舵,這個(gè)數(shù)據(jù)所有請(qǐng)求都有資格去修改,但會(huì)獲得一個(gè)該數(shù)據(jù)的版本號(hào)寓落,只有版本號(hào)符合的才能更新成功括丁,其他的返回?fù)屬?gòu)失敗。

c.對(duì)于與抽獎(jiǎng)無直接關(guān)系的流程采用異步

比如抽獎(jiǎng)成功之后的發(fā)短信功能另起一個(gè)線程池專門處理伶选。這樣可以提高請(qǐng)求的處理速率史飞,提高qps上升后的乘載能力尖昏。

d.數(shù)據(jù)庫的讀寫分離

現(xiàn)在的數(shù)據(jù)庫查詢都是讀的主庫。將數(shù)據(jù)庫的大量查詢改為從庫祸憋,減輕主庫的讀寫壓力会宪。主服務(wù)器進(jìn)行寫操作時(shí),不影響查詢應(yīng)用服務(wù)器的查詢性能蚯窥,降低阻塞,提高并發(fā)塞帐。

e.同一時(shí)間片內(nèi)拦赠,采用信號(hào)量機(jī)制

確保進(jìn)來的人數(shù)不會(huì)過多導(dǎo)致系統(tǒng)響應(yīng)超時(shí):信號(hào)量的采用,能夠使得抽獎(jiǎng)高峰期內(nèi)葵姥,同一時(shí)間片內(nèi)不會(huì)進(jìn)入過多的用戶荷鼠,從底層實(shí)現(xiàn)上規(guī)避了系統(tǒng)處理大數(shù)據(jù)量的風(fēng)險(xiǎn)。這個(gè)可以配合隊(duì)列進(jìn)行限流處理榔幸。

f. 消息存儲(chǔ)機(jī)制

將數(shù)據(jù)請(qǐng)求先添加到信息隊(duì)列中(比如Tair存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu)中)允乐,然后再寫工具啟動(dòng)定時(shí)任務(wù)從Tair中取出數(shù)據(jù)去入庫,這樣對(duì)于db的并發(fā)度大大降低到了定時(shí)任務(wù)的頻率削咆。但是問題可能會(huì)出在保持?jǐn)?shù)據(jù)的一致性和完整性上牍疏。

g.必要時(shí)候采用限流降級(jí)的測(cè)流

當(dāng)并發(fā)過多時(shí)為了保證系統(tǒng)整體可用性,拋棄一些請(qǐng)求拨齐。對(duì)于被限流的請(qǐng)求視為抽不到獎(jiǎng)鳞陨。

3.額外考慮

a.防止黑客刷獎(jiǎng)

防止黑客惡意攻擊(比如cc攻擊)導(dǎo)致qps過高,可以考慮策略在服務(wù)入口為相同uid的賬戶請(qǐng)求限制每秒鐘的最高訪問數(shù)瞻惋。

b. 中獎(jiǎng)數(shù)據(jù)預(yù)熱

中獎(jiǎng)只是少數(shù)厦滤,大部分人并不會(huì)中獎(jiǎng),所以可以在第一步便限制只有少數(shù)用戶的請(qǐng)求能夠打到真正抽獎(jiǎng)邏輯上歼狼。是否可以考慮在抽獎(jiǎng)之前先用隨機(jī)算法生成一批中獎(jiǎng)候選人掏导。然后當(dāng)用戶請(qǐng)求過來時(shí)如果其中絕大多數(shù)請(qǐng)求都非中獎(jiǎng)候選人,則直接返回抽獎(jiǎng)失敗羽峰,不走抽獎(jiǎng)拿獎(jiǎng)品的流程趟咆。少部分用戶請(qǐng)求是中獎(jiǎng)候選人,則進(jìn)入隊(duì)列限寞,排在隊(duì)列前面的獲得獎(jiǎng)品忍啸,發(fā)完為止,先到先得履植。

舉個(gè)例子:10萬個(gè)用戶抽獎(jiǎng)计雌,獎(jiǎng)品100個(gè),先隨機(jī)選出中獎(jiǎng)候選人500個(gè)玫霎。用戶請(qǐng)求過來時(shí)凿滤,不走抽獎(jiǎng)查庫邏輯的用戶過濾掉99500個(gè)妈橄,剩余的候選人的請(qǐng)求用隊(duì)列處理,先到先得。這樣可以把絕大多數(shù)的請(qǐng)求攔截在服務(wù)上游不用查庫翁脆,但是缺點(diǎn)是不能保證獎(jiǎng)品一定會(huì)被抽完(可能抽獎(jiǎng)候選人只有不到100人參與抽獎(jiǎng))眷蚓。

四.設(shè)計(jì)架構(gòu)圖

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市反番,隨后出現(xiàn)的幾起案子沙热,更是在濱河造成了極大的恐慌,老刑警劉巖罢缸,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件篙贸,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡枫疆,警方通過查閱死者的電腦和手機(jī)爵川,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來息楔,“玉大人寝贡,你說我怎么就攤上這事≈狄溃” “怎么了圃泡?”我有些...
    開封第一講書人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)鳞滨。 經(jīng)常有香客問我洞焙,道長(zhǎng),這世上最難降的妖魔是什么拯啦? 我笑而不...
    開封第一講書人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任澡匪,我火速辦了婚禮,結(jié)果婚禮上褒链,老公的妹妹穿的比我還像新娘唁情。我一直安慰自己,他們只是感情好甫匹,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開白布甸鸟。 她就那樣靜靜地躺著,像睡著了一般兵迅。 火紅的嫁衣襯著肌膚如雪抢韭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,196評(píng)論 1 308
  • 那天恍箭,我揣著相機(jī)與錄音刻恭,去河邊找鬼。 笑死扯夭,一個(gè)胖子當(dāng)著我的面吹牛鳍贾,可吹牛的內(nèi)容都是我干的鞍匾。 我是一名探鬼主播,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼骑科,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼橡淑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起咆爽,我...
    開封第一講書人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤梁棠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后伍掀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掰茶,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年蜜笤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盐碱。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡把兔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瓮顽,到底是詐尸還是另有隱情县好,我是刑警寧澤,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布暖混,位于F島的核電站缕贡,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏拣播。R本人自食惡果不足惜晾咪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望贮配。 院中可真熱鬧谍倦,春花似錦、人聲如沸泪勒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽圆存。三九已至叼旋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沦辙,已是汗流浹背夫植。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留怕轿,地道東北人偷崩。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓辟拷,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親阐斜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子衫冻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容