圖解數據庫分片技術

你的程序正在變得越來越好,它有更多的功能,更多的活躍用戶,並且每天收集更多的數據。而同時你的數據庫正在導致程序的其餘部分變慢數據庫分片技術可能是該問題的答案,但許多人不知道它是什麼,最重要的是,不知道何時使用它。在本文中,我們將討論什麼是數據庫分片技術、它是如何工作的以及使用它的最佳方式。

在我們進入這個問題之前,有必要了解爲什麼我們要對數據存儲進行分片,以及在開始分片之前你擁有的各種選項。

數據庫分片信息圖

當表達到特定大小時,人們通常會覺得分片是解決所有擴展問題的神奇方法。然而,我有數十億行的表,並且沒有看到一個令人信服的理由進行分片,因爲我的使用模式很適合單個表並且沒有看到任何強有力的理由(除了管理這麼大的表,它在某些情況下是足夠的理由)對錶進行分片。

01 什麼是數據庫分片?

簡單地說,分片是一種跨多臺機器分佈數據的方法。當沒有一臺機器可以處理預期的工作負載時,分片就特別有必要。

分片是水平擴展的一個例子,而垂直擴展是一個越來越大的機器來支持新工作負載的例子。

水平擴展

工程師們經常陷入複雜的做事方式,但隨着程序的發展,儘早保持簡單會使以後面對具有挑戰性的事情時變得容易得多。因此,如果通過獲得具有更多資源的機器來解決你的問題,這是正確的答案。

我們已經討論了潛在的服務器架構,現在我們談談數據佈局。

你也可以通過幾種方式對數據進行分區並將特定表移動到它們自己的數據庫中,這與你在微服務架構中看到的非常相似,程序的特定部分有其自身數據庫服務器。程序知道每個數據庫該在哪裏尋找。或者,你可以跨多個數據庫節點存儲同一個表的行,這帶來了分片鍵等想法;稍後會詳細介紹。

分區策略

更現代的數據庫,如 Cassandra 和其他數據庫,將分區方法從程序邏輯中抽象出來,並在數據庫級別進行維護。

02 分片前我有哪些選擇?

與任何分佈式架構一樣,數據庫分片也需要花錢。設置分片、使每個分片上的數據保持最新以及確保將請求發送到正確的分片既費時又複雜。在開始分片之前,你可能想看看這些其他選項之一是否適合你。

選項 1:什麼都不做

我被問過無數次,在沒有任何明顯的瓶頸或限制因素,比如用完了可以支持工作負載的硬件,分片是否是一個好主意。我的答案是如果程序仍正常,請不要修理它。

選項 2:垂直擴展

在獲得具有更多資源的機器、添加額外的 RAM、爲計算繁重的工作負載添加更多 CPU 內核以及添加額外的存儲之後,我們也可以避開分片。這些都是不需要重新設計程序和數據庫架構的選項。其他最終限制,例如帶寬(網絡或系統內部),也會迫使你進行分片。

垂直擴展

選項 3:複製

如果你對數據所做的大部分工作是讀取,複製可以提高數據的可用性並加快讀取數據的速度。這可以幫助你避免數據庫分片的一些複雜性。可以通過製作更多數據庫副本來提高讀取性能。當然,假設你已經補充了緩存。這可以通過負載均衡或根據他們在世界上的位置路由查詢來完成。

但是複製使得頻繁寫入的工作負載更難處理,因爲每次寫入都必須複製到每個節點。這可能因數據存儲而異,其中一些是異步執行的,而另一些可能會延遲初始寫入以確保其被複制。

WAL

WAL(預寫日誌)是磁盤上的一種額外結構,只能添加到其中。在將更改寫入數據庫之前,它們首先寫入日誌,此日誌必須在持久存儲上。它用於從崩潰和丟失的事務中恢復。此日誌還用於支持某些數據庫(如 PostgreSQL 和 MySQL)中的複製。 

擴展讀取

選項 4:專業數據庫

性能不佳是因爲數據庫需要對其服務的工作負載進行更好地設計。例如,將搜索數據存儲在關係數據存儲中可能意義不大。將類似的東西移到 Elasticsearch 會更有效。將 blob 移動到像 S3 這樣的對象存儲可能是一個相當大的勝利,而不是將它們存儲在你的關係存儲中。外包此功能可能比嘗試對整個數據庫進行分片更有意義。

如果你的程序數據庫管理大量數據,需要大量讀寫,和 / 或需要始終可用,則分片數據庫可能是最佳選擇。讓我們來看看分片的優缺點。

03 必要時分片

分片可以在增加系統吞吐量、存儲容量和可用性方面爲你提供幾乎無限的可擴展性。有許多更小、更容易控制的系統,每個系統都可以通過各自的副本自行擴展和縮減。

