資料庫分片(Database Sharding)詳解

qcloud發表於2019-02-20

本文由雲+社群發表

作者:騰訊雲資料庫

img

Introduction 導言

任何看到顯著增長的應用程式或網站,最終都需要進行擴充套件,以適應流量的增加。以確保資料安全性和完整性的方式進行擴充套件,對於資料驅動的應用程式和網站來說十分重要。人們可能很難預測某個網站或應用程式的流行程度,也很難預測這種流行程度會持續多久,這就是為什麼有些機構選擇“可動態擴充套件的”資料庫架構的原因。

在這篇概念性文章中,我們將討論一種“可動態擴充套件的”資料庫架構:分片資料庫。近年來,分片(Sharding)一直受到很多關注,但許多人並沒有清楚地瞭解它是什麼,或者對資料庫進行分片可能有意義的場景。我們將討論分片是什麼,它的一些主要優點和缺點,以及一些常見的分片方法。

下方是本文目錄,幫助您接下來的閱讀

img

What is Sharding? 什麼是分片?

分片(Sharding)是一種與水平切分(horizontal partitioning)相關的資料庫架構模式——將一個表裡面的行,分成多個不同的表的做法(稱為分割槽)。每個區都具有相同的模式和列,但每個表有完全不同的行。同樣,每個分割槽中儲存的資料都是唯一的,並且與其他分割槽中儲存的資料無關。

從水平切分(horizontal partitioning)與垂直切分(vertical partitioning)的關係,可能會有所幫助。在垂直切分表中,所有的列被分離出來,並放入新的不同的表中。每個垂直切分內的資料,獨立於所有其他分割槽中的資料,並且每個分割槽都包含不同的行和列。下圖說明了如何在水平和垂直方向上對錶進行分割槽:

img

新增描述

分片(Sharding)將一個資料分成兩個或多個較小的塊,稱為邏輯分片(logical shards)。然後,邏輯分片(logical shards)分佈在單獨的資料庫節點上,稱為物理分片(physical shards)。物理分片(physical shards)可以容納多個邏輯分片(logical shards)。儘管如此,所有分片中儲存的資料,共同代表整個邏輯資料集。

資料庫分片(Database shards)是無共享架構的一個例子。這意味著分片是自治的:分片間不共享任何相同的資料或伺服器資源。但是在某些情況下,將某些表複製到每個分片中作為參考表是有意義的。例如,假設某個應用程式的資料庫依賴於重量測量的固定轉換率。通過將包含必要轉換率資料的表複製到每個分片中,有助於確保查詢所需的所有資料都儲存在每個分片中。

通常,分片(Sharding)在應用程式級別進行實現。這意味著應用程式包含“要向哪個分片傳送讀和寫”的程式碼。但是,某些資料庫管理系統內建了分片功能,允許您直接在資料庫級別實現分片。

以上是分片(Sharding)的概述,接下來讓我們來看一下,這種資料庫架構的優點和缺點。

Benefits of Sharding 分片的好處

資料庫分片的主要吸引力在於,它可以幫助促進水平擴充套件(horizontal scaling),也稱為向外擴充套件(scaling out)。水平擴充套件是將更多的機器新增到現有堆疊中,以分散負載,允許更多的流量和更快的處理。這通常與垂直擴充套件(vertical scaling)形成對比,垂直擴充套件也稱為向上擴充套件(scaling up),是指升級現有伺服器的硬體,通常是新增更多記憶體或CPU。

讓一個關聯式資料庫在單個機器上執行,並按需升級其伺服器資源進行向上擴充套件是相對簡單的。但最終,任何非分散式資料庫在儲存和計算能力方面都會受到限制,因此可以自由地水平擴充套件資料庫,會使您的架構更加靈活且適應性強。

選擇分片資料庫架構的另一個原因,是為了加速查詢響應的時間。當您對尚未分片的資料庫提交查詢時,必須先搜尋您查詢的表中的每一行,然後才能找到您要查詢的結果集。對於具有大型單片資料庫的應用程式,查詢可能變得極其緩慢。但是,通過將一個表分成多個,查詢過程會遍歷更少的行,並且返回結果集的速度要快得多。

分片還可以通過減少當機(outage)的影響,使應用程式更穩定可靠。如果您的應用程式或網站依賴於未分片的資料庫,則當機可能會導致整個應用程式不可用。但是,對於分片資料庫,當機可能只會影響單個分片。即使這可能使某些使用者無法使用應用程式或網站部分功能,但仍會低於整個資料庫崩潰帶來的影響。

Drawbacks of Sharding 分片的缺點

雖然對資料庫進行分片可以使擴充套件更容易並提高效能,但它也可能會帶來某些限制。在這裡,我們將討論其中的一些限制,以及為什麼這些限制會讓我們避免對資料庫全部分片。

正確實現分片資料庫架構,是十分複雜的,所以這是分片遇到的第一個困難。如果操作不正確,則分片過程可能會導致資料丟失或表損壞,這是一個很大的風險。但是,即使正確地進行了分片,也可能對團隊的工作流程產生重大影響。與從單個入口點訪問和管理資料不同,使用者必須跨多個分片位置管理資料,這可能會讓某些團隊存在工作混亂。

