摘要:什麼是分佈式系統?爲何要用分佈式系統?分佈式系統如何分佈?這些你知道嗎?
分佈式系統是一個古老而寬泛的話題,而近幾年由於 「大數據」 概念的興起,又煥發出了新的青春與活力。本文將會經過對以下幾個問題展開談一下分佈式系統:git
什麼是分佈式系統?算法
爲何要用分佈式系統?sql
分佈式系統設計推演數據庫
CAP定理是什麼?segmentfault
分佈式系統如何進行分佈?安全
分佈式應用一般使用的架構類型哪些?服務器
分佈式系統的優缺點有哪些?網絡
簡單的來講,一個分佈式系統是一組計算機系統一塊兒工做,在終端用戶看來,就像一臺計算機在工做同樣。架構
這組一塊兒工做的計算機,擁有共享的狀態,他們同時運行,獨立機器的故障不會影響整個系統的正常運行。異步
咱們如今舉個例子,傳統的數據庫是存儲在一臺機器的文件系統上的。每當咱們取出或者插入信息的時候,咱們直接和那臺機器進行交互。
那麼如今咱們把這個傳統的數據庫設計成分佈式數據庫。假設咱們使用了三臺機器來構建這臺分佈式數據庫,咱們追求的結果是,在機器1上插入一條記錄,須要在機器3上能夠返回那條記錄,固然了,機器1和2也要可以返回這條記錄。
管理分佈式系統是一個很是複雜的話題,裏面充滿了陷阱和地雷。部署維護和調試分佈式系統也是很是頭疼的一件事情,那爲何還要去作呢?
分佈式系統最大的好處就是可以讓你橫向的擴展系統。
之前面提到的單一數據庫爲例,可以處理更多流量的惟一方式就是升級數據庫運行的硬件,這就是縱向擴展。
而縱向擴展的是有侷限性的。當到了必定程度之後,咱們會發現即便最好的硬件,也不可以知足當前流量的需求。
橫向擴展是指經過增長更多的機器來提高整個系統的性能,而不是靠升級單臺計算機的硬件。
從價格上來講,橫向擴展相比縱向擴展更容易控制。
最根本的問題是縱向擴展有很強的侷限性,達到最新硬件的能力之後,仍是沒法知足中等或者大型工做負載的技術要求。
橫向擴展則沒有這個限制,它沒有上限,每當性能降低的時候,你就須要增長一臺機器,這樣理論上講能夠達到無限大的工做負載支持。
除此以外,在容錯和低延遲上也有不少優點。容錯性是指你的分佈式系統的某個節點出現錯誤之後,並不會致使整個系統的癱瘓。而單機系統出錯之後,可能會致使整個系統的崩潰。
低延遲是經過在不一樣的物理位置部署不一樣的機器,經過就近獲取的原則下降訪問的延遲時間。
上面討論了分佈式系統的種種好處,可是咱們必需要清楚設計和運行分佈式系統並不是易事。
咱們先講一個場景,咱們現有的網絡應用變得愈來愈流行,服務的人數也愈來愈多,致使咱們的應用程序每秒收到的請求,遠遠超過可以正常處理的數量。這會致使應用程序性能降低明顯,用戶也會注意到這一點。
那咱們下面就來擴展一下咱們的應用程序來知足更高的要求。通常來講咱們讀取信息的頻率要遠遠超過插入或者修改的頻率。
下面咱們使用主從複製策略來實現擴展系統。咱們能夠建立兩個新的數據庫服務器,他們與主服務器同步。用戶業務對這兩個新的數據庫只能讀取。每次當向主數據庫插入和修改信息時,都會異步的通知副本數據庫進行更新變化。
在這一步上咱們已經有了三倍於原來系統讀取數據的性能支持。可是這裏有一個問題,在數據庫事務的設計當中,咱們遵循ACID原則。可是在咱們同時對其餘兩個數據庫進行數據更新的時候,咱們有一個時間窗口失去了一致性原則。若是在這個時間窗口內對兩個新的數據庫進行查詢,可能查不到數據。這個時候若是同步這三個數據庫的數據,就會影響寫操做的性能。
這是咱們在設計分佈式系統的時候,不得不承受的一些代價。
上面的主從複製策略解決了用戶讀取性能方面的需求,可是當數據量達到必定程度,一臺機子上沒法存放的時候,咱們須要擴展寫操做性能。要解決這樣的問題,咱們可使用分區技術。分區技術是指根據特定的算法,好比用戶名a到z做爲不一樣的分區,分別指向不一樣的數據庫寫入,每一個寫入數據庫會有若干讀取的從數據庫進行同步提高讀取性能。
固然,這樣使得整套系統變得更加複雜。最重要的難點是分區算法。大家試想一下,若是c開頭的用戶名比其餘開頭的用戶名要多不少,這會致使c區的數據量很是龐大,相應地,對於c區的請求也會遠遠大於其餘區。此時c區成爲熱點。要避免熱點,須要對c區進行拆分。此時要進行共享數據就會變得很是昂貴,甚至可能致使停機。
若是一切都很理想,那咱們就擁有了 n倍的寫入流量,n是分區的數目。
固然這裏也存在一個陷阱,咱們進行數據分區之後,致使除了分區鍵之外的查詢都變得很是低效,尤爲是對於sql語句如join查詢就變得很是之糟糕,致使一些複雜的查詢根本沒法使用。
這裏有一個思考題:
如何選擇更好的分區策略算法?
這個定理是指一個分佈式系統不能同時具備一致性,可用性和分區容忍性。
一致性Consistency: 依次讀寫的是什麼就是什麼。
可用性Availability: 整個系統不會崩潰, 每一個非故障節點總會有一個相應。
分區容忍Partition tolerant: 儘管有分區,系統仍能繼續運行並保持其一致性和可用性。
對於任何分佈式系統來講,分區容忍是一個給定的條件,若是沒有這一點,就不可能作到一致性和可用性。試想若是兩個節點連接斷掉了,他們如何可以作到既可用又一致?
最後你只能選擇在網絡分區狀況下,你的系統要麼強一致,要麼高可用。
實踐代表大多數應用程序更看重可用性。這個考量的主要緣由是在不得不一樣步機器裏實現強於一致性是時,網絡延遲會成爲一個問題。
這類因素使得應用程序一般會選擇提供高可用性的解決方案。
此時採用的是最弱的一致性模型來解決的,這種模型保證了若是沒有對某個項目進行新的更新,最終對該項目的全部訪問都會返回最新的值。
這些系統提供了BASE屬性,這是相對於傳統數據庫的ACID來說的。 也就是( Basically available)基本上是可用的,系統總會返回一個響應。
( Soft state)軟狀態, 系統能夠隨着時間的推移而變化,甚至在沒有輸入的狀況下也能夠變化, 如保持最終的一致性的同步。
( Eventual consistency)最終的一致性, 在沒有輸入的狀況下,數據早晚會傳播到每個節點上,從而變得一致。
追求高可用的分佈式數據庫例子有Cassandra;看重強一致性的數據庫,有HBase, Redis, Zookeeper。
咱們來看一下分佈系統進行分佈的經常使用方式:
以哈希方式把不一樣的值進行哈希運算,映射到不一樣的機器或者節點上。這種方式在擴展的時候比較困難,由於數據分散在多個機器上很容易出現分佈不均的狀況,常見的哈希對象有ip,url,id等。
按數據範圍分佈,好比ID在1~100的在機器a上,ID在100~200的在機器b上,諸如此類。這種分佈方法數據比較均勻。若是某個節點處理能力有限,能夠直接分裂這個節點。
維護數據分佈的這些原數據,若是量很是大的話,可能會出現單點瓶頸。
所以必定要嚴格控制元數據量。
按數據量來分佈數據,是以較爲固定的大小將數據劃分爲若干的數據塊,再把不一樣的數據塊分佈到不一樣的服務器上。
以數據量來進行分佈的這些數據,也須要被記錄下來做爲元數據來管理。
當集羣規模很大時,元數據的量也會變大。
這種方式是指把數據給分散到多個服務器上。若是其中一臺出現問題,請求就會被轉到其餘服務器上。其原理是多個機器互爲副本,這是比較理想的實現負載分壓的方式。
一致性哈希。經過哈希域構造哈希環,在增長機器時,變更的是其附近的節點,分攤的是附近節點的壓力,其元數據的維護和按數量分佈的維護方式一致。
咱們如今來看一下使用以上方式進行分佈的例子:
GFS, HDFS: 按數據量分佈。
Map reduce: 按GFS數據分佈作本地化。
BigTable, HBase按數據範圍分佈。
Pnuts: 按哈希方式或者數據範圍分佈。
Dynamo, Cassndra: 按一致性哈希分佈。
Mola, Armor, BigPipe: 按哈希方式分佈。
Doris: 按哈希方式和按數據量分佈進行組合。
6.1 客戶端服務器
在這個類型中,分佈式系統架構有一個服務器做爲共享資源。好比打印機數據庫或者網絡服務器。它有多個客戶機,這些客戶機決定什麼時候使用共享資源,如何使用和顯示改變數據,並將其送回服務器,像git這樣的代碼倉,這是一個很好的例子。
6.2 三層架構
這種架構把系統分爲表現層,邏輯層和數據層,這簡化了應用程序的部署,大部分早期的網絡應用都是三層的。
6.3 多層架構
上面的三層架構是多層架構的一種特殊形式。
通常會把上面的三層進行更詳細的劃分,好比說以業務的形式進行分層。
6.4 點對點架構
在這種架構中,沒有專門的機器提供服務或管理網絡資源。而是將責任統一分配給全部的機器,成爲對等機,對等機既能夠做爲客戶機,也能夠做爲服務器。這種架構的例子,包括bittorrent和區塊鏈。
6.5 以數據庫爲中心
這種架構是指用一個共享的數據庫,使分佈式的各個節點在不須要任何形式直接通訊的狀況下,進行協同工做的架構。
7.1分佈式系統的優勢
7.2分佈式系統的缺點
最後談一下分佈式系統與集羣的關聯。個人觀點是這二者並非對立的。
由於分佈式系統是經過多個節點的集羣來完成一個任務,讓外界看起來是跟一套系統做爲一個總體打交道。
一套分佈式系統能夠有多個集羣,這些集羣能夠業務進行劃分,也能夠物理區域進行劃分。每個集羣能夠做爲這個分佈式系統的一個節點。
這些集羣節點組成的分佈式系統,又能夠做爲單個的節點與其餘的節點組成一個集羣。