[譯] 論資料流的擴充套件性

Park-ma發表於2019-03-09

在分散式系統中,資料流是一種簡單但功能強大的儲存和共享資料的機制。說資料流簡單的原因之一是因為它們很容易擴充套件。無論是從縱向(增加計算機的容量)還是從橫向(增加計算機的數量),資料流都能很好的擴充套件。本次資料流的擴充套件性的教程中,我們將瞭解資料流縱向擴充套件性好的原因,以及在橫向擴充套件性上的選擇。常見的問題是,當資料流在橫向擴充套件時,對資料流的處理也可能要進行橫向的擴充套件,這將會影響資料流處理管道的設計。

縱向還是橫向擴充套件

為了避免讀者感到困惑,我這裡先對於縱向和橫向進行定義。縱向擴充套件是指你使用更強大的計算機來執行資料流的儲存和處理程式。縱向擴充套件有時也稱為向上擴充套件。你可以提高的包括磁碟的大小和速度、記憶體、CPU 的速度以及 CPU 的核心數量和顯示卡等裝置。

Vertical scaling - AKA scaling up to a more powerful computer.

橫向擴充套件指的是將工作分配給多臺計算機。因此,資料流中的資料會在多臺計算機之間分配,處理資料流的程式也會被分配 (至少它們可以被分配)橫向擴充套件有時也稱為向外擴充套件。你可以將一臺計算機的工作橫向擴充套件給多臺計算機

有兩種情況下可能需要橫向擴充套件:一、你得不到一個有更大記憶體和磁碟, 可以儲存和處理你的所有資料的計算機。二、有這樣的計算機,但是太貴買不起。

Horizontal scaling - AKA scaling out to multiple computers.

縱向擴充套件

上面已經提到了,縱向擴充套件意味著從配置低的計算機擴充套件到配置高的計算機。下面是傳統計算機體系結構的各個層次:

Computer architecture - vertical scaling.

資料離 CPU 越遠,CPU 訪問它的的速度就越慢。在上圖中,資料離最底層越近,CPU 訪問速度越慢。

上述計算機體系結構的每一層都經過了優化,以便序列讀取資料。這意味著,順序讀取位於磁碟上,RAM 或 L3、L2、L1 快取記憶體中的資料比讀取隨機分佈在磁碟、RAM 和快取記憶體的資料要快。將資料順序寫入磁碟也要比隨機寫入磁碟各個部分要快得多。

資料流完全是序列資料結構。它們連續地讀取,連續地寫入。這意味著,你可以在單臺計算機上面輕鬆的向上擴充套件資料流。寫入流的資料可以輕鬆的擴充套件到流檔案中。向檔案追加是寫入檔案的最快方式,相比之下,回到檔案開始的位置並重寫檔案相對要慢。

從檔案讀取時,一大塊資料被讀入到 RAM。RAM 中的資料會被存入快取,一小部分資料被讀取並存入到 L3 快取中,還有一小部分被讀取並存入到 L2 快取中,還有更小的一部分被讀取並存入到 L1 快取中,CPU 可以直接訪問 L1 快取並讀取這部分資料。因為你的資料分散在整個磁碟中,如果你需要將一小塊資料從磁碟讀取到 CPU 中,你需要先讀取一大塊資料到 RAM中,然後再進入 L3、L2和L1快取記憶體,那麼在讀取所需資料之前,這將會產生更多次數的資料讀取操作。當資料以序列方式位於一個大塊中時,磁碟、RAM、L3、L2 和 L1 快取記憶體讀取資料的速度要比隨機讀取快得多。原因很簡單,因為讀取次數少,每一次讀取的塊中都包含相關資料。

因為資料流的讀寫很好地利用了現代計算機,當你擴充套件計算機執行資料流服務時,資料流服務的效能也會線性地增長。

橫向擴充套件

之前也已經提到了,橫向擴充套件是將程式從一臺計算機擴充套件到多臺計算機。在資料流中,這意味著要將資料流中的訊息分發到多臺計算機。下面的圖描述了將資料流的訊息分發給多臺計算機的過程:

