什麼是資料庫 sharding?

資料庫 sharding 是一種策略,可解決應用程式資料量過大時的擴充性問題。也就是將單一大型邏輯資料集分割成較小、更易於管理的部分,稱為 shard。每個 shard 都儲存在獨立的資料庫伺服器執行個體,有效將資料和工作負載分散到多部機器。

sharding 是資源調度 (水平擴展) 的重要方法。sharding 可讓您在叢集中新增更多商用伺服器,而不必升級單一伺服器,增加 CPU 或 RAM (垂直擴充),最終達到硬體上限。應用程式可處理幾乎無限成長的資料量和使用者流量。

Credit Karma 的資料庫轉型:從已 shard 的 MySQL 到 Spanner

sharding 是水平擴展的有效做法,同時也是三種常見的水平資源調度策略之一:

  • 唯讀備用資源:這涉及建立主要資料庫的副本,以處理唯讀流量,減輕主要伺服器的負載
  • sharding:將資料和寫入流量分配到多個獨立伺服器
  • 分散式資料庫:Spanner 等產品可在資料庫引擎中原生處理分配和資源調度作業,因此不必手動進行 sharding

資料庫 sharding 如何運作?

資料庫 sharding 是根據稱為 shard 鍵的特定值,將資料分組。shard 鍵是資料庫中的資料欄,例如使用者 ID、客戶區域或訂單編號,可決定特定資料列要儲存在哪個伺服器。當資料寫入資料庫時,系統會查看這個鍵,以決定資料所屬的位置。

為了日後能找到資料,系統必須將查詢導向正確位置。這類轉送作業主要有兩種做法:

  • 轉送層:sharding 架構可能會使用智慧型負載平衡器或專用 Proxy 層。應用程式傳送查詢時,轉送層會檢查 shard 鍵,計算出哪個 shard 持有該資料,並將流量導向該伺服器。
  • 應用程式端邏輯:在某些情況下,例如多人遊戲或高效能即時應用程式,應用程式程式碼本身就包含 sharding 邏輯。這段程式碼會在傳送要求前,計算正確的 shard 位置,藉此減少額外的網路躍點,降低延遲。

資料庫只會鎖定相關資料 shard,因此能更快回覆查詢,並處理數千個並行要求,不會降低速度。

資料 sharding 資訊圖表

常見的 sharding 方法

不同應用程式需要不同的資料分割邏輯。您選擇的方法會決定「轉送層」如何尋找資料。

這個方法會對 shard 鍵使用數學公式 (雜湊函式) 來指派資料。舉例來說,系統可能會計算使用者 ID (mod 4),將使用者指派給 4 部伺服器中的 1 部。

雖然雜湊函式有助於一致地分配資料,但只有在 shard 鍵具高基數和低頻率偏差時,才能確保均勻分配。如果選擇的 shard 鍵值很常見,例如「Last Name」中「Smith」出現的次數比「Pyne」多 1,000 次,雜湊函式就會將所有「Smith」記錄傳送至同一個 shard。即使使用數學公式,仍會建立「熱 shard」。

此外,由於公式會變更,這通常需要「重新分割」或在新的伺服器叢集間移動資料,因此採用這種方法時,新增伺服器也很困難。

系統會根據值範圍,指派資料。舉例來說,您可以將使用者 ID 1 到 1,000 放在伺服器 A,並將 1,001 到 2,000 放在伺服器 B。這項功能非常直覺,適合用於需要讀取一系列資料的查詢 (範圍查詢)。但這種做法的缺點是會產生「熱點」,也就是說,如果所有新使用者都指派給伺服器 B,該伺服器就會負責所有工作,而伺服器 A 則閒置。

這項策略會使用對照表 (目錄) 追蹤哪個 shard 包含哪些資料。這種做法最彈性,因為您可以在 shard 之間移動資料,不必變更公式。不過,這個對照表會成為瓶頸,因為每個查詢都必須先檢查目錄,所以會增加延遲。如果目錄發生故障,就會無法存取整個資料庫。

