ITDSD- 4.分佈式軟件的定量分析

介紹

這是關於分佈式架構新手入門的第五篇文章。這一篇文章主要介紹通過計算分佈式系統中的單次請求成功率,以及重複請求的穩定率獲得系統的穩定性估值。依據軟件結構評估性能及其冗餘。通過對系統的分析判斷出潛在的性能瓶頸。爲設計分佈式系統提供數據支持。

您可以點擊以下鏈接找到前面四篇文章。

  1. Distributed Method of Web Services
  2. ITDSD - 1. Splitting in Microservice Architecture
  3. ITDSD - 2. Practice of Splitting in Microservice Architecture
  4. ITDSD - 3. Overview of Distributed Software Engineering

有共享數據的網絡必然是異步網絡

當多個任務試圖共同使用一個數據時。任務通常需要排隊輪流使用這個數據。因爲同時使用數據會造成數據損壞,通常爲每個任務分別修改了數據的一部分導致數據整體損壞。這種多個任務對一個數據不可同時運行的情況稱爲數據的原子性。這時的數據在多個任務之間是負有一致性功能的協議,因而在多個任務運行關係中具有無法替代的作用。而對數據的輪流使用保證了任務之間通過數據地址進行的信息交換。異步模型和同步模型描述了在使用數據時任務的執行狀態。例如一個任務正在使用數據而另一個任務在等待。則等待的任務被稱爲同步執行。如圖1。

在分佈式環境下客戶端和服務器通過消息觸發相關任務的執行。客戶端的任務發送請求觸發服務器的任務被執行。通常在服務器執行請求並返回前客戶端會阻塞任務的執行等待返回。客戶端的阻塞保證了客戶端的狀態在服務端返回前不會發生變化。這樣服務端返回後可以繼續當前客戶端的處理。我們稱這時客戶端是同步執行請求。而服務器是異步執行請求。因爲服務處理完這個請求後不會阻塞,並等待客戶端其他的指令。這樣保證了服務可以依次處理其他的客戶端請求。按連接等待還是按處理請求等待是同步和異步的重要區別。如圖2。

爲了證明由具有共享數據的單線程服務器組成的網絡必然是異步網絡。首先假設客戶端和服務器創建鏈接後都使用同步方式,並且能與其他客戶端共享數據。即任意方處理完消息後都阻塞等待對方發送新的消息。這樣的鏈接方式稱爲完全同步模式。在完全同步模式下,只要客戶端保持鏈接,則服務器就不能處理其他的客戶端請求。假設客戶端的鏈接時間爲無窮大時則服務器被佔用的時間也爲無窮大。那麼服務器也就在無窮大的時間內無法處理其他的客戶端請求。如圖3所示。

則服務器必然在無窮大的時間裏無法與其他客戶端共享數據。這與我們的假設相互矛盾。所以我們得到了定理1。

定理1,由共享數據的單線程服務器組成的網絡必然是異步網絡。

有共享數據的異步網絡的特點就是基於延遲時間t的一致性。所謂延遲時間t的一致性是指,任意獲得信息的一方所獲得信息都是經過了延遲時間t之後的信息。或者說任何接收端所獲得的信息都是發送端在時間t之前的信息。信息的發送一方並不保證在這段時間中信息是否會發生改變。延遲時間t是基於能量守恆而得到的推論。因爲服務器硬件是遵守能量守恆定律。所以在服務器硬件上任何信息的傳輸也遵守能量守恆定律。所以我們得到了推理1。

推理1,任意兩點間的信息同步都會存在延遲時間t。

推理1表明了任意點拿到的數據都是名義上較舊的數據。例如用戶在服務器上查詢到的比賽分數。用戶在看到數據時服務端可能已經被更新成不一樣的分數了。如果在爲了保證用戶所看到的數據在其使用過程中保證一致。那麼就是要鎖住服務器也就是使鏈接變爲同步模式。由定理1得知同步模式下的網絡不能共享數據。推理1也表明了信息的傳遞是有方向性的。這種傳遞會觸發任務的執行,進而產生的信息也是有方向性的。順着這種方向性便產生了對分佈式網絡定量分析的基礎。因爲在任務執行的方向上,所涉及到的硬件和軟件構成了分佈式系統。