The messages of a data stream distributed onto multiple computers.

將資料流的訊息分發給多臺計算機也稱為對於資料流的分割槽

分割槽影響訊息序列的順序的一致性

對於資料流的分割槽會影響訊息序列的順序的一致性。在一臺計算機上,資料流的訊息的讀取和寫入的順序可以保證是相同的。一旦你對資料流進行了分割槽,我們就不能保證這個順序了。具體的分割槽方法決定了會以何種方式影響訊息序列的順序。

Round Robin 分割槽

Round Robin 分割槽是跨多臺計算機對資料流的訊息進行分割槽的最簡單的方法。Round Robin 分割槽只是在計算機之間均勻和順序地分發訊息。換句話說,1 號訊息儲存在 1 號計算機上,2 號訊息儲存在 2 號計算機上,以此類推。當所有的計算機都接收到訊息後,Round Robin 分割槽的方法再從 1 號計算機開始。

如果只有一個應用程式寫入資料流,使用 Round Robin 分割槽的方法是最簡單的。但是要是有多個程式同時執行就不好辦了。

當使用 Round Robin 分割槽機制時,對於流的讀取來說,按照流中劃分訊息之前的順序重新組裝流中的訊息是相當容易的。輸出流只需以輪詢排程方式從每一個分割槽讀取一條訊息。

基於欄位值分割槽

基於欄位值分割槽的原理是通過每個訊息的特定值將訊息分發給不同的計算機。通常,識別ID(例如主鍵值)作為分發訊息的欄位。計算每個欄位值的雜湊值,然後利用這個雜湊值將訊息對映到叢集的一臺計算機中。

當使用欄位值分割槽時,很可能會丟失整個訊息序列的順序。寫入同一臺計算機(同一分割槽)的訊息仍保持相互之間的順序,但是整個序列的順序可能會丟失,因為其他的計算機(其他分割槽)可能在它們之前被讀取。下圖就說明了這個問題:

Key based data stream partitioning may affect overall message sequence.

如果要獲得資料流分割槽的全部好處,就不能控制流處理器從不同分割槽讀取資料的順序。如果你還想擴充套件流處理器,那更不切實際。下圖就說明這個問題:

Key based data stream partitioning with stream processor partitioning too, will most likely affect overall message sequence.

在很多情況下,其實你並不需要完整的訊息序列的順序。你需要的可能是在資料流中相關訊息的訊息序列順序。例如,如果訊息表示對於客戶端更新,那麼將對於同一客戶端的更新訊息應該集中在叢集中的同一臺計算機(同一個分割槽)上。這樣,你就可以保證對於每一個客戶的更新順序,這對於你的程式來說已經足夠了。對於不同客戶端更新順序可能改變,但是對於同一邏輯實體(客戶端)的更新序列保持相同,對於不同邏輯實體的更新之間的序列的改變可能不一定是個問題。

對於訊息進行分割槽以便最後所有的相關訊息都會在同一臺伺服器上,這通常是通過對訊息主鍵上的資料進行分割槽完成的。這樣應該會保證同一邏輯實體(例如客戶端)的所有相關訊息都會儲存在同一臺計算機上。

基於欄位值的分割槽,訊息的分佈可能會不均勻。它取決於欄位的分佈以及將訊息對映到群集計算機的雜湊函式。不合適的雜湊演算法可能會將更多訊息對映到某些計算機上而不是其他計算機。這樣不均勻的訊息分發會導致叢集計算機之間負載分佈的不平均,這又會導致對於計算機資源的非最佳利用。

在某些情況下,基於非標識欄位值(例如外來鍵或某些其他欄位值)對訊息進行分割槽是有意義的。這顯然會導致訊息離散分佈,甚至可能導致非常不均勻的分佈,例如使用一個比其他值更普遍的值作為分割槽值。

下面是橫向擴充套件資料流的示意圖,其中叢集中的計算機的訊息分佈不一定均勻:

Key based data stream partitioning may lead to uneven distribution of the messages in the stream across the computers in the cluster.

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章