高并發(fā)經(jīng)常會(huì)發(fā)生在有大活躍用戶量,用戶高聚集的業(yè)務(wù)場(chǎng)景中,如:秒殺活動(dòng),定時(shí)領(lǐng)取紅包等。
為了讓業(yè)務(wù)可以流暢的運(yùn)行并且給用戶一個(gè)好的交互體驗(yàn),我們需要根據(jù)業(yè)務(wù)場(chǎng)景預(yù)估達(dá)到的并發(fā)量等因素,來(lái)設(shè)計(jì)適合自己業(yè)務(wù)場(chǎng)景的高并發(fā)處理方案。
在工作這些年里,我有幸遇到了高并發(fā)各種坑,對(duì)如何設(shè)計(jì)高性能接口有一些經(jīng)驗(yàn),其實(shí)無(wú)外乎滿足以下幾個(gè)特點(diǎn):
靈敏性
伸縮性
容錯(cuò)性
事件驅(qū)動(dòng)/消息驅(qū)動(dòng)
高性能接口設(shè)計(jì)準(zhǔn)則
在引言里我也說(shuō)了高性能設(shè)計(jì)的四個(gè)準(zhǔn)則,現(xiàn)在具體對(duì)這四個(gè)準(zhǔn)則做一些描述;
1. 靈敏性
應(yīng)用程序應(yīng)該盡可能快的對(duì)請(qǐng)求做出響應(yīng)。
如果可以在順序獲取數(shù)據(jù)和并行獲取數(shù)據(jù)之間進(jìn)行選擇的話,為了盡快向用戶返回響應(yīng),始終應(yīng)該優(yōu)先選擇并行獲取數(shù)據(jù),可以同時(shí)請(qǐng)求互相沒(méi)有關(guān)聯(lián)的數(shù)據(jù)。當(dāng)我們需要請(qǐng)求多個(gè)互相無(wú)關(guān),沒(méi)有依賴的數(shù)據(jù)的時(shí)候,應(yīng)該考慮是否能夠同時(shí)請(qǐng)求這些數(shù)據(jù)。
如果可能出現(xiàn)錯(cuò)誤,應(yīng)該立即返回,將問(wèn)題通知用戶,不要讓用戶等待直到超時(shí)。
1.1 如何設(shè)計(jì)靈敏性
緩存前置
對(duì)于一些改變不頻繁的數(shù)據(jù),應(yīng)該放在分布式緩存中,例如redis,如果是一些元數(shù)據(jù)(例如,一些計(jì)數(shù)器的配置信息,變量的配置信息等)則應(yīng)該啟用本地緩存,簡(jiǎn)單流程如下:
如果一些熱點(diǎn)數(shù)據(jù)不大的話,建議服務(wù)啟動(dòng)的時(shí)候就應(yīng)該提前加載到緩存中,這樣可以提高服務(wù)的性能。
讀寫拆分部署
如果你的服務(wù)既涉及到讀操作,也涉及到寫操作, 應(yīng)該將讀寫隔離部署,這樣讀服務(wù)的壓力不會(huì)影響到寫服務(wù),寫服務(wù)的壓力不會(huì)影響到讀服務(wù)。流程如下:
當(dāng)然除了按照讀寫進(jìn)行拆分部署外,還可以按照業(yè)務(wù)進(jìn)行隔離部署。
對(duì)等設(shè)計(jì)、無(wú)狀態(tài)
所謂無(wú)狀態(tài)是指應(yīng)用服務(wù)器不保存業(yè)務(wù)的上下文信息,而僅根據(jù)每次請(qǐng)求提交的數(shù)據(jù)進(jìn)行相應(yīng)的業(yè)務(wù)邏輯處理,多個(gè)服務(wù)實(shí)例(服務(wù)器)之間完全對(duì)等,請(qǐng)求提交到任意服務(wù)器,處理結(jié)果是完全一樣的。
不保存狀態(tài)的應(yīng)用給高可用的架構(gòu)設(shè)計(jì)帶來(lái)了巨大便利,既然服務(wù)器不保存請(qǐng)求的狀態(tài),那么所有的服務(wù)器完全對(duì)等,當(dāng)任意一臺(tái)或多臺(tái)服務(wù)器宕機(jī),請(qǐng)求提交給集群中的其他任意一臺(tái)可用機(jī)器處理,這樣對(duì)終端用戶而言,請(qǐng)求總是能夠成功的,整個(gè)系統(tǒng)依然可用。對(duì)于應(yīng)用服務(wù)器集群,實(shí)現(xiàn)這種服務(wù)器可用狀態(tài)實(shí)時(shí)檢測(cè)、自動(dòng)轉(zhuǎn)移失敗任務(wù)的機(jī)制就是負(fù)載均衡。
DB分庫(kù)分表,讀寫分離
對(duì)于數(shù)據(jù)層來(lái)說(shuō),如果數(shù)據(jù)量不大,db可以采用讀寫分離部署,對(duì)于讀多寫少的場(chǎng)景可以解決一部分壓力,從而提高我們接口的響應(yīng)速度,如果寫的數(shù)據(jù)量和讀的數(shù)據(jù)量都很大,那么就必須要對(duì)db進(jìn)行分庫(kù)分表外加讀寫分離了。
2. 伸縮性
應(yīng)用程序應(yīng)該能夠根據(jù)不同的工作負(fù)載進(jìn)行伸縮擴(kuò)展(尤其是通過(guò)增加計(jì)算資源來(lái)進(jìn)行擴(kuò)展)。為了提供伸縮性,系統(tǒng)應(yīng)該努力消除瓶頸。
如果在虛擬機(jī)上運(yùn)行內(nèi)存數(shù)據(jù)庫(kù),那么添加另一個(gè)虛擬幾點(diǎn)就可以將所有的查詢請(qǐng)求分布到兩臺(tái)虛擬服務(wù)器上,將可能的吞吐量增加至原來(lái)的兩倍。添加額外的節(jié)點(diǎn)應(yīng)該能夠幾乎線性的提高系統(tǒng)的性能。
增加一個(gè)內(nèi)存數(shù)據(jù)庫(kù)的節(jié)點(diǎn)后,還可以將數(shù)據(jù)分為兩半,并將其中的一半移至新的節(jié)點(diǎn),這樣就能夠?qū)?nèi)存容量提高至原來(lái)的兩倍。添加節(jié)點(diǎn)應(yīng)該能夠幾乎線性的提高內(nèi)存容量。
所以一般好的接口設(shè)計(jì)是可以通過(guò)水平擴(kuò)展機(jī)器來(lái)達(dá)到提升性能的,這就要求我們?cè)O(shè)計(jì)接口的時(shí)候提現(xiàn)無(wú)狀態(tài)性。
3. 容錯(cuò)性
應(yīng)用程序應(yīng)該考慮到錯(cuò)誤發(fā)生的情況,并且從容的對(duì)錯(cuò)誤情況做出響應(yīng)。如果系統(tǒng)的某個(gè)組件發(fā)生錯(cuò)誤,對(duì)與該組件無(wú)關(guān)的請(qǐng)求不應(yīng)該產(chǎn)生任務(wù)影響。錯(cuò)誤是難以避免的,因此應(yīng)該將錯(cuò)誤造成的影響限制在發(fā)生錯(cuò)誤的組件之內(nèi)。如果可能的話,通過(guò)對(duì)重要組件及數(shù)據(jù)的備份和冗余,這些組件發(fā)生錯(cuò)誤時(shí)不應(yīng)該對(duì)其外部行為有任何影響。
假設(shè)你的系統(tǒng)既使用了redis,也使用了mysql對(duì)數(shù)據(jù)進(jìn)行處理,當(dāng)redis或著mysql掛了的時(shí)候,程序應(yīng)該可以繼續(xù)提供服務(wù),而不是一味的報(bào)錯(cuò)。流程如下:
當(dāng)一個(gè)組件不可用的時(shí)候,可以使用開關(guān)對(duì)某一個(gè)組件進(jìn)行降級(jí),常見(jiàn)的降級(jí)方式分為手動(dòng)降級(jí)和自動(dòng)降級(jí),手動(dòng)降級(jí)可以借助zookeeper進(jìn)行,自動(dòng)降級(jí)可以使用Hystrix。
4. 事件驅(qū)動(dòng)/消息驅(qū)動(dòng)
使用消息而不直接進(jìn)行方法調(diào)用提供了一種幫助我們滿足另外3個(gè)高性能設(shè)計(jì)準(zhǔn)則的方法。消息驅(qū)動(dòng)的系統(tǒng)著重于控制何時(shí)、何地以及如何對(duì)請(qǐng)求做出響應(yīng),允許做出響應(yīng)的組件進(jìn)行路由以及負(fù)載均衡。
由于異步的消息驅(qū)動(dòng)系統(tǒng)只在真正需要時(shí)才會(huì)消耗資源(比如線程),因此它對(duì)系統(tǒng)資源的利用更為高效。消息也可以被發(fā)送到遠(yuǎn)程機(jī)器(位置透明)。
通常不是萬(wàn)不得已,否則我們認(rèn)為丟失一部分?jǐn)?shù)據(jù)換取服務(wù)的高性能,這是值得的。如果能容忍數(shù)據(jù)的部分丟失(在可接受范圍內(nèi)),比如保存數(shù)據(jù)到db,異步計(jì)算耗時(shí)的任務(wù),通過(guò)消息隊(duì)列將是提升我們系統(tǒng)性能的比較好的方式。
總結(jié)
4個(gè)設(shè)計(jì)準(zhǔn)則之間并不是完全獨(dú)立的。為了滿足某個(gè)準(zhǔn)則而采取的方法通常也對(duì)滿足其他準(zhǔn)備有所幫助。例如,如果發(fā)現(xiàn)某個(gè)服務(wù)響應(yīng)速度較慢,我們可能會(huì)在短時(shí)間內(nèi)停止再向該服務(wù)發(fā)送請(qǐng)求,等待其恢復(fù)正常,并立即向用戶返回錯(cuò)誤信息。這樣做降低了響應(yīng)慢的服務(wù)不堪重負(fù)直接崩潰的風(fēng)險(xiǎn),因此也提高了系統(tǒng)的容錯(cuò)性。除此之外,我們立即告知了用戶系統(tǒng)發(fā)生的問(wèn)題,也就改善了系統(tǒng)的響應(yīng)速度,如圖所示:
責(zé)任編輯人:CC
評(píng)論