如何分片資料庫? - stackoverflow

banq發表於2022-03-15

分片是解決網路應用發展帶來的新挑戰的方法之一。其他解決方案包括 DBaaS(或雲中的資料庫)、新的資料庫架構,或者只是增加用於儲存的資料庫數量的老式方法。 

隨著智慧手機的出現,應用程式將我們消耗和產生的資料量增加到了 15 年前無法想象的水平。這給資料庫叢集帶來了很大的壓力,因為它們需要處理越來越多的流量,一些頂級網站和服務每週接收數十億次訪問。

當它到達資料庫叢集時,我們如何處理如此驚人的流量? 

答案可能是分片。

 

為什麼需要分片

傳統資料庫可能難以處理越來越多的資料和查詢流量。NoSQL和 NewSQL 概念現在非常流行,因此越來越多的受這些想法啟發的新資料庫產品正在投放市場。但僅憑這些概念並不能解決日益增長的資料問題。 

分片是一種將資料拆分為單獨的行和列的技術,這些行和列儲存在單獨的資料庫伺服器例項上,以分散流量負載。每個小表稱為一個分片。一些 NoSQL 產品如 Apache HBase 或 MongoDB 有分片,並且分片架構內建在 NewSQL 系統中

讓我們看看一種特殊型別的 NewSQL 架構:與當今的 OLTP(線上事務處理)問題相關的分片。 

雖然有許多解決方案可以最大限度地減少資料庫負載,但分片具有以下優點:

  •  在多臺機器上分佈資料儲存
  •  輕鬆平衡不同分片的流量負載
  •  顯著提高查詢效能
  •  無需額外工作即可擴充套件資料庫
  •  高效重用和升級傳統 DBMS
  •  由於使用代理支援多租戶,因此允許多個資料庫跨使用者使用單個伺服器或雲端計算資源。  

 

如何對資料庫進行分片

以下是一個基本工作流程,可讓您為 DBMS 實現分片。在討論了這項技術的設定和基本思想之後,我們將在稍後對一些基本方面提供一些更深入的見解。

建立分片的最佳技術之一是將資料拆分為多個小表。這些也稱為分割槽。 

原始表可以分為垂直分片或水平分片;也就是說,通過將一列或多列儲存在單獨的表中,或者將一列或多行儲存在單獨的表中。這些表可以標記為垂直分片的“VS1”和平面分片的“HS1”。數字代表第一個表或第一個模式。然後是 2,然後是 3,以此類推。綜合起來,這些資料子集構成了表的原始模式。 

以下是分片的兩個關鍵概念:

  1. • 分片鍵:一個特定的列值,指示該行儲存在哪個分片中。
  2. • 分片演算法:一種將資料分佈到一個或多個分片的演算法。

 

  • Step 1:分析場景查詢和資料分佈,找到分片鍵和分片演算法

確定儲存任何給定行的分片,請將分片演算法應用於分片鍵。不同的分片策略適合不同的場景。常見的策略包括:

  1. MOD:模數的縮寫,這會將每第 n 行或每列傳送到特定的分片。例如,MOD 3 演算法會將第一、四和七行傳送到第一個分片,將第二、五和八行傳送到第二個分片,將第三、六和第九行傳送到第三個分片,並且很快。 
  2. HASH:雜湊分片在分片之間均勻隨機分佈資料。根據對該行的分片列值計算的一致雜湊將每個錶行放置在一個分片中。
  3. RANGE:這會將特定範圍的行或列傳送到各個分片。 
  4. TAG:這會傳送與特定值匹配的所有行或列。 

因此,您要做的就是設計一個使用分片鍵的擬合演算法。您的分片策略將顯著影響查詢效率和未來的橫向擴充套件。不正確或糟糕的分片演算法總是會在不同的分片之間建立冗餘資料進行計算,最終導致整體計算效能不佳。

決定如何對資料庫進行分片時要考慮的關鍵點是業務查詢和資料分佈的特徵。每個資料庫都會有影響這個決定的獨特因素,但我們可以提供一些示例場景來說明一個好的分片演算法如何有效地分佈資料。 