串行和併發的概率

當客戶端發送請求到分佈式系統後,分佈式系統會在一系列的服務器上執行請求。標記這些服務器爲1到n其中n爲任意整數。假設每個服務器都有一個出現錯誤的概率。這個錯誤包括硬件的宕機,軟件的崩潰等。我們將這個出現錯誤的概率記爲x1,則由概率公式得知多個服務器串行執行成功的概率爲x1*x2*x3…xn,我們得到了公式1。例如有一個任務請求,需要通過網關服務器,web服務器,內存數據庫和硬盤數據庫再返回給客戶端。假設這4個服務器運行正常的概率爲99%,90%,96%,96%則請求成功的概率爲0.99*0.9*0.96*0.96=0.82。

雖然單次的請求失敗的概率較高,但當用戶重複發起請求時由併發概率公式可以得知。獨立事件重複請求的成功概率爲1-((1-x1)*(1-x2)*(1-x3)…(1-xn)),我們得到公式2。計算兩次重複請求任意一次通過的概率爲,1-(1-0.82)*(1-0.82)=0.97,所以這次重複請求讓概率提高了約15個百分點。可見重複請求的成功率提升,抵消了系統串行執行的成功率下降。雖然與數學上冪等的概念很相似。但依據定理1分佈式系統是一個動態變化的系統,所以兩次請求從結果還是過程來看都是分別獨立的。

當一個系統是由多個連續的請求和併發的請求組成的複雜的系統時。例如一個由3臺s1,s2,s3服務器組成的系統。其請求成功的概率分別爲90%, 95%, 99%。運行着有3個r1,r2,r3請求的軟件系統。其中r1調用服務器s1,s3記爲r1(s1,s3)。其他的兩個請求分別爲r2(s1,s2,s3),r3(s2,s3)。那麼我們可以分別得到 r1,r2,r3的成功概率爲r1(0.9*0.99)=0.89,r2(0.9*0.95*0.99)=0.85,r3(0.95*0.99)=0.94,則系統運行概率爲1-((1-0.89)*(1-0.85)*(1-0.94))=99.9%。也就是說系統所有服務都停止響應的概率爲0.1%。如圖4所示。

內存數據庫和硬盤數據庫的特性

雖然連續請求提高系統響應的概率,但系統的整體穩定性並不取決於響應成功的概率。因爲如果數據庫無法使用則會造成數據丟失。數據丟失會使系統徹底喪失服務能力。假設一個系統內只有內存數據庫而沒有硬盤數據庫。則內存數據庫運行正常的概率爲96%。一旦內存數據庫運行失敗導致數據丟失則系統徹底喪失運行能力。所以系統整體的穩定性的上限就爲96%。內存數據庫就如同木桶中最短的那個板子一樣。決定了系統整體穩定性的低點。

因爲硬盤數據庫可以在服務重起後仍然保證一定時間的數據不丟失。所以硬盤數據庫成爲系統穩定的上限。只要硬盤不損壞到無法使用導致數據丟失,即使系統重起也不會導致系統無法使用。在一份由數據備份廠商backblaze提供的硬盤故障率報告[1]中指出。其使用最多的硬盤故障率爲2.22%。可以通過使用硬盤陣列RAID0,在雙硬盤備份時的數據丟失率爲0.05%。並且可以通過更多備份進一步降低數據丟失的概率。那麼系統在使用硬盤數據庫後其穩定性將大幅提升。