在對資料庫進行分片後,使用者有時會遇到的一個問題是分片最終會變得不平衡。舉例來說,假設您有一個資料庫,其中有兩個單獨的分片,一個用於姓氏以字母A到M開頭的客戶,另一個用於名字以字母N到Z開頭的客戶。但是,您的應用程式為姓氏以字母G開頭的人提供了過多的服務。因此,A-M分片逐漸累積的資料比N-Z分片要多,這會導致應用程式速度變慢,並對很大一部分使用者造成影響。A-M分片已成為所謂的資料熱點。在這種情況下,資料庫分片的任何好處都被慢速和崩潰抵消了。資料庫可能需要修復和重新分片,才能實現更均勻的資料分佈。

另一個主要缺點是,一旦對資料庫進行了分片,就很難將其恢復到未分片的架構。分片前資料庫的備份資料,都無法與分片後寫入的資料合併。因此,重建原始的非分片架構,需要將新的分割槽資料與舊備份合併,或者將分割槽的資料庫轉換回單個資料庫,這兩種方法都是昂貴且耗時的。

要考慮的最後一個缺點是,並不是每個資料庫引擎本身都支援分片。例如,儘管可以手動分片PostgreSQL資料庫,但PostgreSQL本身並不包括自動分片功能。有許多Postgres分支包括自動分片功能,但這些分支通常落後於最新的PostgreSQL版本,並且缺乏某些其他的功能特性。一些專業的資料庫技術——如MySQL Cluster或某些資料庫即服務產品(如MongoDB Atlas)確實包含自動分片功能,但這些資料庫管理系統的普通版本卻並不包含。因此,分片通常需要“自己動手”的方法。這意味著通常很難找到有關分片或故障排除技巧的文件。

現在我們已經介紹了一些分片的缺點和好處,我們將討論一些分片資料庫的不同架構。

一旦你決定對資料庫進行分片,接下來你需要弄清楚的是如何進行分片。在執行查詢或將傳入的資料分發到分片表或資料庫時,關鍵是要將其分配到正確的分片。否則,它可能導致資料丟失或查詢速度緩慢。在本節中,我們將介紹一些常見的分片架構,每個架構使用稍微不同的流程來跨分片分發資料。

Key Based Sharding 基於鍵的分片

img

新增描述

為了確保資料記錄以正確的方式被放置在正確的分片中,雜湊函式中輸入的值都應該來自同一列。此列稱為分片鍵。簡單來說,分片鍵與主鍵類似,因為它們都是列,用於為各個行建立唯一識別符號。一般來說,分片鍵應該是靜態的,這意味著它不應包含可能隨時間變化的值。否則,它會增加更新操作的工作量,並可能降低效能。

雖然基於鍵的分片是一種相當常見的分片架構,但在嘗試動態新增或刪除資料庫中的其他伺服器時,它會使事情變得棘手。在新增伺服器時,每個伺服器都需要一個相應的雜湊值,並且許多現有條目(如果不是全部)都需要重新對映到新的正確雜湊值,然後遷移到相應的伺服器。當您開始重新平衡資料時,新舊雜湊函式都不會有效。因此,在遷移期間,您的伺服器將無法編寫任何新資料,您的應用程式可能會停機。

這種策略的主要吸引力在於,它可以用於均勻分佈資料,從而防止熱點。此外,由於它以演算法方式分配資料,因此無需維護所有資料所在位置的對映,而其他策略(如範圍或基於目錄的分片)必須維護資料位置的對映。

Range Based Sharding 基於範圍的分片

基於範圍的分片(Range based sharding),基於給定值的範圍進行資料分片。為了說明,假設您有一個資料庫,用於儲存零售商目錄中所有產品的資訊。您可以建立一些不同的分片,並根據每個產品的價格範圍分配每個產品的資訊,如下所示:

img

新增描述

基於範圍的分片的主要好處是,它實現起來相對簡單。每個分片都包含一組不同的資料,但它們都具有相同的模式,以及原始資料庫。應用程式程式碼只讀取資料所屬的範圍,並將其寫入相應的分片。

另一方面,基於範圍的分片並不能預防資料不均勻分佈的現象,而有可能會出現前面提到的資料熱點現象。檢視示例圖,即使每個分片擁有相同數量的資料,特定產品比其他產品獲得更多關注的可能性也會很大。相應的,各個的分片將接收不成比例的讀取操作。

Directory Based Sharding 基於目錄的分片

要實現基於目錄的分片,必須建立並維護一個查詢表,該查詢表使用分片鍵來跟蹤哪個分片包含哪些資料。簡而言之,查詢表是一個表,其中包含有關可以找到特定資料的靜態資訊集。下圖顯示了基於目錄的分片的簡單示例:

img

新增描述