RANGE

例如,在對包含有時間戳的日誌細節的表進行分片時,建議採用以建立日期為分片鍵的RANGE分片演算法。原因是,傳統上,人們往往只在特定的時間範圍內查詢這些詳細記錄。

當使用日期時間時,RANGE演算法會引起另一個問題:歷史記錄通常會更新得比較少,而最近的記錄會經常更新和查詢,大多數查詢會擊中有最近記錄的分片。這將導致大多數查詢相互競爭,以獲得更新資料的獨家權利。

 

MOD

MOD分片演算法可以有效避免這種激烈的競爭。它通過 "shardingKey MOD shards number "對記錄進行分割。最新的行將被分割到不同的分片中,因此最新的查詢將被髮送到不同的分片中,以避免最近的行競爭。當分片金鑰是一個字串值(並且有可能敏感地被披露)時,你可以使用HASH演算法來建立一個MOD演算法可以用來分配資料到分片的值。

 

TAG

然而,有些時候你可能想通過單元格的值來分片;在這種情況下,你會想使用TAG分片演算法。假設為了遵守GDPR法規,你想將所有歐盟資料儲存在位於歐盟的伺服器上。我們將如何操作分片分散式資料庫系統來回答這個問題?如果DBA使用TAG分片演算法,帶有標記國家的資料的行可以被髮送到位於特定國家的特定分片。要知道有多少記錄受到影響,我們的分片資料庫系統只需要從歐盟分片中返回COUNT(*)來回答這個查詢。SELECT COUNT(*) FROM registrant_table WHERE region = "EU". 一個必須從整個分散式系統中計算出最終結果的分散式查詢,變成了一個分片的簡單的單一查詢。

沒有適用於所有情況的銀彈。為了達到最好的效能,花一些時間徹底分析你的具體業務場景。如果你想快速上手,分散式分片資料庫系統一般會選擇一種滿足大多數使用情況的通用策略。

 

  • 第2步:遷移現有資料

如果你決定實施分片,你不需要將所有的原始資料遷移到分片叢集中。這樣做是一個挑戰,因為你會面臨以下問題。

  1. 如何在業務24/7執行時分片資料 
  2. 如何在新的分片叢集中重放增量資料 
  3. 如何比較原始資料庫和新分片叢集之間的資料 
  4. 如何找到將流量切換到新分片叢集的最佳時機

然而,如果你確實決定將歷史資料遷移到分片上,傳統的方法如下。

  1. 首先,通過分片演算法將歷史資料分割到新的資料庫分片叢集中。推薦使用一個自動移動資料的程式,它將執行所有需要的SQL查詢。
  2. 第二,執行一個平臺或程式來拉動和解析資料庫日誌,瞭解在分割槽過程中發生了哪些變化,並將這些變化應用到新的分片叢集中(增量資料分片)。
  3. 第三,選擇一種資料檢查策略來比較原始資料庫和新分片叢集之間的資料。這些資料檢查策略是靈活的,從高精度到短週期,或者兩者之間的平衡。你是想比較每個單元還是隻檢查總量,由你決定。在資料檢查策略方面,要達到最高的準確度,逐一比較行數需要付出最大的努力,而只比較原叢集和新叢集的行數,則以犧牲準確度為代價,速度最快。其他策略,如CRC32,則是實現了準確性和速度的平衡。

 

  • 第3步:將流量轉移到新的叢集

假設上述步驟順利完成,下一步是將線上流量切換到你的新分片叢集。這應該發生在資料庫叢集不能被寫入的時期,以便兩個資料集保持一致,並保持可選的查詢--非高峰期是這個步驟的常見選擇。

為了保持分散式資料的一致性,應該禁止所有更新請求,但允許查詢,因為它們不會在分散式系統中引起任何變化。

這個過程足夠直截了當,但每個部分的處理都會有挑戰性。自動執行移動將最大限度地減少停機時間,並建議謹慎行事,因為你將處理寶貴的資料。