雖然內存數據庫遠沒有硬盤數據庫穩定。但內存數據庫運行度要遠快於硬盤數據庫。隨機讀取可以達到千倍的差距,而順序讀寫也有10倍左右的差距。由穩定性排序由最高到最低依次爲硬盤數據庫,內存數據庫和服務容器。而從響應速度來看由最快到最慢依次爲服務容器,內存數據庫和硬盤數據庫。響應速度指對用戶發起的請求做出的迴應。如果服務容器不使用內存數據庫和硬盤數據庫則處理速度是最快的。因爲處理請求的響應較快所以支持的併發量是最高。當然這裏的穩定性是相對的,即使是穩定最差的服務器容器。正在開發過程的服務容器會頻繁的人爲更新。任何更新的行爲都會導致潛在停機的可能。管理得當的服務容器可以保證95%以上的平穩運行。考慮因爲任何硬件都有1%到5%損壞的可能。軟件穩定率已經非常接近硬件穩定率。所以內存數據庫更多的是充當臨時數據備份的功能。在更換服務容器期間保存數據使用。

二義性

當在分佈式系統中存有多個數據時,例如內存數據庫和硬盤數據庫都同時存有用戶賬戶信息稱爲數據的二義性。由推論1得知這種二義性存在着延遲時間t的一致性。分佈式系統中的二義性會帶來無法調和的數據錯誤。假設有如下系統,在服務器容器接受用戶數據並返回,並將數據依次傳播到內存數據庫和硬盤數據庫。如圖5所示。

假設在傳播的過程中寫入硬盤數據庫失敗,而這時已經返回給用戶操作成功。當用戶下線退出,內存數據庫被刪除。用戶再次上線時就會發現數據丟失。這是用戶返回和實際存儲發生了二義性。

另一種可能是寫入硬盤數據庫成功,寫入內存數據庫失敗。用戶查詢數據始終是錯誤的,導致用戶反覆操作進一步擴大了錯誤的影響。

在由服務容器向內存數據庫和硬盤數據庫傳播的過程中。因爲延遲時間t的存在,在這段時間內發生錯誤導致有的設備寫入成功,有的設備寫入失敗時就產生了二義性。因爲是異步系統在寫入的過程中可能還伴隨着其他的異步操作。導致刪除錯誤操作變得極爲困難。這種分佈式中的二義性錯誤是因爲我們試圖改變延遲時間t的一致性的傳播方向引起的。原本的傳播方向是服務容器到內存數據庫到硬盤數據庫。而我們試圖使用內存數據庫或硬盤數據庫的數據來恢復服務器容器的錯誤。這中間的延遲時間t和分佈式的可用概率必然會產生數據錯誤的風險。高性能伴隨着較高的風險,高穩定伴隨着較低的風險。唯有風險是無法被徹底消除的。

通過將系統進行分佈式可以進一步降低系統的風險。例如將多個系統拆分,分別處理不同的請求。如圖6。

這時我們得到了新的方法來處理系統的風險。由公式2得知對系統進行分佈式可以大幅降低系統整體無法使用的概率。那麼當我們系統風險較高需要較高性能時。如果爲分佈式結構那麼將大幅降低系統整體的風險。也就是受系統影響的用戶減少爲1/n其中n爲分佈式的數量。例如某個網站設計爲服務容器,內存數據庫和硬盤數據庫結構。某日推廣活動大量意外用戶涌入導致峯值的半小時中硬盤IO寫入堵塞。網站採用的是偏性能設計,忽略了硬盤數據庫寫入失敗。在半小時內除了用戶無法登陸外,已經登陸的用戶所有操作都沒有受到任何影響。事後分析如果擁堵時間超過1小時,內存數據庫數據將被清除,就會導致用戶這段時間內的操作丟失。受到擁堵影響的部分爲總共10部分的分佈式系統中的2部分。所以潛在可能操作丟失的用戶爲全部用戶的2/10。

在計算機系統內也存在基於延遲時間t的一致性進行傳播的過程。CPU內的緩存到內存再到硬盤就是一個傳播的過程。這個過程也有數據不一致的概率,只是時間極短導致其非常的低而已。如圖7。

