漫談分佈式系統

漫談分佈式系統

1.分佈式架構中的相關概念

2.分佈式架構的發展過程和歷史

3.分佈式架構的難點

====================================

一. 分佈式架構中的相關概念

1.集羣

小飯店原來只有一個廚師,切菜洗菜備料炒菜全乾。後來客人多了,廚房一個廚師忙不過來,又請了個廚師,兩個廚師都能炒一樣的菜,這兩個廚師的關係是集羣

2.分佈式

爲了讓廚師專心炒菜,把菜做到極致,又請了個配菜師負責切菜,備菜,備料,廚師和配菜師的關係是分佈式,一個配菜師也忙不過來了,又請了個配菜師,兩個配菜師關係是集羣

3.節點

節點是指一個可以獨立按照分佈式協議完成一組邏輯的程序個體。在具體的項目中,一個節點表示的是一個操作系統上的進程。

4.副本

副本(replica/copy)指在分佈式系統中爲數據或服務提供的冗餘。節點的數據丟失時,可以從副本上讀取到數據。數據副本是分佈式系統中解決數據丟失問題的唯一手段。服務副本表示多個節點提供相同的服務,通過主從關係來實現服務的高可用方案

5.中間件

中間件位於操作系統提供的服務之外,又不屬於應用,他是位於應用和系統層之間爲開發者方便的處理通信、輸入輸出的一類軟件,能夠讓用戶關心自己應用的部分。

二. 分佈式架構的發展過程和歷史

一個成熟的大型網站系統架構並不是一開始就設計的非常完美,也不是一開始就具備高性能、高可用、安全性等特性,而是隨着用戶量的增加、業務功能的擴展逐步完善演變過來的。在這個過程中,開發模式、技術架構等都會發生非常大的變化。而針對不同業務特徵的系統,會有各自的側重點,比如像淘寶這類的網站,要解決的是海量商品搜索、下單、支付等問題;像騰訊,要解決的是數億級別用戶的實時消息傳輸;百度所要解決的是海量數據的搜索。每一個種類的業務都有自己不同的系統架構。我們簡單模擬一個架構演變過程。我們以javaweb爲例,來搭建一個簡單的電商系統,從這個系統中來看系統的演變歷史;要注意的是,接下來的演示模型,關注的是數據量、訪問量提升,網站結構發生的變化,而不是具體關注業務功能點。其次,這個過程是爲了讓大家更好的瞭解網站演進過程中的一些問題和應對策略。假如我們系統具備以下功能:
用戶模塊:用戶註冊和管理
商品模塊:商品展示和管理
交易模塊:創建交易及支付結算

1.階段一:單應用架構

網站的初期也可以認爲是互聯網發展的早起,我們經常會在單機上跑我們所有的程序和軟件。把所有軟件和應用都部署在一臺機器上,這樣就完成一個簡單系統的搭建,這個時候的講究的是效率
在這裏插入圖片描述

2.階段二:應用服務器和數據庫服務器分離

隨着網站的上線,訪問量逐步上升,服務器的負載慢慢提高,在服務器還沒有超載的時候,我們應該做好規劃,提升網站的負載能力。假如代碼層面的優化已經沒辦法繼續提高,在不提高單臺機器的性能,增加機器是一個比較好的方式,投入產出比非常高。這個階段增加機器的主要目的是講web服務器和數據庫服務器拆分,這樣不僅提高了單機的負載能力,也提高了容災能力
在這裏插入圖片描述

3.階段三:應用服務器集羣-應用服務器負載告警

隨着訪問量的繼續增加,單臺應用服務器已經無法滿足需求。在假設數據庫服務器還沒有遇到性能問題的時候,我們可以增加應用服務器,通過應用服務器集羣將用戶請求分流到各個服務器中,從而繼續提升負載能力。此時多臺應用服務器之間沒有直接的交互,他們都是依賴數據庫各自對外提供服務
在這裏插入圖片描述
架構發展到這個階段,各種問題也會慢慢呈現

  1. 用戶請求由誰來轉發到具體的應用服務器
  2. 用戶如果每次訪問到的服務器不一樣,那麼如何維護

在這裏插入圖片描述

4.階段四:數據庫壓力變大,數據庫讀寫分離

構演變到這裏,並不是終點。上面我們把應用層的性能拉上來了,但是數據庫的負載也在慢慢增大,那麼怎麼去提高數據庫層面的負載呢?有了前面的思路以後,自然會想到增加服務器。但是假如我們單純的把數據庫一分爲二,然後對於後續數據庫的請求,分別負載到兩臺數據庫服務器上,那麼一定會造成數據庫不統一的問題。所以我們一般先考慮讀寫分離的方式
這個架構的變化會帶來幾個問題
1.主從數據庫之間的數據同步;可以使用mysql自帶的master-slave方式實現主從複製
2.對應數據源的選擇;採用第三方數據庫中間件,例如mycat
在這裏插入圖片描述

5.階段五:使用搜索引擎緩解讀庫的壓力

數據庫做讀庫的話,嚐嚐對模糊查找效率不是特別好,像電商類的網站,搜索是非常核心的功能,即便是做了讀寫分離,這個問題也不能有效解決。那麼這個時候就需要引入搜索引擎了使用搜索引擎能夠大大提高我們的查詢速度,但是同時也會帶來一些附加的問題,比如維護索引的構建。
在這裏插入圖片描述

6.階段六:引入緩存機制緩解數據庫的壓力

