彈力設計之隔離設計

隔離設計對應的單詞是 Bulkheads,中文翻譯爲隔板。但其實,這個術語是用在造船上的,也就是船艙裏防漏水的隔板。一般的船無論大小都會有這個東西,大一點的船都會把船艙隔成若干個空間。這樣,如果船艙漏水,只會進到一個小空間裏,不會讓整個船艙都進水而導致整艘船都沉了,如下圖所示。




我們的軟件設計當然也“漏水”,所以爲了不讓“故障”蔓延開來,需要使用“隔板”技術,來將架構分隔成多個“船艙”來隔離故障。

在分佈式軟件架構中,我們同樣需要使用類似的技術來讓我們的故障得到隔離。這就需要我們對系統進行分離。一般來說,對於系統的分離有兩種方式,一種是以服務的種類來做分離,一種是以用戶來做分離。下面具體說明一下這兩種方式。

按服務的種類來做分離

下面這個圖中,說明了按服務種類來做分離的情況。



上圖中,我們將系統分成了用戶、商品、社區三個板塊。這三個塊分別使用不同的域名、服務器和數據庫,做到從接入層到應用層再到數據層三層完全隔離。這樣一來,在物理上來說,一個板塊的故障就不會影響到另一板塊。

然而任何架構都有其好和不好的地方,上面這種架構雖然在系統隔離上做得比較好,但是也存在以下一些問題。

1、如果我們需要同時獲得多個板塊的數據,那麼就需要調用多個服務,這會降低性能。注意,這裏性能降低指的是響應時間,而不是吞吐量(相反,在這種架構下,吞吐量可以得到提高)。
對於這樣的問題,一般來說,我們需要小心地設計用戶交互,最好不要讓用戶在一個頁面上獲得所有的數據。對於目前的手機端來說,因爲手機屏幕尺寸比較小,所以,也不可能在一個屏幕頁上展示太多的內容。

2、如果有大數據平臺,就需要把這些數據都抽取到一個數據倉庫中進行計算,這也增加了數據合併的複雜度。對於這個問題,我們需要一個框架或是一箇中間件來對數據進行相應的抽取。

3、另外,如果我們的業務邏輯或是業務流程需要跨板塊的話,那麼一個板塊的故障也會導致整個流程走不下去,同樣會導致整體業務故障。
對於這個問題,一方面,我們需要保證這個業務流程中各個子系統的高可用性,並且在業務流程上做成 Step-by-Step 的方式,這樣用戶交互的每一步都可以保存,以便故障恢復後可以繼續執行,而不是從頭執行。

4、還有,如果需要有跨板塊的交互也會變得有點複雜。對此我們需要一個類似於 Pub/Sub 的高可用、且可以持久化的消息訂閱通知中間件來打通各個板塊的數據和信息交換。

5、最後還會有在多個板塊中分佈式事務的問題。對此,我們需要“二階段提交”這樣的方案。

按用戶的請求來做分離

下圖是一個按用戶請求來做分離的圖示。



在這個圖中,可以看到,我們將用戶分成不同的組,並把後端的同一個服務根據這些不同的組分成不同的實例。讓同一個服務對於不同的用戶進行冗餘和隔離,這樣一來,當服務實例掛掉時,只會影響其中一部分用戶,而不會導致所有的用戶無法訪問。

這種分離和上面按功能的分離可以融合。說白了,這就是所謂的“多租戶”模式。對於一些比較大的客戶,我們可以爲他們設置專門獨立的服務實例,或是服務集羣與其他客戶隔離開來,對於一些比較小的用戶來說,可以讓他們共享一個服務實例,這樣可以節省相關的資源。

對於“多租戶”的架構來說,會引入一些系統設計的複雜度。一方面,如果完全隔離,資源使用上會比較浪費,如果共享,又會導致程序設計的一些複雜度。

通常來說多租戶的做法有三種。

1、完全獨立的設計。每個租戶有自己完全獨立的服務和數據。
2、獨立的數據分區,共享的服務。多租戶的服務是共享的,但數據是分開隔離的。
3、共享的服務,共享的數據分區。每個租戶的數據和服務都是共享的。

這三種方案各有優缺點,如圖所示。



通過上圖,可以看到:

如果使用完全獨立的方案,在開發實現上和資源隔離度方面會非常好,然而,成本會比較高,計算資源也會有一定的浪費。
如果使用完全共享的方案,在資源利用和成本上會非常好,然而,開發難度非常大,而且數據和資源隔離非常不好。

所以,一般來說,技術方案會使用折衷方案,也就是中間方案,服務是共享的,數據通過分區來隔離,而對於一些比較重要的租戶(需要好的隔離性),則使用完全獨立的方式。

然而,在虛擬化技術非常成熟的今天,我們完全可以使用“完全獨立”(完全隔離)的方案,通過底層的虛擬化技術(Hypervisor 的技術,如 KVM,或是 Linux Container 的技術,如 Docker)來實現物理資源的共享和成本的節約。

隔離設計的重點

要能做好隔離設計,我們需要有如下的一些設計考量。

1、我們需要定義好隔離業務的大小和粒度,過大和過小都不好。這需要認真地做業務上的需求和系統分析。
2、無論是做系統板塊還是多租戶的隔離,你都需要考慮系統的複雜度、成本、性能、資源使用的問題,找到一個合適的均衡方案,或是分佈實施的方案尤其重要,這其中需要你定義好要什麼和不要什麼。因爲,我們不可能做出一個什麼都能滿足的系統。
3、隔離模式需要配置一些高可用、重試、異步、消息中間件,流控、熔斷等設計模式的方式配套使用。
4、不要忘記了分佈式系統中的運維的複雜度的提升,要能駕馭得好的話,還需要很多自動化運維的工具,尤其是使用像容器或是虛擬機這樣的虛擬化技術可以幫助我們更方便地管理,和對比資源更好地利用。否則做出來了也管理不好。
5、最後,你需要一個非常完整的能夠看得到所有服務的監控系統,這點非常重要。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章