1. 程式人生 > 實用技巧 >我的架構夢:(五十二) 分庫分表實戰及中介軟體之實戰背景

我的架構夢:(五十二) 分庫分表實戰及中介軟體之實戰背景

一、實戰背景

1、背景描述

  • 剛開始我們的系統只用了單機資料庫
  • 隨著使用者的不斷增多,考慮到系統的高可用和越來越多的使用者請求,我們開始使用資料庫主從架構
  • 當用戶量級和業務進一步提升後,寫請求越來越多,這時我們開始使用了分庫分表

2、遇到的問題

  • 使用者請求量太大
    單伺服器TPS、記憶體、IO都是有上限的,需要將請求打散分佈到多個伺服器
  • 單庫資料量太大
    單個數據庫處理能力有限;單庫所在伺服器的磁碟空間有限;單庫上的操作IO有瓶頸
  • 單表資料量太大
    查詢、插入、更新操作都會變慢,在加欄位、加索引、機器遷移都會產生高負載,影響服務

3、如何解決

3.1 垂直拆分

3.1.1 垂直分庫

微服務架構時,業務切割得足夠獨立,資料也會按照業務切分,保證業務資料隔離,大大提升了資料庫的吞吐能力。

在這裡插入圖片描述

3.1.2 垂直分表

表中欄位太多且包含大欄位的時候,在查詢時對資料庫的IO、記憶體會受到影響,同時更新資料時,產生的binlog檔案會很大,MySQL在主從同步時也會有延遲的風險。

在這裡插入圖片描述

3.2 水平拆分

3.2.1 水平分表

針對資料量巨大的單張表(比如訂單表),按照規則把一張表的資料切分到多張表裡面去。
但是這些表還是在同一個庫中,所以庫級別的資料庫操作還是有IO瓶頸。

在這裡插入圖片描述

3.2.2 水平分庫

將單張表的資料切分到多個伺服器上去,每個伺服器具有相應的庫與表,只是表中資料集合不同。 水平分庫分表能夠有效的緩解單機和單庫的效能瓶頸和壓力,突破IO、連線數、硬體資源等的瓶頸。

在這裡插入圖片描述

4、水平分庫規則

不跨庫、不跨表,保證同一類的資料都在同一個伺服器上面。

資料在切分之前,需要考慮如何高效的進行資料獲取,如果每次查詢都要跨越多個節點,就需要謹慎使用。

5、水平分表規則

5.1 RANGE

  • 時間:按照年、月、日去切分。例如order_2020、order_202005、order_20200501
  • 地域:按照省或市去切分。例如order_beijing、order_shanghai、order_shenzhen
  • 大小:從0到1000000一個表。例如1000001-2000000放一個表,每100萬放一個表

5.2 HASH

  • 使用者ID取模
    不同的業務使用的切分規則是不一樣,就上面提到的切分規則,舉例如下:

    (1) 站內信
    使用者維度:使用者只能看到傳送給自己的訊息,其他使用者是不可見的,這種情況下是按照

    使用者ID hash分庫,在使用者檢視歷史記錄翻頁查詢時,所有的查詢請求都在同一個庫內。
    (2) 使用者表
    範圍法:以使用者ID為劃分依據,將資料水平切分到兩個資料庫例項,如:1到1000W在 一張表,1000W到2000W在一張表,這種情況會出現單表的負載較高。
    (3) 按照使用者ID HASH儘量保證使用者資料均衡分到資料庫中

    如果在登入場景下,使用者輸入手機號和驗證碼進行登入,這種情況下,登入時是
    不是需要掃描所有分庫的資訊?
    最終方案:使用者資訊採用ID做切分處理,同時儲存使用者ID和手機號的對映的關係 表(新增一個關係表),關係表採用手機號進行切分。可以通過關係表根據手機號查詢到對應的ID,再定位使用者資訊。

    (4) 流水錶
    時間維度:可以根據每天新增的流水來判斷,選擇按照年份分庫,還是按照月份分庫,
    甚至也可以按照日期分庫
    (5) 訂單表
    在BOSS平臺,求職者(下面統稱C端使用者)投遞企業(下面統稱B端使用者)的職位產生的記錄稱之為訂單表。在線上的業務場景中,C端使用者看自己的投遞記錄,每次的投遞到了哪個狀態, B端使用者檢視自己收到的簡歷,對於合適的簡歷會進行下一步溝通,同一個公司內的員工可以協作處理簡歷。

    如何能同時滿足C端和B端對資料查詢,不進行跨庫處理?
    最終方案:為了同時滿足兩端使用者的業務場景,採用空間換時間,將一次的投遞記錄存為兩份,C端的投遞記錄以使用者ID為分片鍵,B端收到的簡歷按照公司ID為分片鍵。

6、主鍵選擇

  • UUID:本地生成,不依賴資料庫,缺點就是作為主鍵效能太差
  • SNOWFLAKE:百度UidGenerator、美團Leaf、基於SNOWFLAKE演算法實現

7、資料一致性

  • 強一致性:XA協議
  • 最終一致性:TCC、saga、Seata

8、資料庫擴容

  • 成倍增加資料節點,實現平滑擴容
  • 成倍擴容以後,表中的部分資料請求已被路由到其他節點上面,可以清理掉

9、業務層改造

  • 基於代理層方式:MycatSharding-ProxyMySQL Proxy
  • 基於應用層方式:Sharding-jdbc

10、分庫後面臨的問題

  • 事務問題:一次投遞需要插入兩條記錄,且分佈在不同的伺服器上,資料需要保障一致性。
  • 跨庫跨表的join問題
    全域性表(字典表):基礎資料/配置資料,所有庫都拷貝一份
    欄位冗餘:可以使用欄位冗餘就不用join查詢了
    系統層組裝:可以在業務層分別查詢出來,然後組裝起來,邏輯較複雜
  • 額外的資料管理負擔和資料運算壓力:資料庫擴容、維護成本變高