天天看點

資料庫分庫分表

  1. 對資料庫進行分庫分表的原因

    超大容量:

    資料表是超大表,資料庫處理能力達到極限;

    資料庫包含多個超大表。

    性能問題:

    單一伺服器性能有限

    更新擴充:

    單一主庫無法靈活地進行更新和擴充,無法滿足業務快速發展的需求

    所有業務資料都放在同一個庫中,存在單點故障風險。

  2. 資料庫拆分

    将表按照業務拆分到不同的資料庫伺服器上,同時針對大表進行分表處理,進而解決單一資料庫和資料表過大及IO服務連接配接數和IO讀寫上的瓶頸。

    常見的拆分方法有:垂直拆分、水準拆分、垂直水準拆分

  3. 垂直拆分

    垂直分庫:根據業務耦合性,将關聯度低的不同表存儲在不同的資料庫。做法與大系統拆分為多個小系統類似,按業務分類進行獨立劃分。與"微服務治理"的做法相似,每個微服務使用單獨的一個資料庫。

    垂直分表:基于資料庫中的"列"進行,某個表字段較多,可以建立一張擴充表,将不經常用或字段長度較大的字段拆分出去到擴充表中。在字段很多的情況下(例如一個大表有100多個字段),通過"大表拆小表",更便于開發與維護,也能避免跨頁問題,MySQL底層是通過資料頁存儲的,一條記錄占用空間過大會導緻跨頁,造成額外的性能開銷。另外資料庫以行為機關将資料加載到記憶體中,這樣表中字段長度較短且通路頻率較高,記憶體能加載更多的資料,命中率更高,減少了磁盤IO,進而提升了資料庫性能。

    優點:(1)解決業務系統層面的耦合。(2)業務清晰與微服務的治理類似,也能對不同業務的資料進行分級管理、維護、監控、擴充等。(3)高并發場景下,垂直切分一定程度的提升IO、資料庫連接配接數、單機硬體資源的瓶頸。

    缺點:(1)部分表無法join,隻能通過接口聚合方式解決,提升了開發的複雜度。(2)分布式事務處理複雜。(3)依然存在單表資料量過大的問題(需要水準切分)。

  4. 水準拆分

    水準切分分為庫内分表和分庫分表,是根據表内資料内在的邏輯關系,将同一個表按不同的條件分散到多個資料庫或多個表中,每個表中隻包含一部分資料,進而使得單個表的資料量變小,達到分布式的效果。

    優點:(1)不存在單庫資料量過大、高并發的性能瓶頸,提升系統穩定性和負載能力.(2)應用端改造較小,不需要拆分業務子產品。

    缺點:(1)跨分片的事務一緻性難以保證.(2)跨庫的join關聯查詢性能較差.(3)資料多次擴充難度和維護量極大。

    水準切分後同一張表會出現在多個資料庫/表中,每個庫/表的内容不同。幾種典型的資料分片規則為:

    1)根據數值範圍

    按照時間區間或ID區間來切分。例如:按日期将不同月甚至是日的資料分散到不同的庫中;将userId為19999的記錄分到第一個庫,1000020000的分到第二個庫,以此類推。某種意義上,某些系統中使用的"冷熱資料分離",将一些使用較少的曆史資料遷移到其他庫中,業務功能上隻提供熱點資料的查詢,也是類似的實踐。

    這樣的優點在于:(1)單表大小可控。(2)天然便于水準擴充,後期如果想對整個分片叢集擴容時,隻需要添加節點即可,無需對其他分片的資料進行遷移。(3)使用分片字段進行範圍查找時,連續分片可快速定位分片進行快速查詢,有效避免跨分片查詢的問題。

    缺點:熱點資料成為性能瓶頸。連續分片可能存在資料熱點,例如按時間字段分片,有些分片存儲最近時間段内的資料,可能會被頻繁的讀寫,而有些分片存儲的曆史資料,則很少被查詢。

    2)根據數值取模

    一般采用hash取模mod的切分方式,例如:将 Customer 表根據 cusno 字段切分到4個庫中,餘數為0的放到第一個庫,餘數為1的放到第二個庫,以此類推。這樣同一個使用者的資料會分散到同一個庫中,如果查詢條件帶有cusno字段,則可明确定位到相應庫去查詢。

    優點:資料分片相對比較均勻,不容易出現熱點和并發通路的瓶頸

    缺點:(1)後期分片叢集擴容時,需要遷移舊的資料(使用一緻性hash算法能較好的避免這個問題)(2)容易面臨跨分片查詢的複雜問題。比如上例中,如果頻繁用到的查詢條件中不帶cusno時,将會導緻無法定位資料庫,進而需要同時向4個庫發起查詢,再在記憶體中合并資料,取最小集傳回給應用,分庫反而成為拖累。

  5. 分庫分表帶來的問題
  6. 進行分表

    經過計算,将資料分到6個表中,保證在5~6年内不需要繼續進行分表。

    分表後使用靜态常量定義查詢、插入等SQL語句,表名使用replace()方法進行替換

    設計開關,将開關狀态存入redis中,通過改變狀态控制讀取舊表或者新表

\n

故不積跬步,無以緻千裡

繼續閱讀