好訊息是,你不是第一個遇到這些挑戰的人。開源專案讓我們能夠站在巨人的肩膀上。

Apache ShardingSphere(我是它的貢獻者)將整個分片過程作為其主要功能之一來處理。它提供不同的分片策略,遷移資料,重新分片,並管理現有的分片。

它還提供了更多的高階功能,以幫助解決下一節中提到的問題。作為額外的獎勵,Apache ShardingSphereit擁有一個活躍的社群,這意味著你的大多數問題已經得到解決。

 

 

使用分片和複製 

除了上面提到的核心流程外,還要對下面的專案進行訓練,因為資料庫場景是多樣化的,你的需求會隨著應用的擴充套件而改變。

另一種提高資料庫效能和可擴充套件性的方法是通過複製。複製建立獨立執行的重複資料庫節點。寫入一個節點的資料就會被複制到另一個重複的節點上。

一般來說,無論是專業人士還是從事激情專案的開發人員,都會努力從資料庫中榨取最大的能量,以獲得高可用性和效能--然而,分片和複製的架構會導致複雜的資料庫管理和路由策略。

那麼,分片和複製之間有什麼區別?

分片是指將一個大表分割成幾個小表,以建立許多分片;

另一方面,複製將建立原始表的許多副本。每個副本將包含原表(主節點)的全部資料。

分片可以幫助使用者在多個伺服器上平衡資料的存在,以獲得可擴充套件性,而複製將建立主資料庫的備份以提高系統的可用性。

這兩種不同的架構給分散式系統帶來了不同的優勢。

基於這一推理,一些使用者希望同時擁有這兩種能力,因此,同時利用分片和複製的混合架構並不罕見。

例如:使用者可能希望將一個包含巨大資料量的資料庫分片到不同的伺服器上,比如P1、P2、P3。每個查詢也將被分片到不同的分片中,以提高這個分散式資料庫系統的TPS或QPS。然而,如果其中一個分片崩潰了,可用性將降低到2/3。

此外,拉起另一個離線版本的副本是很耗時的,會造成嚴重後果的損失。為了提高這個分片系統的可用性,一個有效的方法是為每個分片拉起復制,也就是前面提到的主節點P1、P2、P3。

R1、R2、R3的存在說明了我上面解釋的解決方案。當P1不可用時,它的複製,R1,將被提升到主節點,為業務服務。這是一個安全的選擇,它的想法是,故障越小,對你的業務和服務的損失就越小。

這個想法聽起來不錯,但這種分散式分片資料庫系統的拓撲結構使應用訪問變得複雜。假設每個主節點擁有兩個副本,那麼由P1、P2、P3和它們的六個副本組成的網路將使開發人員感到困惑和負擔,提出的問題包括:哪個主節點對這個查詢是正確的? 如何訪問它們的一個副本?如何在不同的副本之間做負載平衡?一旦主節點不能工作,誰會幫我重新安排這個查詢?

在我們假設的場景中,開發人員的責任是為業務效率編碼。這種非凡的架構確實有優勢,但要利用和維護卻太複雜了。

如何從應用中隱藏這種複雜性?

一般來說,有兩種型別的客戶端或訪問模式供使用者選擇,外加一種新的 "獎勵 "型別的客戶端。分片可以通過專門的資料庫連線驅動程式來唆使,也可以通過將你的應用程式連線到一個路由資料的代理應用程式。

Sidecar是分片可用模式中較新的概念,源自於服務網格。簡單來說,它是一個與服務一起部署的代理例項,用於處理不同服務之間的通訊、監控等。這種模式的運作類似於連線在摩托車上的副車。這意味著副車附著在父級應用上,同時為應用提供支援功能。

如果我們使用一個專門的驅動程式或代理,而不是sidecar,它將作為一個單一的資料庫伺服器行事和出現,幫助使用者管理他們的資料庫叢集。這樣,應用程式就不會受到這些複雜的訪問拓撲結構的影響,或者不得不重構自己以適應新的框架。

相關文章