隔離設(shè)計(jì)對應(yīng)的單詞是 Bulkheads欢伏,中文翻譯為隔板匿垄。但其實(shí),這個術(shù)語是用在造船上的虎忌,也就是船艙里防漏水的隔板泡徙。一般的船無論大小都會有這個東西,大一點(diǎn)的船都會把船艙隔成若干個空間膜蠢。這樣堪藐,如果船艙漏水,只會進(jìn)到一個小空間里挑围,不會讓整個船艙都進(jìn)水而導(dǎo)致整艘船都沉了礁竞,如下圖所示。
我們的軟件設(shè)計(jì)當(dāng)然也“漏水”杉辙,所以為了不讓“故障”蔓延開來模捂,需要使用“隔板”技術(shù),來將架構(gòu)分隔成多個“船艙”來隔離故障蜘矢。
在分布式軟件架構(gòu)中狂男,我們同樣需要使用類似的技術(shù)來讓我們的故障得到隔離。這就需要我們對系統(tǒng)進(jìn)行分離品腹。一般來說并淋,對于系統(tǒng)的分離有兩種方式,一種是以服務(wù)的種類來做分離珍昨,一種是以用戶來做分離县耽。下面具體說明一下這兩種方式句喷。
按服務(wù)的種類來做分離
下面這個圖中,說明了按服務(wù)種類來做分離的情況兔毙。
上圖中唾琼,我們將系統(tǒng)分成了用戶、商品澎剥、社區(qū)三個板塊锡溯。這三個塊分別使用不同的域名、服務(wù)器和數(shù)據(jù)庫哑姚,做到從接入層到應(yīng)用層再到數(shù)據(jù)層三層完全隔離祭饭。這樣一來,在物理上來說叙量,一個板塊的故障就不會影響到另一板塊倡蝙。
然而任何架構(gòu)都有其好和不好的地方,上面這種架構(gòu)雖然在系統(tǒng)隔離上做得比較好绞佩,但是也存在以下一些問題寺鸥。
1、如果我們需要同時獲得多個板塊的數(shù)據(jù)品山,那么就需要調(diào)用多個服務(wù)胆建,這會降低性能。注意肘交,這里性能降低指的是響應(yīng)時間笆载,而不是吞吐量(相反,在這種架構(gòu)下涯呻,吞吐量可以得到提高)凉驻。
對于這樣的問題,一般來說魄懂,我們需要小心地設(shè)計(jì)用戶交互,最好不要讓用戶在一個頁面上獲得所有的數(shù)據(jù)闯第。對于目前的手機(jī)端來說市栗,因?yàn)槭謾C(jī)屏幕尺寸比較小,所以咳短,也不可能在一個屏幕頁上展示太多的內(nèi)容填帽。
2、如果有大數(shù)據(jù)平臺咙好,就需要把這些數(shù)據(jù)都抽取到一個數(shù)據(jù)倉庫中進(jìn)行計(jì)算篡腌,這也增加了數(shù)據(jù)合并的復(fù)雜度。對于這個問題勾效,我們需要一個框架或是一個中間件來對數(shù)據(jù)進(jìn)行相應(yīng)的抽取嘹悼。
3叛甫、另外,如果我們的業(yè)務(wù)邏輯或是業(yè)務(wù)流程需要跨板塊的話杨伙,那么一個板塊的故障也會導(dǎo)致整個流程走不下去其监,同樣會導(dǎo)致整體業(yè)務(wù)故障。
對于這個問題限匣,一方面抖苦,我們需要保證這個業(yè)務(wù)流程中各個子系統(tǒng)的高可用性,并且在業(yè)務(wù)流程上做成 Step-by-Step 的方式米死,這樣用戶交互的每一步都可以保存锌历,以便故障恢復(fù)后可以繼續(xù)執(zhí)行,而不是從頭執(zhí)行峦筒。
4究西、還有,如果需要有跨板塊的交互也會變得有點(diǎn)復(fù)雜勘天。對此我們需要一個類似于 Pub/Sub 的高可用怔揩、且可以持久化的消息訂閱通知中間件來打通各個板塊的數(shù)據(jù)和信息交換。
5脯丝、最后還會有在多個板塊中分布式事務(wù)的問題商膊。對此,我們需要“二階段提交”這樣的方案宠进。
按用戶的請求來做分離
下圖是一個按用戶請求來做分離的圖示晕拆。
在這個圖中,可以看到材蹬,我們將用戶分成不同的組实幕,并把后端的同一個服務(wù)根據(jù)這些不同的組分成不同的實(shí)例。讓同一個服務(wù)對于不同的用戶進(jìn)行冗余和隔離堤器,這樣一來昆庇,當(dāng)服務(wù)實(shí)例掛掉時,只會影響其中一部分用戶闸溃,而不會導(dǎo)致所有的用戶無法訪問整吆。
這種分離和上面按功能的分離可以融合。說白了辉川,這就是所謂的“多租戶”模式表蝙。對于一些比較大的客戶,我們可以為他們設(shè)置專門獨(dú)立的服務(wù)實(shí)例乓旗,或是服務(wù)集群與其他客戶隔離開來府蛇,對于一些比較小的用戶來說,可以讓他們共享一個服務(wù)實(shí)例屿愚,這樣可以節(jié)省相關(guān)的資源汇跨。
對于“多租戶”的架構(gòu)來說务荆,會引入一些系統(tǒng)設(shè)計(jì)的復(fù)雜度。一方面扰法,如果完全隔離蛹含,資源使用上會比較浪費(fèi),如果共享塞颁,又會導(dǎo)致程序設(shè)計(jì)的一些復(fù)雜度浦箱。
通常來說多租戶的做法有三種。
1祠锣、完全獨(dú)立的設(shè)計(jì)酷窥。每個租戶有自己完全獨(dú)立的服務(wù)和數(shù)據(jù)。
2伴网、獨(dú)立的數(shù)據(jù)分區(qū)蓬推,共享的服務(wù)。多租戶的服務(wù)是共享的澡腾,但數(shù)據(jù)是分開隔離的沸伏。
3、共享的服務(wù)动分,共享的數(shù)據(jù)分區(qū)毅糟。每個租戶的數(shù)據(jù)和服務(wù)都是共享的。
這三種方案各有優(yōu)缺點(diǎn)澜公,如圖所示姆另。
通過上圖,可以看到:
如果使用完全獨(dú)立的方案坟乾,在開發(fā)實(shí)現(xiàn)上和資源隔離度方面會非常好迹辐,然而,成本會比較高甚侣,計(jì)算資源也會有一定的浪費(fèi)明吩。
如果使用完全共享的方案,在資源利用和成本上會非常好殷费,然而印荔,開發(fā)難度非常大,而且數(shù)據(jù)和資源隔離非常不好宗兼。
所以躏鱼,一般來說氮采,技術(shù)方案會使用折衷方案殷绍,也就是中間方案,服務(wù)是共享的鹊漠,數(shù)據(jù)通過分區(qū)來隔離主到,而對于一些比較重要的租戶(需要好的隔離性)茶行,則使用完全獨(dú)立的方式。
然而登钥,在虛擬化技術(shù)非常成熟的今天畔师,我們完全可以使用“完全獨(dú)立”(完全隔離)的方案,通過底層的虛擬化技術(shù)(Hypervisor 的技術(shù)牧牢,如 KVM看锉,或是 Linux Container 的技術(shù),如 Docker)來實(shí)現(xiàn)物理資源的共享和成本的節(jié)約塔鳍。
隔離設(shè)計(jì)的重點(diǎn)
要能做好隔離設(shè)計(jì)伯铣,我們需要有如下的一些設(shè)計(jì)考量。
1轮纫、我們需要定義好隔離業(yè)務(wù)的大小和粒度腔寡,過大和過小都不好。這需要認(rèn)真地做業(yè)務(wù)上的需求和系統(tǒng)分析掌唾。
2放前、無論是做系統(tǒng)板塊還是多租戶的隔離,你都需要考慮系統(tǒng)的復(fù)雜度糯彬、成本凭语、性能、資源使用的問題情连,找到一個合適的均衡方案叽粹,或是分布實(shí)施的方案尤其重要,這其中需要你定義好要什么和不要什么却舀。因?yàn)槌婕福覀儾豢赡茏龀鲆粋€什么都能滿足的系統(tǒng)。
3挽拔、隔離模式需要配置一些高可用辆脸、重試、異步螃诅、消息中間件啡氢,流控、熔斷等設(shè)計(jì)模式的方式配套使用术裸。
4倘是、不要忘記了分布式系統(tǒng)中的運(yùn)維的復(fù)雜度的提升,要能駕馭得好的話袭艺,還需要很多自動化運(yùn)維的工具搀崭,尤其是使用像容器或是虛擬機(jī)這樣的虛擬化技術(shù)可以幫助我們更方便地管理,和對比資源更好地利用猾编。否則做出來了也管理不好瘤睹。
5升敲、最后,你需要一個非常完整的能夠看得到所有服務(wù)的監(jiān)控系統(tǒng)轰传,這點(diǎn)非常重要驴党。