AP-樹形結構的傳播

把數據從最開始被改變的地方向其他硬件進行傳播的過程稱爲AP方法或AP關係。因爲把數據單單隻放在一個硬件內會導致在這個硬件使用過程中其他硬件被阻塞的問題。這種傳播導致讀取數據並不是最新的也不是絕對一致的而是基於延遲時間t的一致性。所以在AP關係下傳播的數據不能用於具有原子關係的操作。也就是不能把AP網絡內的數據再反向寫入AP網絡。因爲延遲時間t的存在將會用較舊的數據覆蓋較新的數據。如圖8所示。

服務器的備份就可能導致這種舊數據覆蓋新數據的情況,當主服務器下線備用服務器上線時,備用服務器內較舊的數據疊加新的請求會導致數據混亂。例如一件商品主服務器記錄存貨爲0件,而備份服務器記錄還有1件。則備份服務器上線後就會導致用戶買到不存在的物品。

AP關係爲我們帶來了在幾乎任何情況下都不會被阻塞的訪問。並且可以利用樹形傳播的方式進行擴在。這種擴展帶來了近乎於無限的流量和硬件支持。在分佈式領域這是非常重要的設計方法。其被應用於內容分發,DNS,ZooKeeper等重要的分佈式工具中。其分發的形式也多種多樣例如gossip,路由協議等。我們也可以使用阻塞的方法保證數據不受延遲時間t的影響。或者使用競爭的算法例如Bitcoin來消除延遲時間t的影響。

在ZooKeeper這個樹形發散的網絡裏分爲了讀取和寫入兩個不同的操作。對於讀取的成功概率可以直接使用公式2得出。而寫入的概率則分爲了不同的階段。對於最初的原點其寫入的概率就是原點可用的概率。當原點擴散到下一層後,其再次擴散成功的概率爲當前層所有節點使用公式2得出的概率。即任意節點擴散成功就認爲擴散的行爲還在繼續。可見在AP關係中寫入行爲一旦開始擴散,已經擴散成功的節點越多,成功完成全部擴散的概率就越高。並且讀取成功率更是高得驚人。如圖9所示

協議和數據

由定理1得知分佈式網絡是異步網絡下圍繞共享數據建設的。外部的請求到達網絡後要找到對應數據集,並觸發任務操作數據集合。當一個數據集合在分佈式網絡中有多個備份時。需要選擇一個數據集合進行寫入然後擴散到其他的數據備份中。而這個選擇被寫入的數據集合必須是在分佈式網絡中具有唯一性。否則就會產生數據的二義性。這個數據集合一旦被選定,多個所有關於這個數據集合的操作都會被固定下來。這個選定的點成爲了處理指定數據集合的硬件軟件交匯點。這個點就成爲了指定數據集合操作的協議。注意這裏已經不僅僅侷限於數據。當在分佈式系統中有多個數據備份時這個選定的協議必須是唯一的。也就是說分佈式系統是圍繞着數據協議展開建設的。這個協議的實體就是存儲着數據的硬件。沒有成爲協議的數據被稱爲備份數據或只讀數據。在備份數據或只讀數據上寫入是無效的。

當分佈式集羣中計算機依據計算產生結果數據集時這個數據就已經存在了。我們可能會在存入內存數據庫或硬盤數據庫之後才返回客戶端報告執行成功。但這個報告無論是否返回其實並不影響數據的穩定性。因爲硬盤也有丟失數據的情況,只是這個可能性比較低而已。數據由開始產生再擴散到其他硬件。其源頭也就是鏈接任務和數據的那個點稱爲協議。這個協議即是任務與任務之間的協議,也是任務和數據的協議。例如它可能被命名爲“用戶信息”的數據和註冊的任務。

既然稱爲協議它就是有方向性的。即任務處理完成到發佈爲寫入數據。寫入數據再通過AP關係在分佈式系統中擴散。如圖10

