深入理解分散式系統

架構師修行手冊發表於2023-03-30

來源:悟空聊架構


21世紀以來,大規模分散式系統、雲端計算和雲原生飛速發展,在短短20年間就成為各大企業資訊科技基礎架構的核心基石。

企業邁向分散式的根本原因包括:


  • 移動網際網路時代,各大企業每天都在和巨大的流量和爆炸性增長的資料打交道;

  • 摩爾定律的失效,使得提升單機效能會產生很高的成本,同時網路速度越來越快,意味著並行化程度只增不減;

  • 此外,許多應用都要求7×24小時可用,因停電或維護導致的服務不可用,變得越來越讓人難以接受;

  • 最後,經濟全球化也導致了企業必須構建分佈在多臺計算機甚至多個地理區域的系統。


相較於單體應用或單機系統,分散式應用或分散式系統具有高效能、高可用性、容錯性和可擴充套件性等優點。可見,未來所有的基礎架構都會是分散式的。

然而分散式系統是一個相當複雜的領域,需要處理各種各樣的異常,這些異常不僅難以排查和診斷,而且難以復現,這不是增加測試或採用DevOps就能解決的,有些異常是不可避免的,需要在軟體架構中做取捨。

因此,想要構建一個健壯的分散式系統,必須先學習相關的基礎知識,消化大量資訊。

儘管學習分散式系統最好的方式是閱讀大量的經典論文,但大部分關於分散式系統的資料,要麼艱深太晦澀,要麼散落在不計其數的學術論文中,對於初學分散式系統的從業者來說,門檻太高,學習曲線太陡峭;再加上相關知識點比較零散、不成體系,讓人覺得雲山霧罩、望而卻步。《深入理解分散式系統》一書便可以很好地解決該問題!


而分散式系統中一個很重要的知識點就是——分割槽。下面就根據《深入理解分散式系統》書中所述,詳細介紹分割槽的概念及水平分割槽演算法。



深入理解分散式系統
01


分散式系統帶來的主要好處之一是實現了可擴充套件性,使我們能夠儲存和處理比單臺機器所能容納的大得多的資料集。

實現可擴充套件性的主要方式之一是對資料進行分割槽(Partition)。

分割槽是指將一個資料集拆分為多個較小的資料集,同時將儲存和處理這些較小資料集的責任分配給分散式系統中的不同節點。資料分割槽後,我們就可以透過向系統中增加更多節點來增加系統可以儲存和處理的資料規模。分割槽增加了資料的可管理性、可用性和可擴充套件性。

分割槽分為垂直分割槽(Vertical Partitioning)和水平分割槽(Horizontal Partitioning),這兩種分割槽方式普遍認為起源於關係型資料庫,在設計資料庫架構時十分常見。

圖1展示了垂直分割槽和水平分割槽的區別。

深入理解分散式系統

圖1


  • 垂直分割槽是對錶的列進行拆分,將某些列的整列資料拆分到特定的分割槽,並放入不同的表中。垂直分割槽減小了表的寬度,每個分割槽都包含了其中的列對應的所有行。垂直分割槽也被稱為“行拆分(Row Splitting)”,因為表的每一行都按照其列進行拆分。例如,可以將不經常使用的列或者一個包含了大text型別或BLOB型別的列垂直分割槽,確保資料完整性的同時提高了訪問效能。值得一提的是,列式資料庫可以看作已經垂直分割槽的資料庫。

  • 水平分割槽是對錶的行進行拆分,將不同的行放入不同的表中,所有在表中定義的列在每個分割槽中都能找到,所以表的特性依然得以保留。舉個簡單的例子:一個包含十年訂單記錄的表可以水平拆分為十個不同的分割槽,每個分割槽包含其中一年的記錄(具體的分割槽方法我們會在後面詳細討論)。

列式資料庫(Column-Oriented DBMS或Columnar DBMS)也叫列存資料庫,是指以列為單位進行資料儲存架構的資料庫,主要適用於批次資料處理和即時查詢。與之相對應的是行式資料庫。一般來說,行式資料庫更適用於聯機事務處理(OLTP)這類頻繁處理事務的場景,列式資料庫更適用於聯機分析處理(OLAP)這類在海量資料中進行復雜查詢的場景。 

垂直分割槽和列相關,而一個表中的列是有限的,這就導致了垂直分割槽不能超過一定的限度,而水平分割槽則可以無限拆分。


