可能是講分佈式系統最到位的一篇文章 原

  如果現在讓你闡述一下什麼是“分佈式系統”,你腦子裏第一下跳出來的是什麼?我想,此時可以用蘇東坡先生的一句詩,來形象地描述大家對分佈式系統的認識:

  橫看成嶺側成峯,遠近高低各不同。

  我覺得每個人腦子裏一下子涌現出來的肯定是非常具象的東西,就像下面這些:

  如果你一下子想到的是XX中心、XX服務,意味着你把服務化的模式(SOA、ESB、微服務)和分佈式系統錯誤地劃上了等號。

  那麼,什麼是“服務化”呢?服務化就像企業當中將相同崗位的人員劃分到同一個部門管理,以此來收斂特定的工作入口,再進行二次分配,以提高人員利用率和勞動成果的複用度。服務化的本質是“分治”,而“分治”的前提是先要拆,然後才談得上如何治。這時,高內聚、低耦合的思想在拆分過程中起到了一個非常重要的作用,因爲這可以儘可能地降低拆分後不同組件間進行協作的複雜度。所以重要的是“怎麼拆“,還有如何循序漸進地拆,而這個過程中你究竟是採用了何種服務化模式(比如SOA、ESB、微服務等)並不是關鍵。

  爲什麼說“怎麼拆”最重要呢?我來舉個例子,企業的組織架構包括三種模型:職能型、項目型、矩陣型。你可以把這裏的企業理解爲一個“分佈式系統”,把後面的3種模型理解爲這個分佈式系統的3種形態。作爲這個“系統”的所有人,你需要考慮如何拆分它,才能使得各功能組件相互之間可以更好地協作。假設,你要將一個總計10000名員工的企業按“職能型”拆分成20個部門,得到的結果是每個部門500人。

  這時,如果工作是流水線式的上下游關係。一個部門完工了再交給下一個部門。

  af32062abbf14de787fdbd3245a8446a.jpeg

  那麼這時候是高內聚、低耦合的。因爲一個工種只與另一個工種產生了關聯,並且僅有一次。

  但如果工作需要頻繁的由不同職能的人員同時進行,會導致同一個部門可能與多個部門產生聯繫。

  可能是講分佈式系統最到位的一篇文章

  那麼,這時是低內聚、高耦合的。因爲一個工種需要和其他多個工種產生關聯並且遠不止一次。

  可以看到服務化體現了“分治”的效果,這也是分佈式系統的核心思想,因此從“分治”這個本質上來看,服務化的確是分佈式系統,但分佈式系統不僅僅停留在那些服務化的模式上。

  我相信,你在工作中參與開發的任何軟件系統,到處都存在着需要拆分的地方,除非它的功能極簡到只需要計算一個1+1。比如,當我們在電商平臺點擊“提交訂單”的時候,會涉及生成訂單、扣除積分、扣除庫存等等動作。電商系統初期所有的功能可能都在一個系統裏面,那麼這些操作可以寫在一個方法體裏嗎?我想只要代碼能夠成功運行,大部分人是不會管你怎麼寫的。但是如果這時需要增加一個紅包功能呢?相信你或多或少遇到過在幾百上千行代碼中去增改功能的事情,其中的痛苦應該深有體會。

  要解決這個問題就是要做拆分,通過梳理、歸類,將不同的緊密相關的部分收斂到一個獨立的邏輯體中,這個邏輯體可以是函數、類以及命名空間,等等。所以,從這個角度來說“分治”的問題其實早就存在我們的工作中,就看我們是否有去關注它了。因此,這並不只是我們在進行服務化時才需要考慮的問題。

  那麼如何才能做好這個事情,更好的拆分能力正是我們需要掌握的。如果只是因爲看到其他人這麼拆,我也這麼拆,根據“二八原則”,或許“依樣畫葫蘆”可以達到80%的契合度,但是往往那剩下的20%會是耗費我們80%精力的“大麻煩”。要知道,只有掌握了核心主旨,才能更快地找到最理想的高內聚、低耦合方案。

  “分佈式系統”是各種中間件嗎?

  又或許,聽到分佈式系統,你想到了某某MQ框架、某某RPC框架、某某DAL框架,把運用中間件和分佈式系統錯誤地劃上了等號。

  這裏需要搞清楚的是,中間件起到的是標準化的作用。中間件只是承載這些標準化想法的介質、工具,可以起到引導和約束的效果,以此起到大大降低系統複雜度和協作成本的作用。我們來分別看一下:

  MQ框架標準化了不同應用程序間非實時異步通信的方式。

  RPC框架標準化了不同應用程序間實時通訊的方式。

  DAL(Data Access Layer,數據訪問層)框架標準化了應用程序和數據庫之間通訊的方式。

  所以,雖然分佈式系統中會運用中間件,但分佈式系統卻不僅僅停留在用了什麼中間件上。你需要清楚每一類中間件背後是對什麼進行了標準化,它的目的是什麼,帶來了哪些副作用,等等。只有如此,你才能真正識別不同技術框架之間的區別,找到真正適合當前系統的技術框架。

  那麼標準是拍腦袋決定的嗎?肯定不是,正如前面所說每一次標準化都是有目的的,需要產生價值。比如,大部分中間件都具備這樣一個價值:

  爲了在軟件系統的迭代過程中,避免將精力過多地花費在某個子功能下衆多差異不大的選項中。

  在現實中,這點更多時候出現在技術層面的中間件裏,比如,數據庫訪問框架的作用是爲了標準化操作不同數據庫的差異,使得上層應用程序不用糾結於該怎麼與mysql交互或者該怎麼與SQL SERVER交互。因爲與業務相比,技術層面“穩定”多了,所以做標準化更有價值,更能獲得長期收益。但“穩定”是相對的,哪怕單純在業務層面也存在相對穩定的部分。

  比如,你可以想象一下“盛飯”的場景,在大多數情況下其中相對穩定的是什麼,不穩定的是什麼。想完之後看下面的示例。

  ...
  基類:人
  繼承基類的子類:男人、女人
  基類:碗
  繼承基類的子類:大碗、小碗、湯碗
  基類:勺子
  繼承基類的子類:鐵勺、陶瓷勺、塑料勺
  function盛飯(參數人,參數碗,參數勺子){
  do人拿起碗
  do人拿起勺子
  do人用勺子舀起飯
  do人把勺子放到碗的上方並倒下
  }
  ...

  從這個示例裏我們發現,不穩定的部分都已經成爲變量了,那麼剩下的這個方法體起到的作用和前面提到的中間件是一樣的,它標準化,標準化了盛飯的過程。所以識別相對穩定的部分是什麼,如何把它們提煉出來,並且圍繞這些點進行標準化,纔是我們需要掌握的能力。而鍛鍊這個能力和需要這個能力的地方同樣並不侷限於分佈式系統。

  列舉這些現象只是想說,我們在認知一個分佈式系統的時候,內在勝於表象,掌握一個紮實的理論基本功更爲重要。而且,這些訓練場無處不在。

  海市蜃樓般的“分佈式系統”

  我相信,自從進入移動時代以來,各種高大上的系統架構圖越來越頻繁地出現,你的眼前充斥着各種主流、非主流的眼花繚亂的技術框架。你不由得肅然起敬一番,心中吶喊着:“對,這就是我想去的地方,我想參與甚至實現一個這樣牛逼的分佈式系統,再也不想每天只是增刪改查了。”

  得不到的事物總是美好的,但往往我們也會過度地高估它的美好。與此類似,高大上的架構圖背後呈現的系統的確也是一個成熟分佈式系統的樣貌,但我們要清楚一點:羅馬不是一日建成的。

  而且,“分佈式”這個詞只是意味着形態上是散列狀的,而“一分爲二”和“一分爲N”本質上並沒有區別。所以,很多小項目或者大型項目的初期所搭配的基礎套餐“單程序+單數據庫”,同樣可以理解爲分佈式系統,其中遇到的問題很多同樣也存在於成熟的分佈式系統中。

  想象一下,下面的場景是否在“單程序+單數據庫”項目中出現過?

 

  •   log記錄執行成功,但是數據庫的數據沒發生變化;

  •   進程內的緩存數據更新了,但是數據庫更新失敗了。

 

  這裏我們停頓30秒,思考一下爲什麼會出現這些問題?

  這裏需要我們先思考一下“軟件”是什麼。軟件的本質是一套代碼,而代碼只是一段文字,除了提供文字所表述的信息之外,本身無法“動”起來。但是,想讓它“動”起來,使其能夠完成一件我們指定的事情,前提是需要一個宿主來給予它生命。這個宿主就是計算機,它可以讓代碼變成一連串可執行的“動作”,然後通過數據這個“燃料”的觸發,“動”起來。這個持續的活動過程,又被描述爲一個運行中的“進程”。

  那麼除了我們開發的系統是軟件,數據庫也是軟件,前者負責運算,後者負責存儲運算後的結果(也可稱爲“狀態”),分工協作。

  所以,“單程序+單數據庫”爲什麼也是分佈式系統這個問題就很明白了。因爲我們所編寫的程序運行時所在的進程,和程序中使用到的數據庫所在的進程,並不是同一個。也因此導致了,讓這兩個進程(系統)完成各自的部分,而後最終完成一件完整的事,變得不再像由單個個體獨自完成這件事那麼簡單。這就如“兩人三足”遊戲一樣,如何儘可能地讓外部看起來像是一個整體、自然地前進。

  所以,我們可以這麼理解,涉及多個進程協作才能提供一個完整功能的系統就是“分佈式系統”。

  那麼再回到上面舉例的兩個場景,我們在思考“單程序+單數據庫”項目中遇到的這些問題背後的原因和解決它的過程時,與我們在一個成熟的分佈式系統中的遭遇是一樣的,例如數據一致性。當然,這只是分佈式系統核心概念的冰山一角。

  維基百科對“分佈式系統”的宏觀定義是這樣的:

  分佈式系統是一種其組件位於不同的聯網計算機上的系統,然後通過互相傳遞消息來進行通信和協調。爲了達到共同的目標,這些組件會相互作用。

  我們可以再以大小關係來解釋它:把需要進行大量計算的工程數據分割成小塊,由多臺計算機分別計算,然後將結果統一合併得出數據結論的科學。這本質上就是“分治”。而“單程序+單數據庫”組合的系統也包含了至少兩個進程,“麻雀雖小五臟俱全”,這也是“分佈式系統”。

  總結

  現在,我們搞清楚了,看待一個“分佈式系統”的時候,內在勝於表象。以及,只要涉及多個進程協作才能提供一個完整功能的系統,就是“分佈式系統”。

  我相信還有很多其他景象出現你的腦海中,但這大多數都是分佈式系統的本質產生的“化學反應”,進而形成的結果。如果停留在這些表象上,那麼我們最終將無法尋找到“分佈式系統”的本質,也就無法得到真正的“道”,更不會真正具備駕馭這些形態各異的“分佈式系統”的能力。

  所以,希望你在學習分佈式系統的時候,不要因追逐“術”而丟了“道”。沒有“道”只有“術”是空殼,最終會走火入魔,學得越多,會越混亂,到處都是矛盾和疑惑。

  因此,我們這個系列除了教給你在具體場景下的最佳實踐,還會和你講解爲什麼這樣做,以及該如何去權衡不同方案。不會過多的講述具體的技術框架,大部分內容圍繞理論展開,欲使每個人能夠掌握好這些分佈式中的基礎理論和思路,修煉好自己的內功。

  我將在後續的文章中,以一個項目的初期到成熟期作爲路線圖,帶領你循序漸進地深入到分佈式系統中,層層遞進地去剝開它的本質,並且圍繞這個本質去思考(是什麼問題,有哪些方式可以解決,什麼時候該用何種種方式等等),讓你知其然且知其所以然,形成一套完整的知識體系,完成核心“骨架”的塑造。而在此之後,你自己在課外學習時,就可以去填充“血肉”部分,逐漸豐滿自己。未來,大家的區別就在於胖一點和瘦一點,但只要能很好地完成工作,胖瘦又有何影響?

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