讀取和寫入對數據是兩種操作,但對於任務是執行的輸入和執行的輸出。所以寫入數據是判斷任務之間原子關係的重要依據。在異步網絡下任何任務在任意時間都會被執行,所以任意兩個任務之間有共同寫入的數據就構成了寫入衝突。也就是兩個任務構成了原子關係。

異步網絡下原子關係是個有趣的概念。例如我和妻子都喜歡吃牛排,那麼在任何情況下兩個人都可能使用做牛排的看煎鍋。所以對於看煎鍋的使用要進行排隊。否則可能就變成我有煎鍋需要牛肉,妻子有牛肉需要煎鍋,誰也不能做牛排的尷尬。所以每次想做牛排的時候都要去檢查日曆,看看煎鍋是否被佔用。而實際情況是一年來我都沒有做過牛排,煎鍋一直被妻子使用。這個例子揭示了潛在的衝突和發生的頻次有關。頻次較低的情況,衝突發生的概率較低。如果假定這個煎鍋是我們社區唯一的煎鍋。任何社區的居民製作牛排都只能使用這個煎鍋。那麼我想才比較符合異步網絡下對於原子關係的定義。我和所有的鄰居都構成了對於煎鍋的原子關係。

分佈式系統設計中的性能分析

在只有一臺服務器容器和一臺硬盤數據庫的小型系統裏。一個請求的完成,從服務容器到數據庫,要經過(a)服務軟件,(b)服務器容器,(c)網絡鏈接,(d)數據庫軟件,(e)硬盤。哪麼請求成功的概率爲(a)*(b)*(c)*(d)*(e)=f。如果直接將數據存入硬盤則請求要經過(a)服務軟件,(b)服務器容器,(e)硬盤則請求成功的概率爲(a)*(b)*(e)=g。因爲0<(c)*(d)<1所以f<g,所以一臺服務容器和一臺硬盤數據庫的小型系統請求成功率小於單獨的服務容器。因爲系統可以無限制的重試提高請求成功率。所以系統的整體穩定性取決於硬盤的穩定性。f和g都使用了硬盤所以整體穩定性相同。當有多個服務容器共同使用中心數據庫時。如圖11所示。

在之前我用社區共享的煎鍋做了例子。假設其中一個服務容器正在使用煎鍋那麼另一個請求煎鍋的服務容器將會等待。那麼這個並行系統就退化爲串行系統。系統將遵守Amdahl定律。即系統並行化的部分性能得到了提高,而串行化的部分阻塞在數據庫。如果串行化導致數據庫處理性能下降影響了數據分發功能進而影響並行化處理能力,那麼將導致系統整體處理能力的下降。假設因爲串行化的佔用導致每個服務容器受到的影響相同爲x,則n個鏈接被佔用的時間爲x*x*x…x^n,即數據庫的串行化會導致整體處理能力成指數級別下降。出現的問題越多掉線或重試導致性能需求越大進而導致問題更嚴重。串行化的部分沒有得到很好的解決。例如鎖住表1請求表2和鎖住表2請求表1的兩個任務會形成死鎖。如圖12所示。指數曲線圖

在互聯網軟件系統中有80%的數據是非活躍數據。這些數據存儲在硬盤上並不需要計算。而20%的數據是當前需要計算的數據。硬盤數據庫定位是管理這80%的數據並且提供多維度的大數據分析功能。當數據因爲用戶使用被激活時需要調入服務容器進行處理。假設硬盤陣列有288T容量,那麼系統運行時需要56T的內存。單臺服務器無法提供這麼多的運行內存,所以系統需要分佈式服務器。

