數據庫分片(Database Sharding)詳解

本文由雲+社區發表

做者:騰訊雲數據庫算法

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英文官網,若轉載請註明出處。翻譯目的在於傳遞更多全球最新數據庫領域相關信息,並不意味着騰訊雲數據庫產品團隊贊同其觀點或證明其內容的真實性。若是其餘媒體、網站或其餘任何形式的法律實體和我的使用,必須通過著做權人合法書面受權並自負所有法律責任。不得擅自使用騰訊雲數據庫團隊的名義進行轉載,或盜用騰訊雲數據庫團隊名義發佈信息。

此文已由騰訊雲+社區在各渠道發佈

獲取更多新鮮技術乾貨,能夠關注咱們騰訊雲技術社區-雲加社區官方號及知乎機構號

相關文章
相關標籤/搜索