標籤:
分布式系統總結
我們的系統一直是分布式的。即便在虛擬化、容器技術出現之前,我想他也是一個分布式系統。今天嘗試將我對分布式的理解做一些總結。
為什麼要分布式?
我想首先是money方面的問題。隨著產品支援的容量增加,軟體的計算量、儲存的資料都變得很大。Grosch定理說CPU的計算能力與它的價格的平方成正比。也就是說如果你付出兩倍的價錢,就能獲得四倍的效能。這麼看其實花錢買高效能的CPU更划算。很遺憾Grosch定理不再適用了。另一方面,隨著計算量的增加,沒有辦法找到這樣強大的電腦做到這麼大的計算量(比如春晚搖紅包的計算量估計不可能由一台電腦搞定)。這要求必須將計算能力一般的電腦群組織到一起,完成超級計算。
其次,是部署和營運的考慮。所有計算都在一個電腦上,一個故障就全玩玩了。而多個電腦共同工作時,一個故障不會影響大局。在升級時,也可以先升級試用某一些電腦,效果滿意再升級全部。
第三,當業務持續增長時,分布式系統能更好應對 —— 多加入一些電腦就行了。
其實不需要多說,雲端運算的興起已經說明了一切。
下面聊一下分布式系統中主要考慮的問題。
總的講,一個分布式系統必須考慮的幾個大塊: 接入、計算、儲存, 以及這幾塊之間的資料通訊 ——交換。
一、對外統一介面,內部結點透明,多業務並發
一個系統對外一定是介面固定的,外部使用者一定要有一個固定的入口接入系統。比如提供固定的IP地址、偶聯地址、或者某協議地址或網域名稱。內部的計算結點不能直接對外可見,否則無法做可靠性、水平擴充等等工作。這就要求有一個接入部分,同時要在接入部分和內部結點之間做一次負載平衡。通常負載平衡策略是根據自己的業務特點決定的。
最簡單的就是輪選計算結點,當計算結點的個數發生變化(水平擴充或縮容)時需要負載平衡器感知到即可。但往往業務特點決定了不會選擇簡單輪選策略,比如:一個業務是長串連的,長串連意思是一個商務程序需要和外部多條訊息互動。那麼在一個商務程序中,必須將訊息都發到同一個計算結點,這就需要設計自己特點的轉寄策略。比如下面訊息3必須也發給第一個結點。
再有,還可能和資料存放區方式有關係,具體來說:如果計算結點是純計算(即不儲存使用者資料),那麼每次商務程序的開始都可以隨意選擇一個計算結點,他從儲存部分擷取需要的資料,業務完成後再推送回儲存部分。但這種方式增加了資料交換的負擔。比如第一次業務完成後,第二次業務完全可以選擇第三個計算結點。
有時產品希望將使用者資料cache到計算結點上面,這樣就不用每次業務來臨都從儲存部分拉去資料,這種方式減少了資料交換,但是帶來了其他方面的考慮:使用者資料和計算結點有強耦合關係,必須通過一定的負載策略將特定的使用者發送到特定的計算結點處理。這又對可靠性、水平擴充方面帶來了難度:因為必鬚根據使用者和計算結點的關係進行負載策略的調整。
對多業務並發的情況是設計負載平衡策略時要考慮的又一個問題。即對同一個使用者同時出現多個業務操作——即流程衝突。比如對一個使用者,可以進行業務A,也可以進行業務B。 但是如果在執行業務A的時候,業務B的請求又上來了,系統需要處理這種情況。這裡有兩個考量:1是需要識別出正在執行A,2是如果處理AB同時進行的業務,還是終止某一個。 其中考量1又會牽扯到負載平衡策略的設計,比如,同一個使用者的業務是否都需要轉向同一個計算結點?
總的說,我認為應該儘可能的將計算和資料解耦,由此帶來的資料交換的問題可以嘗試減少資料量(必須僅傳輸本次商務程序必須的資料)來減少。同時將業務拆分為更小、獨立的service,這樣也會降低資料交換。 而這樣可以帶來計算結點管理的簡單。
二、高穩定性
穩定性來自兩個方面:一個是程式健壯,這反映的是每一個結點都高可靠。 二是系統健壯,即一個結點出問題不影響整個系統運行。我們討論第二點。
最早期的可靠性保證是簡單、粗暴的方式,一般簡單粗暴都是最有效。比如主備熱備份的方式。一個單板運行處理業務(主板),另一個單板空轉(備板),就等候著處理板出問題時自己頂上。主板即時的將處理的業務資料同步到備板。可以說備板就是主備的複製。轉寄系統一旦發現主板出現問題,直接將訊息鏈路切換到備板,備板可以繼續運行。這種方式提供了高可靠性,代價是硬體的低效利用。
也許可以在上述方案上最佳化。比如互備的方式:即兩個板子都處理業務,但是互相做備份。即把兩塊板子配置成好基友,每個上面都有對方的配置和運行資料。當一塊板子出現問題時,另一個把他的業務也接管過來,自己幹兩個人的活。這樣似乎彌補了上面備板空跑的情況,有效利用了資源。但相信睿智的您肯定發現:互備的兩個基友資源使用率不可以超過50%,一旦超過,也是無法接管對方的業務。 所以本質上並沒有改變。
再繼續分析,其實系統中計算結點出現故障的機率是不高的,多個結點同時故障的機率更低。所以可以多個業務處理板由一個備板備份(n+1)的方式。這種方式可以提高硬體的使用率。當然還可以做n+m的備份方式。我們不繼續做分析了。
總結這些保證可靠性的思路無非兩個方面:一是通過系統存在冗餘的計算能力,確保電腦出問題時還有計算結點頂上去。二是在保證這種計算能力的同時,還保證了計算結點的資料(參考粗暴方案中的資料同步) 。我們要清晰的分開考慮這兩個問題,這也是我上面說的計算和資料解耦。
事實上,虛擬化技術的出現解決了計算能力的保證,無論是openstack,還是容器都可以通過他們的技術使得在一個計算結點故障時,再建立一個相同能力的計算結點出來。而資料,應該放到計算之外的地方去。
三、資料存放區
為了討論方便,我們將資料分為兩類:待用資料(配置)和動態資料(使用者資料)。這兩種資料的對待方式是不同的。
對於待用資料來說,資料必須隨時有效,必須做持久化儲存。所以必須在硬碟或資料庫中有資料。同時,這類資料的特點是讀多寫少,或幾乎沒有寫,而讀取資料的頻率非常高,所以應該做一個讀緩衝層,資料在記憶體中cache,保證效率。
對於使用者資料來說,情況就又不一樣。使用者一旦接入網路,就需要將資料建立並儲存下來,以後使用者做業務就要操作這些資料。一種方案是將資料存放區在業務處理結點上,這是最容易的方案。但是這種方案使計算和資料產生的綁定,在負載平衡、可靠性、水平伸縮方面都需要考慮很多。 另一種方案是將資料拉遠,放到儲存服務中。這種方式降低了計算與資料的耦合,但是增加了資料交換,對網路提出了要求,同時資料擷取的非同步過程對編碼也有一些改動。 這方面在前面也討論了很多,計算與儲存綁定的方案, 計算與儲存分離的方案我們都經曆過。 總的講我認為應該分離,因為計算結點可靠性的原因、計算結點擴充性的原因等等......當然也是一個權衡,需要根據項目的情況決定。
四、能力水平擴充
這是虛擬化技術帶來的功能。在虛擬化出現之前,我們擴容一次都要重新設定負荷分擔策略,整個系統重啟,那時的符合分擔與硬體單元是靜態配置的。談不上能力擴充。虛擬化使得系統和硬體解耦,軟體看到的不再是某框某槽某型號的CPU,而是“資源”。在增加、重啟一個虛擬機器非常容易的情況下,原來的很多問題都不再是問題:比如一個硬體發生故障我想立即啟動一個相同的(這在以前是不可能的除非人跑到機房去弄), 再比如業務量增多了我需要加一些資源(以前也要人去啟動更多的伺服器)。
虛擬化技術帶來了這些,那麼怎麼實現系統的能力擴充:
1. 首先要有一套檢測系統來監控系統啟動並執行狀態,
2. 還要有一個決策機制來計算和決策彈性動作的執行
3. 還有考慮配套的負載平衡的變化、使用者資料的訪問、進行中中的業務如何處理等等。。。
介紹一個集中管理式思路,各個計算結點將資源使用方式上報給總監控結點,再由決策機制計算後決定彈性動作。
彈性過程啟動資源申請或釋放,同時伴隨著負載平衡策略的調整,使用者資料的擷取等等。這裡是比較難的地方,不同的設計差別也比較大。假如有產品對業務成功率要求變態的高(比如我們項目),要求在彈性過程中也要保持業務成功率,而一個業務的流程又很長的時候就很麻煩。具體來說,比如一個業務要執行10條訊息互動,而在第5條的時候監控結點決策出應該擴容,又增加了一些計算結點,這必然導致負載平衡策略的調整。如果不幸的將負載平衡策略設計的與使用者有關係,這時一個使用者的訊息將無法決策往那個計算結點轉寄。因為新增計算結點後,這個使用者的分擔策略可能調整到了新結點,但是前5條訊息已經在老結點上執行了。。。這裡需要根據項目自己的特點設計出符合自己的方案。這裡我還是再次推薦計算和資料分離,而彈性的過程也要與業務特點解耦,摻雜了過多的商務邏輯的彈性過程,是很痛苦的,也難以維護。
另外,監控決策是需要時間的。如果業務量激增,可能監控來不及反應系統就沖死了。還是應該有一定的提前預判,由人工來提前擴容。同時,系統的業務忙閑一般是呈規律性的,隨著系統的進步,決策系統要增加一些自學習的能力。
五、業務鏈
假設一個業務進入系統先交給A業務單元,執行完再交給B,C,... 姑且把ABC叫這個業務的執行鏈。業務鏈不應該長,應該盡量短(當然有時系統成形後就身不由己了)。在業務鏈的每個環節,都會存在一次負載平衡選擇。這都會引起很多思考。應該把業務單元做的內聚。
同時我也不是主張盡量減少業務單元的類型,把ABCD類型的業務單元捏成一個。不同的業務類型單元需要不同的資料,有不同的Auto Scaling需求,應該分開。
業務鏈上的結點之間應該送耦合,盡量不需要知道上下遊的標識。
六、系統營運監控
主要指整個系統業務運行情況的監控。如各種統計,Log日誌,信令跟蹤,失敗資訊,警示等等。
從兩個層面來講:
在系統層面,希望將業務統計在各個業務單元之間聯絡起來。比如一條業務經過的業務單元,從中窺測分發情況、執行情況等等。這些東西在分析系統問題時很重要。
另一個是代碼層面,各種統計最好是非入侵性的,散落在代碼各處的統計點對維護來說很難。
分布式系統總結