一米死、為什么難秒殺系統(tǒng)難做?
原因:庫(kù)存只有一份衷佃,所有人會(huì)在集中的時(shí)間讀和寫(xiě)這些數(shù)據(jù)趟卸。例如小米手機(jī)每周二的秒殺,可能手機(jī)只有1萬(wàn)部氏义,但瞬時(shí)進(jìn)入的流量可能是幾百幾千萬(wàn)锄列。又例如12306搶票,亦與秒殺類似惯悠,瞬時(shí)流量更甚邻邮。
二、常見(jiàn)架構(gòu)
![4layer](http://www.habadog.com/wp-content/uploads/2015/04/4layer.png)
流量到了億級(jí)別克婶,常見(jiàn)站點(diǎn)架構(gòu)如上:
2.1 瀏覽器端筒严,最上層,會(huì)執(zhí)行到一些JS代碼
2.2 站點(diǎn)層情萤,這一層會(huì)訪問(wèn)后端數(shù)據(jù)鸭蛙,拼html頁(yè)面返回給瀏覽器
2.3 服務(wù)層,向上游屏蔽底層數(shù)據(jù)細(xì)節(jié)
2.4 數(shù)據(jù)層筋岛,最終的庫(kù)存是存在這里的娶视,mysql是一個(gè)典型
三、優(yōu)化方向
3.1 將請(qǐng)求盡量攔截在系統(tǒng)上游:傳統(tǒng)秒殺系統(tǒng)之所以掛睁宰,請(qǐng)求都?jí)旱沽撕蠖藬?shù)據(jù)層肪获,數(shù)據(jù)讀寫(xiě)鎖沖突嚴(yán)重,并發(fā)高響應(yīng)慢勋陪,幾乎所有請(qǐng)求都超時(shí)贪磺,流量雖大,下單成功的有效流量甚小【一趟火車(chē)其實(shí)只有2000張票诅愚,200w個(gè)人來(lái)買(mǎi)寒锚,基本沒(méi)有人能買(mǎi)成功,請(qǐng)求有效率為0】
3.2 充分利用緩存:這是一個(gè)典型的讀多寫(xiě)少的應(yīng)用場(chǎng)景【一趟火車(chē)其實(shí)只有2000張票违孝,200w個(gè)人來(lái)買(mǎi)刹前,最多2000個(gè)人下單成功,其他人都是查詢庫(kù)存雌桑,寫(xiě)比例只有0.1%喇喉,讀比例占99.9%】,非常適合使用緩存
四校坑、優(yōu)化細(xì)節(jié)
4.1 瀏覽器層請(qǐng)求攔截點(diǎn)擊了“查詢”按鈕之后拣技,系統(tǒng)那個(gè)卡呀千诬,進(jìn)度條漲的慢呀,作為用戶膏斤,我會(huì)不自覺(jué)的再去點(diǎn)擊“查詢”徐绑,繼續(xù)點(diǎn),繼續(xù)點(diǎn)莫辨,點(diǎn)點(diǎn)點(diǎn)傲茄。。沮榜。有用么盘榨?平白無(wú)故的增加了系統(tǒng)負(fù)載(一個(gè)用戶點(diǎn)5次,80%的請(qǐng)求是這么多出來(lái)的)蟆融,怎么整草巡?
4.1.1 產(chǎn)品層面,用戶點(diǎn)擊“查詢”或者“購(gòu)票”后振愿,按鈕置灰捷犹,禁止用戶重復(fù)提交請(qǐng)求
4.1.2 JS層面,限制用戶在x秒之內(nèi)只能提交一次請(qǐng)求如此限流冕末,80%流量已攔萍歉。
4.2 站點(diǎn)層請(qǐng)求攔截與頁(yè)面緩存瀏覽器層的請(qǐng)求攔截,只能攔住小白用戶(不過(guò)這是99%的用戶喲)档桃,高端的程序員根本不吃這一套枪孩,寫(xiě)個(gè)for循環(huán),直接調(diào)用你后端的http請(qǐng)求藻肄,怎么整陋葡?
4.2.1 同一個(gè)uid或舞,限制訪問(wèn)頻度追驴,做頁(yè)面緩存低葫,x秒內(nèi)到達(dá)站點(diǎn)層的請(qǐng)求,均返回同一頁(yè)面
4.2.2 同一個(gè)item的查詢州弟,例如手機(jī)車(chē)次钧栖,做頁(yè)面緩存,x秒內(nèi)到達(dá)站點(diǎn)層的請(qǐng)求婆翔,均返回同一頁(yè)面如此限流拯杠,又有99%的流量會(huì)被攔截在站點(diǎn)層
4.3 服務(wù)層請(qǐng)求攔截與數(shù)據(jù)緩存站點(diǎn)層的請(qǐng)求攔截,只能攔住普通程序員啃奴,高級(jí)黑客潭陪,假設(shè)他控制了10w臺(tái)肉雞(并且假設(shè)買(mǎi)票不需要實(shí)名認(rèn)證),這下uid的限制不行了吧?怎么整依溯?
4.3.1 大哥老厌,我是服務(wù)層,我清楚的知道小米只有1萬(wàn)部手機(jī)黎炉,我清楚的知道一列火車(chē)只有2000張車(chē)票梅桩,我透10w個(gè)請(qǐng)求去數(shù)據(jù)庫(kù)有什么意義呢?對(duì)于寫(xiě)請(qǐng)求拜隧,做請(qǐng)求隊(duì)列,每次只透有限的寫(xiě)請(qǐng)求去數(shù)據(jù)層趁仙,如果均成功再放下一批洪添,如果庫(kù)存不夠則隊(duì)列里的寫(xiě)請(qǐng)求全部返回“已售完”
4.3.2 對(duì)于讀請(qǐng)求,還要我說(shuō)么雀费?cache抗干奢,不管是memcached還是redis,單機(jī)抗個(gè)每秒10w應(yīng)該都是沒(méi)什么問(wèn)題的如此限流盏袄,只有非常少的寫(xiě)請(qǐng)求忿峻,和非常少的讀緩存mis的請(qǐng)求會(huì)透到數(shù)據(jù)層去,又有99.9%的請(qǐng)求被攔住了
4.4 數(shù)據(jù)層閑庭信步到了數(shù)據(jù)這一層辕羽,幾乎就沒(méi)有什么請(qǐng)求了逛尚,單機(jī)也能扛得住,還是那句話刁愿,庫(kù)存是有限的绰寞,小米的產(chǎn)能有限,透這么多請(qǐng)求來(lái)數(shù)據(jù)庫(kù)沒(méi)有意義铣口。
五滤钱、總結(jié)
沒(méi)什么總結(jié)了,上文應(yīng)該描述的非常清楚了脑题,對(duì)于秒殺系統(tǒng)件缸,再次重復(fù)下筆者的兩個(gè)架構(gòu)優(yōu)化思路:1)盡量將請(qǐng)求攔截在系統(tǒng)上游2)讀多寫(xiě)少的常用多使用緩存