數據集中並被剝離的方式有助並行部分的分佈式。有助於分佈式系統內性能的優化,例如降低硬盤數據庫的計算能力。但對串行化的部分沒有任何幫助。其本質是軟件的AP化,即數據的可用性和協議性。如圖11所示,數據的可用性的提高對分佈式的性能的提升是有限的。提升到一定的程度就會受限於串行化部分。因爲在這個系統的串行部分都高度集中在數據庫。即使是兩個不互相影響的串行化也都必須在數據庫完成。因爲數據庫無法知道軟件系統如何使用數據並建立原子關係。對於數據庫來說任何表之間都有可能串行化。因爲對無限可能的準備,即任意表都可能串行。數據庫只有把所有表都集中放在一起。這種集中導致了數據庫承擔的功能無法被分解。因爲串行化的部分,必須放在單一線程內保證處理的原子性。這點Amdahl定律已經證實了。軟件中可並行的部分可以使用儘可能多的計算能力來承載訪問壓力。也就是並行部分的性能和所提供的硬件數量是線性關係。而串行部分只能在一個單獨的服務容器內運行。所以串行部分無法因爲硬件的增加而提高性能。所以串行部分的性能在系統內將是一個固定值。例如上個例子中的中心數據庫,因爲整個系統的串行部分都在數據庫中執行。那麼串行部分的計算需求的和其服務容器的計算能力的比值就是整個分佈式系統的性能比率。例如中央數據庫的當前CPU的使用率爲50%,因爲所有串行操作都在中央數據庫,所以就相當於整個分佈式系統的計算能力已經使用50%。

假如我們有兩個中心數據庫來處理串行化的部分。其中一臺CPU使用率爲100%另一臺爲50%那麼我們整體使用率是否爲75%呢?顯然不是,因爲100%的服務器有大量潛在計算需求無法處理瀕臨崩潰。如果小於100%可以近似的認爲需求得到滿足,如果任意服務器已經大於100%則超出了正常使用範圍。

可見在分佈式系統中決定系統性能的是串行部分,也就是具有原子關係的部分。也就是在RP方法中有讀寫或只寫數據的任務。串行部分也不是完整不可分割的,依據寫入數據的不同可以進行分割。考慮有兩個Amdahl的系統運行在同一組硬件內。

那麼其兩個串行部分放在同一個硬件內就會導致整體性能較低,而拆開放在兩個不同的硬件內就會提高整體性能。一個複雜的軟件系統可能存在多個Amdahl系統。找到這些Amdahl系統並將其各自放到獨立硬件中就可以大幅提高分佈式系統處理上限。RP方法就是爲了找到這些隱藏的Amdahl系統。從根本上提高分佈式系統的處理能力的上限。

當我們找到所有軟件系統內隱藏的Amdahl系統後,就可以依據Amdahl系統的數量乘以使用的硬件得出分佈式系統的可承載能力的上限。例如我們有2個Amdahl系統分別爲支付和購買,每個系統的單用戶請求需要大約0.001秒進行處理。那麼將這兩個Amdahl系統放入分別放入兩臺服務器中。則支付和購買的用戶沒秒併發的上限爲2000人。

結論

軟件系統是由可並行部分和串行部分組成。串行部分又有多個串行部分組成。按Adam定理,並行部分的性能與硬件數量成正比。串行部分與硬件性能成正比。因爲串行部分通常只佔軟件系統全部的20%,所以通常分佈式系統只是解決了80%的並行部分。再疊加80%的軟件系統並不會有高強度的併發訪問。這樣分佈式系統大約只有4%的部分是涉及高強度的訪問。並且只有非常少數的頂級公司會關注這4%的串行問題。所以串行問題可能帶來的各種問題常常被人們忽略。甚至這些串行問題被簡單的當成了系統bug。並不是說一般的公司和系統不需要分佈式系統。因爲不出問題只是概率上較低而已。一旦出現問題對公司的技術團隊將是致命的打擊。技術人員應當關注任何可能出現的系統缺陷。

在下一章中我將用網上商場的網站舉例如何創建一個分佈式系統。如何在分片,緩存,硬盤之間做到平衡。

引用

1https://www.backblaze.com/blog/backblaze-hard-drive-stats-q1-2019/

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