另外,表中資料以行為單位不斷增長,而列的變動很少,因此,水平分割槽更常見。

在分散式系統領域,水平分割槽常稱為分片(Sharding)。

需要說明的是,很多圖書和文章會糾結分片和分割槽的具體區別,一種觀點認為,分片意味著資料分佈在多個節點上,而分割槽只是將單個儲存檔案拆分成多個小的檔案,並沒有跨物理節點儲存。由於本書重點討論的是分散式系統,因此無論是分割槽還是分片,本書都認為其資料分佈在不同物理機器上。

分片在不同系統中有著各種各樣的稱呼,MongoDB和Elasticsearch中稱為shard,HBase中稱為region,Bigtable中稱為tablet,Cassandra和Riak中稱為vnode。



深入理解分散式系統
02


水平分割槽演算法用來計算某個資料應該劃分到哪個分割槽上,不同的分割槽演算法有著不同的特性。本節我們將研究一些經典的分割槽演算法,討論每種演算法的優缺點。

為了方便討論,我們假設資料都是鍵值對(Key-Value)的組織形式,通常表示為

1. 範圍分割槽

範圍分割槽(Range Partitioning)是指根據指定的關鍵字將資料集拆分為若干連續的範圍,每個範圍儲存到一個單獨的節點上。用來分割槽的關鍵字也叫分割槽鍵。前面介紹的按年拆分表資料就是一個範圍分割槽的例子,對於2011年到2020年這十年的訂單記錄,以年為範圍,可以劃分為10個分割槽,然後將2011年的訂單記錄儲存到節點N1上,將2012年的訂單記錄儲存到節點N2上,以此類推。

圖A中的資料可以按年齡進行範圍分割槽,將資料劃分成如圖2所示的分割槽。

深入理解分散式系統

圖2

如何劃分範圍可以由管理員設定,或者由儲存系統自行劃分。通常會選擇額外的負載均衡節點或者系統中的一個節點來接收客戶端請求,然後根據範圍分割槽演算法,確定請求應該重定向(路由)到哪個節點或哪幾個節點。

範圍分割槽的主要優點有:


  • 實現起來相對簡單。

  • 能夠對用來進行範圍分割槽的關鍵字執行範圍查詢。

  • 當使用分割槽鍵進行範圍查詢的範圍較小且位於同一個節點時,效能良好。

  • 很容易透過修改範圍邊界增加或減少範圍資料,能夠簡單有效地調整範圍(重新分割槽),以平衡負載。


範圍分割槽的主要缺點有:


  • 無法使用分割槽鍵之外的其他關鍵字進行範圍查詢。

  • 當查詢的範圍較大且位於多個節點時,效能較差。

  • 可能產生資料分佈不均或請求流量不均的問題,導致某些資料的熱點現象,從而某些節點的負載會很高。例如,當我們將姓氏作為分割槽鍵時,某些姓氏的人非常多(比如姓李或者姓王),這會造成資料分佈不均。又例如前面的按年拆分訂單的例子,雖然資料分佈較為均衡,但根據日常生活習慣,最近一年的訂單查詢流量可能比前幾年的查詢流量加起來還要多,這就會造成請求流量不均。總的來說,一些節點可能需要儲存和處理更多的資料和請求,一般透過繼續拆分範圍分割槽來避免熱點問題。


使用範圍分割槽的分散式儲存系統有Google Bigtable、Apache HBase和PingCAP TiKV。範圍分割槽適合那些需要實現範圍查詢的系統。

2. 雜湊分割槽

雜湊分割槽(Hash Partitioning)的策略是將指定的關鍵字經過一個雜湊函式的計算,根據計算得到的值來決定該資料集的分割槽,如圖3所示。

深入理解分散式系統深入理解分散式系統

圖3

雜湊分割槽的優點是,資料的分佈幾乎是隨機的,所以分佈相對均勻,能夠在一定程度上避免熱點問題。

雜湊分割槽的缺點是:


  • 在不額外儲存資料的情況下,無法執行範圍查詢。

  • 在新增或刪除節點時,由於每個節點都需要一個相應的雜湊值,所以增加節點需要修改雜湊函式,這會導致許多現有的資料都要重新對映,引起資料大規模移動。並且在此期間,系統可能無法繼續工作。


3. 一致性雜湊