隨着訪問量的持續增加,逐漸出現許多用戶訪問統一部分內容的情況,對於這些熱點數據,沒必要每次都從數據庫去讀取,我們可以使用緩存技術,比如memcache、redis來作爲我們應用層的緩存;另外在某些場景下,比如我們對用戶的某些IP的訪問頻率做限制,那這個放內存中又不合適,放數據庫又太麻煩,這個時候可以使用Nosql的方式比如mongDB來代替傳統的關係型數據庫
在這裏插入圖片描述

7.階段七:數據庫的水平/垂直拆分

我們的網站演進的變化過程,交易、商品、用戶的數據都還在同一個數據庫中,儘管採取了增加緩存,讀寫分離的方式,但是隨着數據庫的壓力持續增加,數據庫的瓶頸仍然是個最大的問題。因此我們可以考慮對數據的垂直拆分和水平拆分
垂直拆分:把數據庫中不同業務數據拆分到不同的數據庫
水平拆分:把同一個表中的數據拆分到兩個甚至跟多的數據庫中,水平拆分的原因是某些業務數據量已經達到了單個數據庫的瓶頸,這時可以採取講表拆分到多個數據庫中
在這裏插入圖片描述

8.階段八:應用的拆分

隨着業務的發展,業務越來越多,應用的壓力越來越大。工程規模也越來越龐大。這個時候就可以考慮講應用拆分,按照領域模型講我們的用戶、商品、交易拆分成多個子系統
這樣拆分以後,可能會有一些相同的代碼,比如用戶操作,在商品和交易都需要查詢,所以會導致每個系統都會有用戶查詢訪問相關操作。這些相同的操作一定是要抽象出來,否則就會是一個坑。所以通過走服務化路線的方式來解決
那麼服務拆分以後,各個服務之間如何進行遠程通信呢?通過RPC技術,比較典型的有:webservice、hessian、http、RMI 等等前期通過這些技術能夠很好的解決各個服務之間通信問題,but,互聯網的發展是持續的,所以架構的演變和優化還在持續。
在這裏插入圖片描述

三. 分佈式架構的難點

1.三態

在集中式架構中,我們調用一個接口返回的結果只有兩種,成功或者失敗,但是在分佈式領域中,會出現“超時”這個狀態。

2.分佈式事務

是一個老生常談的問題,我們都知道事務就是一些列操作的原子性保證,在單機的情況下,我們能夠依靠本機的數據庫連接和組件輕易做到事務的控制,但是分佈式情況下,業務原子性操作很可能是跨服務的,這樣就導致了分佈式事務,例如A和B操作分別是不同服務下的同一個事務操作內的操作,A調用B,A如果可以清楚的知道B是否成功提交從而控制自身的提交還是回滾操作,但是在分佈式系統中調用會出現一個新狀態就是超時,就是A無法知道B是成功還是失敗,這個時候A 是提交本地事務還是回滾呢?其實這是一個很難的問題,如果強行保證事務一致性,可以採取分佈式鎖,但是那樣會增加系統複雜度而且會增大系統的開銷,而且事務跨越的服務越多,消耗的資源越大,性能越低,所以最好的解決方案就是避免分佈式事務。還有一種解決方案就是重試機制,但是重試如果不是查詢接口,必然涉及到數據庫的變更,如果第一次調用成功但是沒返回成功結果,那調用方第二次調用對調用方來說依然是重試,但是對於被調用方來說是重複調用,例如A向B轉賬,A-100,B + 100,這樣會導致A扣了100,而B增加200。這樣的結果不是我們期望的,因此需在要寫入的接口做冪等設計。多次調用和單次調用是一樣的效果。通常可以設置一個唯一鍵,在寫入的時候查詢是否已經存在,避免重複寫入。但是冪等設計的一個前提就是服務是高可用,否則無論怎麼重試都不能調用返回一個明確的結果調用方會一直等待,雖然可以限制重試的次數,但是這已經進入了異常狀態了,甚至到了極端情況還是需要人肉補償處理。其實根據CAP和BASE理論,不可能在高可用分佈式情況下做到一致性,一般都是最終一致性保證。

3.負載均衡

每個服務單獨部署,爲了達到高可用,每個服務至少是兩臺機器,因爲互聯網公司一般使用可靠性不是特別高的普通機器,長期運行宕機概率很高,所以兩臺機器能夠大大降低服務不可用的可能性,這正大型項目會採用十幾臺甚至上百臺來部署一個服務,這不僅是保證服務的高可用,更是提升服務的QPS,但是這樣又帶來一個問題,一個請求過來到底路由到哪臺機器?路由算法很多,有DNS路由,如果session在本機,還會根據用戶id或則cookie等信息路由到固定的機器,當然現在應用服務器爲了擴展的方便都會設計爲無狀態的,session會保存到專有的session服務器,所以不會涉及到拿不到session問題。那路由規則是隨機獲取麼?這是一個方法,但是據我所知,實際情況肯定比這個複雜,在一定範圍內隨機,但是在大的範圍也會分爲很多個域,例如如果爲了保證異地多活的多機房,誇機房調用的開銷太大,肯定會優先選擇同機房的服務,這個要參考具體的機器分佈來考慮。

4.一致性

數據被分散或者複製到不同的機器上,如何保證各臺主機之間的數據的一致性將成爲一個難點。

5.故障的獨立性

分佈式系統由多個節點組成,整個分佈式系統完全出問題的概率是存在的,但是在時間中出現更多的是某個節點出問題,其他節點都沒問題。這種情況下我們實現分佈式系統時需要考慮得更加全面些

:如果想對此進行深入研究的讀者,可以去買幾本相關的書籍,我有《20180520-大型網站系統與JAVA中間件實踐》PDF版,有需要的可以聯繫我。

發佈了25 篇原創文章 · 獲贊 30 · 訪問量 1143
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章