地理 sharding 會根據使用者的實際位置,將資料指派給特定伺服器。舉例來說,法國使用者的資料會儲存在歐盟地區的伺服器,而美國使用者的資料則會儲存在北美地區的伺服器。這可為使用者大幅縮短延遲時間 (速度),並協助公司遵守 GDPR 等資料落地法規。

有時稱為功能分區,這種做法是依據特徵而非資料列來分割資料。舉例來說,您可以將所有「使用者個人資料」資料表放在伺服器 A,並將所有「相片上傳」資料表放在伺服器 B。雖然這種做法能以邏輯方式整理資料,但功能上與微服務資料架構類似,如果特定功能 (例如相簿) 的資料量過大,單一伺服器就無法負荷,並不能解決問題。

如何最佳化資料庫 sharding,確保資料平均分布

選擇合適的 shard 鍵,是 sharding 作業中最關鍵的決定。如果選擇不當的鍵,可能會導致資料分配不均 (熱點),而選擇適當的鍵則可確保所有伺服器平均運作。如要最佳化這項作業,必須考量三個因素:

  1. 基數:這是指鍵可擁有的不重複值數量。您需要高基數的鍵 (例如使用者 ID),而不是低基數的鍵 (例如「性別」或「州/省」),這樣資料才能分割成許多小區塊。
  2. 頻率:請避免使用特定值出現頻率過高的鍵。舉例來說,如果依「城市」進行 shard,且 80% 的使用者都住在紐約,則「紐約」shard 會過載。
  3. 單調遞增的變更:避免使用會隨時間嚴格遞增的鍵,例如時間戳記或自動遞增的 ID。如果按日期進行 shard,則所有新資料寫入作業都會前往「今天」shard,導致寫入熱點,而較舊的 shard 則閒置。

sharding 的重要術語

雖然這兩個詞彙在系統設計中經常一起使用,但解決的問題不同。

sharding 是一種水平分區,會將資料分配到完全不同的伺服器。由於不同伺服器可以同時處理寫入作業,因此能解決硬體容量限制 (儲存空間) 和寫入處理量瓶頸。

  • 手動 sharding:在手動 sharding 環境中,開發人員或資料庫管理員必須負責定義 shard 鍵、為每個 shard 建立基礎架構,以及編寫查詢轉送邏輯。讓您精細控管資料的存放位置。不過,這需要大量維護作業。如果某個 shard 變得過大,您必須手動「重新分割」資料,也就是將數百萬列資料移至新伺服器,同時盡可能縮短應用程式停機時間。
  • 自動 sharding:Bigtable 等 NoSQL 資料庫,或 Spanner 等分散式 SQL 資料庫中,通常會提供自動 sharding 功能,能自動處理資料和流量分配作業。系統會監控資料大小和各伺服器的負載。如果特定 shard 成為「熱點」或過於龐大,資料庫引擎會自動分割 shard,並將資料移至較不擁塞的伺服器。這能減輕團隊的作業負擔,並確保應用程式擴充時維持一致的效能。

分區是將大型資料表分割成較小、更易於管理的部分 (例如按月分割記錄資料表),但這些部分仍保留在同一個伺服器執行個體。這樣一來,您就能輕鬆封存或刪除舊資料,而不影響資料表中的其他內容,解決儲存空間問題。但無法解決伺服器問題。由於所有分區仍位於同一部機器,因此會繼續共用相同的 CPU 和 RAM,這表示如果伺服器達到效能上限,即使是分區也沒有幫助。

複製是指將整個資料庫複製到多部伺服器。如果想確保讀取作業的可用性,這會是不錯的選擇,因為當一個伺服器故障時,另一個伺服器可以接管。不過,由於寫入的每筆資料都必須複製到每個副本,因此寫入速度會受限於單一機器的容量,對於調度寫入資源沒有幫助。

同樣重要的是,大多數複製模型一次只允許一個「寫入者」(主要節點)。如果嘗試讓多部伺服器同時接受寫入作業,可能會發生寫入衝突,也就是兩部伺服器嘗試以不同資訊更新同一筆記錄。解決這些衝突在技術上相當困難,如果沒有由複雜的分散式系統處理,可能會導致資料遺失或不一致。