一致性雜湊(Consistent Hashing)是一種特殊的雜湊分割槽演算法,在分散式儲存系統中用來緩解雜湊分割槽增加或刪除節點時引起的大規模資料移動問題。

一致性雜湊演算法將整個雜湊值組織成一個抽象的圓環,稱為雜湊環(Hashing Ring)。雜湊函式的輸出值一般在0到INT_MAX(通常為232-1)之間,這些輸出值可以均勻地對映到雜湊環邊上。舉個例子,假設雜湊函式hash()的輸出值大於/等於0小於/等於11,那麼整個雜湊環看起來如圖4所示。

深入理解分散式系統

圖4

接下來將分散式系統的節點對映到圓環上。假設系統中有三個節點N1、N2和N3,系統管理員可以透過機器名稱或IP地址將節點對映到環上,假設節點分佈到雜湊環上,如圖5所示。

深入理解分散式系統

圖5

接著,將需要儲存的資料的關鍵字輸入雜湊函式,計算出雜湊值,根據雜湊值將資料對映到雜湊環上。假設此時要儲存三個鍵值對資料,它們的關鍵字分別為a、b和c,假設經過雜湊函式計算後的雜湊值分別為1、5和9,則資料對映到環上後如圖6所示。

深入理解分散式系統

圖6

那麼資料具體分割槽到哪個節點上呢?

在一致性雜湊演算法中,資料儲存在按照順時針方向遇到的第一個節點上。例如圖6中,關鍵字a順時針方向遇到的第一個節點是N2,所以a儲存在節點N2上;同理,關鍵字b儲存在節點N3上,關鍵字c儲存在節點N1上。資料分佈方法如圖7所示。

深入理解分散式系統

圖7

接下來我們繼續看一下,向叢集中新增一個節點會發生什麼。假設叢集此時要新增一個節點N4,並新增到如圖8所示的雜湊環位置。那麼,按照順時針計算的方法,原本儲存到節點N2上的關鍵字a將轉移到N4上,其他資料保持不動。

深入理解分散式系統

圖8

可見,相比於普通的雜湊分割槽新增或刪除節點時會導致大量對映失效,一致性雜湊很好地處理了這種情況。

對於新增一臺伺服器這種情況,受影響的僅僅是新節點在雜湊環上與相鄰的另一個節點之間的資料,其他資料並不會受到影響。例如圖8中,只有節點N2上的一部分資料會遷移到節點N4,而節點N1和N3上的資料不需要進行遷移。

一致性雜湊對於節點的增減只需要重新分配雜湊環上的一部分資料,改善了雜湊分割槽大規模遷移的缺點。此外,一致性雜湊也不需要修改雜湊函式,直接將新節點指定到雜湊環上的某個位置即可。相比簡單的雜湊分割槽,一致性雜湊有著更好的可擴充套件性和可管理性。

但是,一致性雜湊仍然有明顯的缺點,當系統節點太少時,還是容易產生資料分佈不均的問題。另外,一個較為嚴重的缺點是,當一個節點發生異常需要下線時,該節點的資料全部轉移到順時針方向的節點上,從而導致順時針方向節點儲存大量資料,大量負載會傾斜到該節點。

解決這個問題的方法是引入虛擬節點(Virtual Node),虛擬節點並不是真實的物理伺服器,虛擬節點是實際節點在雜湊環中的副本,一個物理節點不再只對應雜湊環上一個點,而是對應多個節點。我們假設一個物理節點要對映到雜湊環中的三個點,引入虛擬節點後的雜湊環如圖9所示。

深入理解分散式系統

圖9

可以很直觀地發現,虛擬節點越多,資料分佈就越均勻。當節點發生異常被迫下線時,資料會分攤給其餘的節點,避免某個節點獨自承擔儲存和處理資料的壓力。

如果系統中有不同配置、不同效能的機器,那麼虛擬節點也很有用。例如,系統中有一臺機器的效能是其他機器的兩倍,那麼我們可以讓這臺機器對映出兩倍於其他機器的節點數,讓它來承擔更多的負載。

不過,在不額外儲存資料的情況下,一致性雜湊依然無法高效地進行範圍查詢。任何範圍查詢都會傳送到多個節點上。


以上內容來源於《深入理解分散式系統》一書,作者唐偉志曾工作於騰訊微信事業部,在分散式系統方面有著深入的研究。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70027824/viewspace-2942558/,如需轉載,請註明出處,否則將追究法律責任。

相關文章