why分庫分表
分庫分表其實是解決海量數據存儲、高並發查詢和寫的問題。解決這個問題還有其他的方案,但是使用場景不同,比如:
- NosSql:比如Hbase,MongoDB,這些適合非結構化、不關心事務的場景,這時可以可以選擇Nosql陣營的產品。
- 關系型數據庫:
- 讀寫分離:讀多寫少模式,采用主從架構,根據qps的峰值和單台機器查詢的性能確定數量。
- 表分區:在表存儲階段進行存儲,應用無感知,因為是在一個庫內完成的操作,無法線性擴展,所以只能適應數據量不是特別大的case。
本章主要討論關系型數據庫的分庫分表
- 分表:單表瓶頸:單表數據過千萬時,查詢RT會升高,整體的QPS會下降,難以支撐高並發場景。
- 分庫:單庫瓶頸:應用數變多,io,磁盤達到瓶頸,整體的QPS會下降,難以支撐高並發場景。
how分庫分表
-
水平切分與垂直切分
- 垂直切分:垂直拆分是指數據表列的拆分,把一張列比較多的表拆分為多張表。表的記錄並不多,但是字段卻很長,表占用空間很大,檢索表的時候需要執行大量的IO,嚴重降低了性能。這時需要把大的字段拆分到另一個表,並且該表與原表是一對一的關系。
- 切分原則
- 1,把不常用的字段單獨放在一張表;,
- 2,把text,blob等大字段拆分出來放在附表中;
- 3,經常組合查詢的列放在一張表中;
- 優點
- 數據庫的拆分簡單明了,拆分規則明確;
- 應用程序模塊清晰明確,整合容易;
- 數據維護方便易行,容易定位;
- 缺點
- 部分表關聯無法在數據庫級別完成,需要在程序中完成;
- 對於訪問極其頻繁且數據量超大的表仍然存在性能平靜,不一定能滿足要求;
- 事務處理相對更為復雜;
- 切分達到一定程度之后,擴展性會遇到限制;
- 過讀切分可能會帶來系統過渡復雜而難以維護。
- 備注:一定要在設計階段就解決這個問題,時候的拆分成本代價較高
- 切分原則
- 水平切分:將一個表的記錄水平分到多張表里面,下面會細說
- 垂直切分:垂直拆分是指數據表列的拆分,把一張列比較多的表拆分為多張表。表的記錄並不多,但是字段卻很長,表占用空間很大,檢索表的時候需要執行大量的IO,嚴重降低了性能。這時需要把大的字段拆分到另一個表,並且該表與原表是一對一的關系。
-
如何選擇分庫分表字段:
- 充分的業務場景分析,找出使用頻度最高的字段。
- 常見的有賣家id、買家id、訂單id、商戶id、業務id、時間
-
分庫分表水平切分的策略:確定分表字段后,要確定如何按照字段去分,常見算法分區、取模、數據路由表
- 按照時間分區
- 原理:將一定區間內的數據放到一張表,多個表在一個庫里面
- 案例:具體用哪一種,需要根據數據量進行評估
- 按照日分
每日1張表,當單庫超過100張表的時候,分到下一個庫。
算法:庫ID=(當前日期-上線日期)/100 表ID=業務表_yyyyMMdd - 按照月分
業務表_yyyyMM - 按照年分
業務表_yyyy
- 按照日分
- 先hash,后取模
- 直接取模
- 范圍分表
- 比如四張表,每個表只存1000w,第一個表存1-1000w,第四張表存儲3001-4000w
- 按照時間分區
帶來的問題&解決的辦法
事物都具有兩面性,分庫分表固然解決了高並發存儲的問題,但是也帶來了一些后遺症
- 全局主鍵問題
- 多種查詢維度的問題:比如訂單表,既要通過買家id來查,又要通過賣家id來查,這時sharding column就矛盾了。怎么解決呢?
- 數據冗余:上面的例子,可以冗余兩張表,分別是買家和賣家表。犧牲存儲來換查詢復雜度
- 表替代索引:數據冗余適合查詢維度較少的場景,如果多了,數據冗余量太大,就不再是合理的方案了,表替代索引法。
- 全局存儲搜索法:通過搜索引擎的方式存儲和查詢,比如數據同步到ES上。
- 分庫分表+es的方案,隨着數據量越來越來,雖然分庫分表可以繼續成倍擴容,但是這時候壓力又落到了es這里,這個架構也會慢慢暴露出問題!
一般訂單表,積分明細表等需要分庫分表的核心表都會有好幾十列,甚至上百列(假設有50列),但是整個表真正需要參與條件索引的可能就不到10個條件(假設有10列)。這時候把50個列所有字段的數據全量索引到es中,對es集群有很大的壓力,后面的es分片故障恢復也會需要很長的時間。
這個時候我們可以考慮減少es的壓力,讓es集群有限的資源盡可能保存條件檢索時最需要的最有價值的數據,即只把可能參與條件檢索的字段索引到es中,這樣整個es集群壓力減少到原來的1/5(核心表50個字段,只有10個字段參與條件),而50個字段的全量數據保存到HBase中,這就是經典的es+HBase組合方案,即索引與數據存儲隔離的方案。
Hadoop體系下的HBase存儲能力我們都知道是海量的,而且根據它的rowkey查詢性能那叫一個快如閃電。而es的多條件檢索能力非常強大。這個方案把es和HBase的優點發揮的淋漓盡致,同時又規避了它們的缺點,可以說是一個揚長避免的最佳實踐。
它們之間的交互大概是這樣的:先根據用戶輸入的條件去es查詢獲取符合過濾條件的rowkey值,然后用rowkey值去HBase查詢,后面這一查詢步驟的時間幾乎可以忽略,因為這是HBase最擅長的場景
- 分庫分表+es的方案,隨着數據量越來越來,雖然分庫分表可以繼續成倍擴容,但是這時候壓力又落到了es這里,這個架構也會慢慢暴露出問題!
業界知名中間件產品和優劣對比
- 阿里的TDDL,DRDS和cobar,
- 開源社區的sharding-jdbc(3.x已經更名為sharding-sphere);
- 民間組織的MyCAT;
- 360的Atlas;
- 美團的zebra;