Spanner 等分散式資料庫具備 sharding 的優勢,並能免除手動作業。這些系統從一開始就設計成可跨機器叢集運作。這些系統會自動處理資料分布、重新平衡,並以公開透明的方式處理複製作業。其中有些系統有多個寫入者,並會自動處理寫入衝突。這可讓您水平擴充,同時維持傳統關聯式資料庫的一致性。

請參閱下表,瞭解這些核心資料庫概念的差異。

功能

資料分割

分區

複製

分散式資料庫

主要目標

大規模調度寫入資源和儲存空間

易於管理與維護

高可用性和調度讀取資源


自動化全球資源調度

資料位置

不同伺服器上的不同資料區塊

同一部伺服器上的不同資料區塊

相同資料在多部伺服器上的多個副本

在叢集中管理

寫入效能

大幅改善 (平行寫入)

小幅改善 (較小的索引)


無改善 (寫入作業必須傳送至所有副本)

大幅改善

複雜度

低 (代管)

功能

資料分割

分區

複製

分散式資料庫

主要目標

大規模調度寫入資源和儲存空間

易於管理與維護

高可用性和調度讀取資源


自動化全球資源調度

資料位置

不同伺服器上的不同資料區塊

同一部伺服器上的不同資料區塊

相同資料在多部伺服器上的多個副本

在叢集中管理

寫入效能

大幅改善 (平行寫入)

小幅改善 (較小的索引)


無改善 (寫入作業必須傳送至所有副本)

大幅改善

複雜度

低 (代管)

資料庫 sharding 的好處

對於處理 TB 規模的資料或每秒數百萬筆交易的應用程式,sharding 通常是唯一可行的解決方案。

水平資源調度

sharding 可將標準伺服器新增至叢集,實現近乎無限的擴充性。這可避免傳統垂直擴充應用程式的「硬體稅」。如果不採用 sharding,通常就得購買昂貴的專用硬體,但效能仍有上限。sharding 可使用更經濟實惠的機器,讓資料庫隨著業務成長而擴充

提升查詢效能

sharding 可加快個別查詢速度,因為每個伺服器搜尋的資料集較小。查詢作業不必搜尋 1 億列的索引,可能只要搜尋 100 萬列的 shard 即可。此外,由於資料位於不同機器上,因此您可以平行執行多個查詢,大幅提高應用程式的總處理量。

可靠性

sharding 可限制故障的「影響範圍」。如果一個 shard 故障,只有該 shard 的使用者會受到影響,應用程式的其餘部分仍會保持連線。不過,伺服器數量越多,管理負擔就越重。與單一伺服器設定相比,管理數十個執行個體的備份、安全性和修補程式會增加作業複雜度。

sharding 的難題

sharding 雖然能滿足大規模需求,但會帶來重大的技術和營運取捨。在捨棄單一執行個體架構前,請先考量這些挑戰。

  • 資料熱點:即使使用雜湊函式,流量不均仍可能產生「熱點」,其中一小群活躍使用者讓某個伺服器過載,其他 shard 則未充分利用。
  • 效能迴歸:未使用 shard 鍵的查詢,需要系統在每個伺服器上執行「散布收集」作業。同樣地,橫跨 shard 聯結的運算成本很高,因為應用程式必須從多個實體位置提取及合併資料。
  • 作業複雜度:管理已 shard 的環境會增加例行工作的難度。必須協調多個獨立執行個體的結構定義更新、備份和時間點復原作業。
  • 交易一致性:許多已 shard 的架構難以在不同 shard 中支援 ACID 交易。這通常會迫使開發人員管理複雜的「部分失敗」情境,或依賴最終一致模型。

透過 Google Cloud 解決業務難題

新客戶可以獲得價值 $300 美元的免費抵免額,盡情試用各項 Google Cloud 功能。

後續行動

做好準備,不必再擔心資料庫限制