前段時(shí)間把所有重要API的日志做了分庫(kù)分表改善成箫,本打算按照這個(gè)思路寫(xiě)工作記錄,可是想了想太局限沒(méi)延伸的擴(kuò)展點(diǎn)就選擇放棄,然后再發(fā)散思維一點(diǎn)為什么我要分庫(kù)分表妖泄,主要因?yàn)楝F(xiàn)在的API訪問(wèn)量已經(jīng)比起剛開(kāi)始構(gòu)建系統(tǒng)的時(shí)候大得多,所以改造是有必然的艘策,既然是這樣就想寫(xiě)一個(gè)有系統(tǒng)性的改善提綱蹈胡。
植入一個(gè)簡(jiǎn)單的程序背景
假設(shè)系統(tǒng)部署在一臺(tái)AP服務(wù)器(8核16G),DB放在另一臺(tái)服務(wù)器(16核32G)
有10萬(wàn)用戶(hù),活躍用戶(hù)1萬(wàn)罚渐,每天高峰期4個(gè)小時(shí)却汉,高峰期活躍的用戶(hù)占比估算8成,就是8000人活躍在4小時(shí)內(nèi)對(duì)系統(tǒng)發(fā)起請(qǐng)求荷并。如果按每人每天發(fā)起20次算合砂,那么高峰期8000人發(fā)起的請(qǐng)求也才16萬(wàn)次,平均到4小時(shí)內(nèi)的每秒(14400秒)源织,每秒也就10次請(qǐng)求翩伪,估算每次API請(qǐng)求對(duì)應(yīng)3次數(shù)DB操作(CRUD),也就是每秒30次請(qǐng)求谈息,按照這臺(tái)數(shù)據(jù)庫(kù)服務(wù)器的配置缘屹,支撐是絕對(duì)沒(méi)問(wèn)題的。
上面描述的系統(tǒng)侠仇,大概就是下面這樣:
那么接下來(lái)我們開(kāi)始模擬系統(tǒng)的一個(gè)演變過(guò)程
-
系統(tǒng)集群化部署
如果此時(shí)用戶(hù)數(shù)開(kāi)始快速增長(zhǎng)了50倍轻姿,上升到500萬(wàn)。此時(shí)日活用戶(hù)是50萬(wàn)傅瞻,高峰期對(duì)系統(tǒng)每秒請(qǐng)求是500/s踢代。然后對(duì)數(shù)據(jù)庫(kù)的每秒請(qǐng)求數(shù)量是1500/s,這個(gè)時(shí)候會(huì)發(fā)生怎樣變化嗅骄?
按照上述的機(jī)器配置來(lái)說(shuō)胳挎,如果系統(tǒng)內(nèi)處理的是較為復(fù)雜的一些業(yè)務(wù)邏輯,是那種重業(yè)務(wù)邏輯系統(tǒng)的話是比較耗費(fèi)CPU的溺森。此時(shí)慕爬,8核16G的機(jī)器每秒請(qǐng)求達(dá)到500/s的時(shí)候,很可能機(jī)器CPU負(fù)載較高了屏积,然后DB層面医窿,以上述配置而言1500/s的高峰請(qǐng)求壓力應(yīng)該可以接受的。
這個(gè)主要是要觀察DB所在服務(wù)器的磁盤(pán)負(fù)載炊林、網(wǎng)絡(luò)負(fù)載姥卢、CPU負(fù)載、內(nèi)存負(fù)載的使用情況而定渣聚。
假設(shè)DB現(xiàn)在沒(méi)出現(xiàn)問(wèn)題那么需要做的一個(gè)事情独榴,首先就是要支持系統(tǒng)集群化部署∞戎Γ可以在前面掛一個(gè)負(fù)載均衡層棺榔,把請(qǐng)求均衡打到系統(tǒng)層面,讓系統(tǒng)可以用多臺(tái)機(jī)器集群化支撐更高的并發(fā)壓力隘道。
比如說(shuō)這里假設(shè)給系統(tǒng)增加部署一臺(tái)機(jī)器症歇,那么每臺(tái)機(jī)器就只有250/s的請(qǐng)求了郎笆。這樣一來(lái),兩臺(tái)機(jī)器的CPU負(fù)載都會(huì)明顯降低忘晤,要是連這個(gè)都不做宛蚓,那單臺(tái)機(jī)器負(fù)載越來(lái)越高的時(shí)候,極端情況下是可能出現(xiàn)機(jī)器上部署的系統(tǒng)無(wú)法有足夠的資源響應(yīng)請(qǐng)求了德频,然后出現(xiàn)請(qǐng)求卡死苍息,甚至系統(tǒng)宕機(jī)之類(lèi)的問(wèn)題。
- 添加負(fù)載均衡層壹置,將請(qǐng)求均衡打到系統(tǒng)層竞思。
- 系統(tǒng)層采用集群化部署多臺(tái)機(jī)器,扛住初步的并發(fā)壓力钞护。
此時(shí)的架構(gòu)圖大概變成下面的樣子:
-
DB分庫(kù)分表 + 讀寫(xiě)分離
如果用戶(hù)量繼續(xù)增長(zhǎng)盖喷,達(dá)到了1000萬(wàn)注冊(cè)用戶(hù),然后每天日活用戶(hù)是100萬(wàn)难咕。那么此時(shí)對(duì)系統(tǒng)層面的請(qǐng)求量會(huì)達(dá)到每秒1000/s课梳,按道理當(dāng)然可以繼續(xù)通過(guò)集群化的方式來(lái)擴(kuò)容,反正前面的負(fù)載均衡層會(huì)均勻分散流量過(guò)去的余佃。
但是暮刃,這時(shí)數(shù)據(jù)庫(kù)層面接受的請(qǐng)求量會(huì)達(dá)到3000/s,這就有點(diǎn)問(wèn)題了爆土。
此時(shí)數(shù)據(jù)庫(kù)層面的并發(fā)請(qǐng)求翻了一倍椭懊,一定會(huì)發(fā)現(xiàn)線上的DB負(fù)載越來(lái)越高。每次到了高峰期步势,磁盤(pán)IO氧猬、網(wǎng)絡(luò)IO、內(nèi)存消耗坏瘩、CPU負(fù)載的壓力都會(huì)很高很容易DB服務(wù)器崩潰的狀況盅抚。
所以此時(shí)你必須得對(duì)系統(tǒng)做分庫(kù)分表 + 讀寫(xiě)分離的擴(kuò)展,也就是把一個(gè)庫(kù)拆分為多個(gè)庫(kù)倔矾,部署在多個(gè)DB服務(wù)上妄均,這是作為主庫(kù)承載寫(xiě)入請(qǐng)求的。然后每個(gè)主庫(kù)都掛載至少一個(gè)從庫(kù)哪自,由從庫(kù)來(lái)承載讀請(qǐng)求丰包。
此時(shí)假設(shè)對(duì)數(shù)據(jù)庫(kù)層面的讀寫(xiě)并發(fā)是3000/s,其中寫(xiě)并發(fā)占到了1000/s提陶,讀并發(fā)占到了2000/s烫沙。那么一旦分庫(kù)分表之后匹层,采用兩臺(tái)數(shù)據(jù)庫(kù)服務(wù)器上部署主庫(kù)來(lái)支撐寫(xiě)請(qǐng)求隙笆,每臺(tái)服務(wù)器承載的寫(xiě)并發(fā)就是500/s锌蓄。每臺(tái)主庫(kù)掛載一個(gè)服務(wù)器部署從庫(kù),那么2個(gè)從庫(kù)每個(gè)從庫(kù)支撐的讀并發(fā)就是1000/s撑柔。
并發(fā)量繼續(xù)增長(zhǎng)時(shí)就需要關(guān)注在DB層面瘸爽。
優(yōu)先考慮分區(qū),當(dāng)分區(qū)不能滿(mǎn)足需求時(shí)铅忿,考慮分表剪决,合理的分表對(duì)效率的提升會(huì)優(yōu)于分區(qū),最后才是分庫(kù)檀训。
此時(shí)的架構(gòu)圖大概如下所示:
-
加入緩存集群
接下來(lái)柑潦,注冊(cè)用戶(hù)量還是越來(lái)越大,如果可以不停地加機(jī)器峻凫,比如說(shuō)系統(tǒng)層面不停加機(jī)器渗鬼,就可以承載更高的并發(fā)請(qǐng)求。
然后數(shù)據(jù)庫(kù)層面如果寫(xiě)入并發(fā)越來(lái)越高荧琼,就擴(kuò)容加數(shù)據(jù)庫(kù)服務(wù)器譬胎,通過(guò)分庫(kù)分表是可以支持?jǐn)U容機(jī)器的,如果數(shù)據(jù)庫(kù)層面的讀并發(fā)越來(lái)越高命锄,就擴(kuò)容加更多的從庫(kù)堰乔。
但是這里有一個(gè)很大的問(wèn)題:數(shù)據(jù)庫(kù)其實(shí)本身不是用來(lái)承載高并發(fā)請(qǐng)求的而且使用服務(wù)器越多成本越高,這明顯是下策中的下策脐恩。那么現(xiàn)在要怎么來(lái)改善镐侯?
在高并發(fā)架構(gòu)里通常都有緩存這個(gè)環(huán)節(jié),緩存系統(tǒng)的設(shè)計(jì)就是為了承載高并發(fā)而生被盈。AP承載的并發(fā)量都在每秒幾萬(wàn)析孽,甚至每秒數(shù)十萬(wàn),對(duì)高并發(fā)的承載能力比數(shù)據(jù)庫(kù)系統(tǒng)要高出一到兩個(gè)數(shù)量級(jí)只怎。
具體來(lái)說(shuō)袜瞬,寫(xiě)DB的時(shí)候同時(shí)寫(xiě)一份數(shù)據(jù)到緩存集群里,然后用緩存集群來(lái)承載大部分的讀請(qǐng)求身堡。這樣的話邓尤,通過(guò)緩存集群,就可以用更少的機(jī)器資源承載更高的并發(fā)贴谎。這里可以根據(jù)系統(tǒng)的業(yè)務(wù)特性汞扎,對(duì)那種寫(xiě)少讀多的請(qǐng)求,引入緩存集群擅这。
比如讀請(qǐng)求目前是每秒2000/s澈魄,兩個(gè)從庫(kù)各自抗了1000/s讀請(qǐng)求,但是其中可能每秒1800次的讀請(qǐng)求都是可以直接讀緩存里的不怎么變化的數(shù)據(jù)仲翎。那么此時(shí)你一旦引入緩存集群痹扇,就可以抗下來(lái)這1800/s讀請(qǐng)求铛漓,落到數(shù)據(jù)庫(kù)層面的讀請(qǐng)求就200/s。
- 不要盲目進(jìn)行數(shù)據(jù)庫(kù)擴(kuò)容鲫构,服務(wù)器成本昂貴
- 引入緩存集群浓恶,用緩存集群抗住大量的讀請(qǐng)求
同樣,給大家來(lái)一張架構(gòu)圖结笨,一起來(lái)感受一下:
由于時(shí)間關(guān)系簡(jiǎn)單的一個(gè)小結(jié)
- 系統(tǒng)集群化
- DB層面的分庫(kù)分表+讀寫(xiě)分離
- 針對(duì)讀多寫(xiě)少的請(qǐng)求包晰,引入緩存集群
這個(gè)改善步驟不一定要這樣,可以針對(duì)系統(tǒng)中出現(xiàn)的問(wèn)題來(lái)專(zhuān)門(mén)優(yōu)化解決炕吸。
初步來(lái)說(shuō)伐憾,簡(jiǎn)單的一個(gè)改善闡述是講完了,但是其實(shí)改善才剛開(kāi)始赫模。
一個(gè)完整而復(fù)雜的高并發(fā)系統(tǒng)架構(gòu)中塞耕,會(huì)包含各種復(fù)雜的自研基礎(chǔ)架構(gòu)系統(tǒng)、各種精妙的架構(gòu)設(shè)計(jì)(比如熱點(diǎn)緩存架構(gòu)設(shè)計(jì)嘴瓤、多優(yōu)先級(jí)高吞吐MQ架構(gòu)設(shè)計(jì)扫外,等等)、監(jiān)控服務(wù)平臺(tái)廓脆、還有各種復(fù)雜系統(tǒng)組合而成的高并發(fā)架構(gòu)整體技術(shù)方案筛谚、還有負(fù)載均衡/Web服務(wù)器等相關(guān)技術(shù)。
所以大家切記要對(duì)技術(shù)保持敬畏之心停忿,虛心學(xué)習(xí)驾讲。
一個(gè)人可以走得很快,一群人可以走得很遠(yuǎn)席赂。