此處,Delivery Zone列被定義為分片鍵。將來自分片鍵的資料,連同每一行應該寫入的分片寫入查詢表。這與基於範圍的分片類似,但不是確定分片鍵的資料落入哪個範圍,而是將每個鍵繫結到其自己的特定分片。如果分片鍵的基數很低,並且分片鍵儲存鍵的範圍沒有意義,那麼基於目錄的分片比基於範圍的分片要更好。請注意,它也不同於基於金鑰的分片,因為它不通過雜湊函式處理分片鍵; 它只是根據查詢表檢查鍵值,以檢視資料需要寫入的位置。

基於目錄的分片的主要吸引力在於其靈活性。基於範圍的分片架構只能指定鍵值範圍,而基於鍵的分片架構只能使用固定的雜湊函式,如前所述,在以後更改該函式非常困難。另一方面,基於目錄的分片允許您使用任何系統或演算法將資料項分配給分片,使用這種方法動態新增分片也相對容易。

雖然基於目錄的分片是這裡討論的最靈活的分片方法,但是在每次查詢或寫入之前連線到查詢表,可能會對應用程式的效能產生不利影響。此外,查詢表可能出現單點故障:如果查詢表損壞或出現其他故障,它可能會影響資料庫寫入新資料或訪問現有資料的能力。

Should I Shard? 我應該分片嗎?

是否應該實現分片資料庫架構,幾乎總是一個爭論的問題。有些人認為分片對於達到一定規模的資料庫來說,是不可避免的結果。而另一些人則認為這是一個令人頭疼的問題,除非絕對必要,否則應該避免,因為分片增加了操作的複雜性。

由於這種增加的複雜性,通常僅在處理非常大量的資料時才執行分片。以下是一些常見方案,可能對資料庫分片的操作有所幫助:

· 應用程式資料量增長到超過單個資料庫節點的儲存容量。

· 對資料庫的讀寫量,超過單個節點或其只讀副本可以處理的量,從而導致響應時間增加或超時。

· 應用程式所需的網路頻寬,超過單個資料庫節點和任何只讀副本可用的頻寬,從而導致響應時間增加或超時。

在分片之前,您應該用盡所有其他選項來優化資料庫。您可能需要考慮的一些優化包括:

設定遠端資料庫。如果您使用的是一個整體應用程式,其中所有元件都位於同一個伺服器上,那麼可以通過將資料庫移到它自己的機器上來提高資料庫的效能。由於資料庫的表保持不變,因此這不會增加分片的複雜性。但是,它仍然允許您垂直伸縮資料庫,使其與基礎結構的其他部分分離。

實現快取。如果您的應用程式的讀取效能導致您遇到麻煩,那麼快取是一種可以幫助改進它的策略。快取涉及臨時儲存已在記憶體中請求的資料,以便您以後更快地訪問它。

建立一個或多個只讀副本。另一種有助於提高讀取效能的策略,包括將資料從一個資料庫伺服器(主伺服器)複製到一個或多個從伺服器。在此之後,每次新的寫操作在複製到從伺服器之前都要先到主伺服器,而讀操作只對從伺服器進行。像這樣分發讀寫可以防止任何一臺機器承擔過多的負載,從而有助於防止速度下降和崩潰。請注意,建立讀副本需要更多的伺服器資源,因此花費更多的錢,這對一些人來說可能是一個很大的限制。

升級到更大的伺服器。在大多數情況下,將一個資料庫伺服器擴充套件到具有更多資源的計算機比分片需要更少的工作量。與建立只讀副本一樣,具有更多資源的伺服器升級可能會花費更多的錢。因此,只有當它確實是您的最佳選擇時,您才應該進行伺服器擴容。

請記住,如果您的應用程式或網站增長超過某個點,這些策略本身都不足以提高效能。在這種情況下,分片可能確實是您的最佳選擇。

Conclusion 結語

對於那些希望橫向擴充套件資料庫的人來說,分片是一個很好的解決方案。但是,它還會增加很多複雜性,併為您的應用程式建立更多潛在的故障點。分片對於某些人來說可能是必要的,但是建立和維護分片架構所需的時間和資源可能會超過對其他人的好處。

通過閱讀這篇概念性文章,您應該更清楚地瞭解分片的優缺點。接下來,您可以使用這些見解來對分片資料庫架構是否適合您,做出更明智的決定。

版權宣告:本文由騰訊雲資料庫產品團隊整理,頁面原始內容來自於db weekly英文官網,若轉載請註明出處。翻譯目的在於傳遞更多全球最新資料庫領域相關資訊,並不意味著騰訊雲資料庫產品團隊贊同其觀點或證實其內容的真實性。如果其他媒體、網站或其他任何形式的法律實體和個人使用,必須經過著作權人合法書面授權並自負全部法律責任。不得擅自使用騰訊雲資料庫團隊的名義進行轉載,或盜用騰訊雲資料庫團隊名義釋出資訊。

此文已由騰訊雲+社群在各渠道釋出

獲取更多新鮮技術乾貨,可以關注我們騰訊雲技術社群-雲加社群官方號及知乎機構號

相關文章