所有這些優勢都要在操作複雜性、程序開銷和支持這種新設計的基礎設施成本上進行權衡。

它是如何工作的?

在我們可以分片數據庫之前,我們需要回答幾個重要問題。你的計劃將取決於你如何回答這些問題。

  1. 我們如何跨分片分佈數據?如果數據分佈不均,是否存在潛在熱點(hotspots)?

  2. 我們運行哪些查詢操作,以及表如何交互?

  3. 數據將如何增長?以後需要如何重新分配?

術語熱點是指節點的工作負載已超過特定資源(內存、io 等)的閾值。有一個有趣的例子叫做 Bieber Bug。

在我們進入下一點之前,理解以下術語很重要。

Shard Key(分片鍵)是主鍵的一部分,它告訴我們數據應該如何分佈。使用分片鍵,你可以通過將操作路由到正確的數據庫來快速查找和更改數據。

同一節點包含具有相同分片鍵的條目。共享相同分片鍵的一組數據稱爲邏輯分片。一個數據庫節點包含多個邏輯分片,也稱爲物理分片。

分離邏輯分片

最關鍵的推定也是未來最難改變的推定。 邏輯分片只能跨越一個節點,因爲它是一個原子存儲單元。在分片對於單個節點來說太大的情況下,數據庫集羣實際上空間不足。

基於鍵的分片

算法分片數據庫使用哈希函數來定位數據。這允許我們給定一個特定的分片鍵來找到正確的物理分片來請求數據。

數據僅通過散列函數進行分發。 它不考慮有效負載的大小或空間使用情況。當沒有合適的分區鍵時,散列的好處是允許更均勻的分佈,並且如果你有合適的分區鍵,則可以即時計算位置。

基於鍵的分片

如果你對確定性哈希函數感興趣,請查看我關於該主題的 Redis 帖子:

https://architecturenotes.co/redis/

這種分片策略的缺點是重新分片數據可能很困難,並且在可用的同時保持一致性更難。

04 基於範圍的分片

在基於範圍的分片中,根據某個值的範圍將數據分成塊。

基於範圍的分片

這需要一個查找表來查看數據應該存儲在哪裏。保持此類表格的一致性並在此處選擇範圍至關重要。

在爲這種分片類型選擇分片鍵時,必須選擇一個具有高基數的分片鍵,因此該鍵的可能值的數量很多。例如,可能值爲 North、South、East 和 West 的鍵的基數較低,因爲只有 4 個。此外,理想情況下,你希望在該基數內有良好的分佈。

均勻 / 不均勻分佈

如果一切都落在 50% 的可能值中,你的一些分片將開始出現熱點。使用準確的數據將其作爲實驗運行很容易,只需幾行代碼即可完成。首先,選擇一個鍵和範圍並檢查潛在分佈。

05 基於關係的分片

這種共享機制將相關數據保存在一個物理分片上。 例如,相關數據通常分佈在關係數據庫中的多個表中。

例如,對於像 Instagram 這樣的程序,用戶和所有相關數據將被分片到同一個物理節點,其中分別包含帖子和評論。通過將相關實體放在同一個分區中,你可以從單個分區中獲得更多收益。因此,在整個物理分片和更少的跨物理分片查詢中保持更強的一致性。

跨分片事務

最後,我想總結一些複雜性的細節,當你需要進行跨多個分片的事務時,這些複雜性可能會引入。無論你計劃多少,足夠長壽命的服務或程序最終都會遇到一些跨分片事務。

這實質上意味着你需要由 ACID 兼容數據庫提供的事務保證,但跨分片時數據庫不能確保這種合規性,因爲你操作的數據不在啓動它的事務範圍內。

這通常被稱爲全局事務,其中多個子事務需要協調併成功。作爲一般規則,事務打開的時間越長,爭用就越多,並且可能會發生故障。

兩階段提交

兩階段提交在理論上很簡單,但在實踐中很難執行。

協議路徑中的讀寫放大是一個主要問題。寫入放大的發生是因爲你必須寫入事務記錄並持久地進行提交,這需要每個參與者至少進行一次寫入。過多的寫入可能會導致鎖爭用和程序不穩定。數據庫必須額外過濾每次讀取,以確保它看不到任何依賴於掛起的跨分片事務的狀態,這會影響系統中的所有讀取,甚至是非事務性讀取。

06 結論

我們已經討論了分片、何時使用它以及如何設置它。對於需要管理大量數據並使其隨時可用於大量讀取和寫入的程序,分片是一種出色的解決方案。儘管如此,它還是使操作變得更加複雜。在開始實施之前,你應該考慮收益是否值得付出代價,或者是否有更直接的解決方案。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/8HYRVFWibtAIhwxApoTJuQ