史上最詳盡的 MySQL 分庫分表文章
點擊下方“IT牧場”,選擇“設(shè)為星標”

1、先拋出兩個問題 2、 基本概念 3、 分片 3.1 水平拆分,垂直拆分都是什么? 3.2 為什么分表? 2.3 為什么分庫? 3.4 分布式事務(wù)? 3.5 小結(jié) 3.6 如何自己實現(xiàn)分庫分表? 4、 分組 4.1 為什么分組? 4.2 同步,異步,半同步 4.3 ha方案 5、 應(yīng)用案例 5.1 記錄一次mongo遷移mysql的過程(分庫分表使用jproxy) 5.2 記錄一次異構(gòu)具有復(fù)雜分片規(guī)則數(shù)據(jù)庫的過程
文章集中整理總結(jié)mysql分庫分表開源產(chǎn)品,分布式數(shù)據(jù)庫的設(shè)計,以及實際應(yīng)用案例等相關(guān)內(nèi)容,部分附上本文作者實際應(yīng)用過程中的理解。
本文感謝 sjdbc,mycat,姜承堯,林濤 等文章提供的精彩介紹。
1、先拋出兩個問題
問題一、當mysql單表數(shù)據(jù)量爆炸時,你怎么辦?
問題二、當你的數(shù)據(jù)庫無法承受高強度io時你怎么辦?
2、 基本概念
2.1 談數(shù)據(jù)庫分片需要首先確定以下概念
單庫,就是一個庫

分片(sharding),分片解決 擴展性問題,屬于水平拆分,引入分片,就引入了數(shù)據(jù)路由和分區(qū)鍵的概念。分表解決的是數(shù)據(jù)量過大的問題,分庫解決的是數(shù)據(jù)庫性能瓶頸的問題。

分組(group),分組解決 可用性問題,分組通常通過主從復(fù)制(replication)的方式實現(xiàn)。(各種可用級別方案單獨介紹)

互聯(lián)網(wǎng)公司數(shù)據(jù)庫實際軟件架構(gòu)是( 大數(shù)據(jù)量下):又分片,又分組(如下圖)

3、 分片
3.1 水平拆分,垂直拆分都是什么?

分區(qū)表?1)若不走分區(qū)鍵很容易出現(xiàn)全表鎖,并發(fā)上來后簡直是災(zāi)難。2)自己分庫分表,自己掌控業(yè)務(wù)場景、訪問模式,可控。mysql分區(qū)表官方介紹是針對myisam做的優(yōu)化,你知道他怎么玩的?分半天還是一個ibdata是不是很尷尬
3.2 為什么分表?
關(guān)系型數(shù)據(jù)庫在大于一定數(shù)據(jù)量的情況下檢索性能會急劇下降。在面對互聯(lián)網(wǎng)海量數(shù)據(jù)情況時,所有數(shù)據(jù)都存于一張表,顯然會輕易超過數(shù)據(jù)庫表可承受的數(shù)據(jù)量閥值。這個單表可承受的數(shù)據(jù)量閥值,需根據(jù)數(shù)據(jù)庫和并發(fā)量的差異,通過實際測試獲得。
水平拆分如果能預(yù)估規(guī)模,越早做成本越低。
3.3 為什么分庫?
單純的分表雖然可以解決數(shù)據(jù)量過大導(dǎo)致檢索變慢的問題,但無法解決過多并發(fā)請求訪問同一個庫,導(dǎo)致數(shù)據(jù)庫響應(yīng)變慢的問題。所以通常水平拆分都至少要采用分庫的方式,用于一并解決大數(shù)據(jù)量和高并發(fā)的問題。這也是部分開源的分片數(shù)據(jù)庫中間件只支持分庫的原因。
3.4 分布式事務(wù)?
但分表也有不可替代的適用場景。最常見的分表需求是事務(wù)問題。同在一個庫則不需考慮分布式事務(wù),善于使用同庫不同表可有效避免分布式事務(wù)帶來的麻煩。目前強一致性的分布式事務(wù)由于性能問題,導(dǎo)致使用起來并不一定比不分庫分表快。目前采用最終一致性的柔性事務(wù)居多。分表的另一個存在的理由是,過多的數(shù)據(jù)庫實例不利于運維管理。
mysql本身?消息補償?2PC?
3.5 小結(jié)
綜上所述,最佳實踐是合理地配合使用分庫+分表。
3.6 如何自己實現(xiàn)分庫分表?
dao層,首先
通過分區(qū)鍵算出庫名表名(如shardKey%shardNum 算出來表index如y,然后y/(shardNum/sourceNum)=x,y是表下標,x是庫下標)。把source從spring容器中拿出來,把表名當參數(shù)傳進去,拼成分片后的sql。思路大概是(select … from order where … -> 先拿到db_x的source 然后 select … from order_y where …)
你想這么干?你已經(jīng)成功了。當然淘寶和當當?shù)募軜?gòu)師也是這么干的。
3.7 SO,不需要我們親自動手,其實你需要做的只是按照實際需求挑選而已。

3.8 重點介紹兩個產(chǎn)品,先不說具體配置,只說思想
sharding-jdbc(所處位置,通用數(shù)據(jù)訪問層,部署在客戶端的jar包,用于將用戶的SQL路由到指定的數(shù)據(jù)庫中)
盜一波圖





jproxy
jproxy是什么?
jproxy提供MariaDB, MySQL等數(shù)據(jù)庫的統(tǒng)一接入訪問,擁有流量過載保護,數(shù)據(jù)自動拆分,可配置路由規(guī)則,數(shù)據(jù)無縫遷移等功能。應(yīng)用場景:數(shù)據(jù)需要分庫分表,自動擴容的應(yīng)用。

為什么分片都是2的n次方?a % (2^n) 等價于 a & (2^n - 1) 其中一個原因就是位運算
擴容?虛擬桶。極限就是一片一庫。
演變過程 cobar->mycat->jproxy
mycat是什么?
簡單的說,就是:一個徹底開源的,面向企業(yè)應(yīng)用開發(fā)的“大數(shù)據(jù)庫集群”。支持事務(wù)、ACID、可以替代Mysql的加強版數(shù)據(jù)庫,一個的數(shù)據(jù)庫中間件產(chǎn)品。
其優(yōu)勢具有: 基于阿里開源的Cobar產(chǎn)品而研發(fā),Cobar的穩(wěn)定性、可靠性、優(yōu)秀的架構(gòu)和性能 擁有眾多成熟的使用案例 強大的團隊(其參與者都是5年以上資深軟件工程師、架構(gòu)師、DBA等) 開源,創(chuàng)新,持續(xù)更新
盜一波圖

4、 分組
4.1 為什么分組?
分組解決可用性問題
mysql的ha 網(wǎng)洛上的都是vip漂移實現(xiàn)的


共享存儲? 不需要復(fù)制了 更高的一致性
真正的高并發(fā)場景,什么架構(gòu)都抗不住,老老實實用緩存。
需要大量讀的場景盡量做到最終一致性。
4.2 同步,異步,半同步
異步復(fù)制 (mysql默認)
Master將事件寫入binlog,但并不知道Slave是否或何時已經(jīng)接收且已處理。當Slave準備好才會向Master請求binlog。缺點:不能保證一些事件都能夠被所有的Slave所接收。
同步復(fù)制
Master提交事務(wù),直到事務(wù)在
所有的Slave都已提交,此時才會返回客戶端,事務(wù)執(zhí)行完畢。缺點:完成一個事務(wù)可能會有很大的延遲。
半同步復(fù)制
半同步復(fù)制工作的機制處于同步和異步之間,Master的事務(wù)提交阻塞,
只要一個Slave已收到該事務(wù)的事件且已記錄。它不會等待所有的Slave都告知已收到,且它只是接收,并不用等其完全執(zhí)行且提交。
半同步復(fù)制的步驟:
i.當Slave主機連接到Master時,能夠查看其是否處于半同步復(fù)制的機制。
ii.當Master上開啟半同步復(fù)制的功能時,至少應(yīng)該有一個Slave開啟其功能。此時,一個線程在Master上提交事務(wù)將受到阻塞,直到得知一個已開啟半同步復(fù)制功能的Slave已收到此事務(wù)的所有事件,或等待超時。
iii.當一個事務(wù)的事件都已寫入其relay-log中且已刷新到磁盤上,Slave才會告知已收到。
iv.如果等待超時,也就是Master沒被告知已收到,此時Master會自動轉(zhuǎn)換為異步復(fù)制的機制。當至少一個半同步的Slave趕上了,Master與其Slave自動轉(zhuǎn)換為半同步復(fù)制的機制。
v.半同步復(fù)制的功能要在Master,Slave都開啟,半同步復(fù)制才會起作用;否則,只開啟一邊,它依然為異步復(fù)制。
4.3 ha方案
MHA MMM
5、 應(yīng)用案例
5.1 記錄一次mongo遷移mysql的過程(分庫分表使用jproxy)
mongo怎么了?跟分片無關(guān)的部分簡單說。
mongo很好,只是業(yè)界并沒有成熟的MongoDB運維經(jīng)驗,jd too。像高并發(fā)的系統(tǒng) 訂單和庫存 商品 還是拿nosql把,高并發(fā)的寫,也不會打掛他,比如hbase,頂多GC頻繁點,但是也是可用的。一致性完全可以CAS搞定,而不是mysql的排他鎖。
遷移數(shù)據(jù)庫的一個方案 中心化(統(tǒng)一入口) 雙寫(先同步寫mysql如果發(fā)生異常改異步,盡量避免服務(wù)不可用) 倒庫(jproxy支持通過游標形式全量遍歷庫-逐個表操作,可以利用其異步同步數(shù)據(jù)) 數(shù)據(jù)校驗 切庫提供服務(wù)

去mongo+優(yōu)化方案(此處引入了分片的概念)


壓測與性能





去mongo任務(wù)線
| 類型 | 任務(wù) | 備注 | 影線系統(tǒng) | 風險 |
|---|---|---|---|---|
| design | 海關(guān)遷移方案設(shè)計評審 | … | … | 無 |
| design | 分庫分表技術(shù)選型 | jproxy | … | 無 |
| apply | 申請遷移相關(guān)應(yīng)用(輔助系統(tǒng)) | 跑批任務(wù) | … | 無 |
| apply | 申請mysql集群 | dbs系統(tǒng) | … | 無 |
| apply | 申請jproxy集群 | 直接找接口人 | … | 無 |
| apply | 申請es集群 | esm杰斯 | … | 無 |
| coding | trace表服務(wù)中心化 | soa | center | 高 |
| coding | 涉及trace業(yè)務(wù)邏輯梳理,全部切換中心接口 | 接口完全適配 | platform | 低 |
| verify | 回歸測試,并線上走單驗證一段時間 | 先預(yù)發(fā)后正式 | … | 高 |
| coding | 實現(xiàn)mysql版本共2個表sql映射文件 | 基于自主研發(fā)的generator | center | 低 |
| verify | mysql版本sql映射文件單元測試 | 基于自主研發(fā)的generator | center | 低 |
| coding | trace表實現(xiàn)基于jproxy的分庫分表 | 128個庫(主) 1主3從 | center | 中 |
| coding | es分別按照商家id分片,保稅區(qū)id分片,異步寫,讀開放jsf | 2套集群4套索引 | es | 中 |
| coding | 中心接口加入代理層,可利用開關(guān)切換讀mongo/mysql/es | … | center | 高 |
| coding | 異步補償mongo,mysql,es功能開發(fā) | 基于jmq | platform | 中 |
| coding | 代理層實現(xiàn)mongo和mysql版本互為主被雙寫(mongo主),異步寫es | 雙11后mysql主 | center | 高 |
| verify | 線上開雙寫(包括es) | 兩套es集群 | … | 中 |
| coding | 倒庫功能開發(fā),數(shù)據(jù)校驗功能開發(fā) | reactor | config | 高 |
| verify | 倒庫,并進行數(shù)據(jù)校驗 | 校驗規(guī)則(特殊字段不校驗) | … | 高 |
| verify | 對中心接口進行壓測 | 線上,壓測環(huán)境隔離(jsf別名) | … | 高 |
| coding | 優(yōu)化配置(mysql調(diào)整最大連接數(shù),es使用filterCache) | … | … | 高 |
| verify | 對中心接口進行壓測 | … | … | 高 |
| verify | 升級后架構(gòu)正式上線 | … | … | 無 |
| verify | 監(jiān)控切換mysql之后的接口性能 | … | … | 無 |
| verify | 監(jiān)控切換mysql之后對相關(guān)依賴系統(tǒng)的影響 | … | … | 無 |
| todo | 停mongo寫 | … | … | 無 |
| todo | 繼續(xù)遷移海關(guān)mongo中其他表(以上均為trace表) | … | … | 無 |
| todo | 徹底下線mongo數(shù)據(jù)庫服務(wù)器,只保留mysql服務(wù)器 | … | … | 無 |
5.2 記錄一次異構(gòu)具有復(fù)雜分片規(guī)則數(shù)據(jù)庫的過程
5.2.1 難點
交易庫存復(fù)雜的分片規(guī)則,數(shù)據(jù)量大,更新頻繁,一致性保證。
回到本源,緩存+隊列

5.2.2 不跑題,我們就說分片部分,如何接手一個復(fù)雜分片規(guī)則的數(shù)據(jù)庫?
參考案例如何異構(gòu)一個數(shù)十億級別的數(shù)據(jù)庫
有多復(fù)雜? 6000+表,28個庫,4套分片規(guī)則。(解決方案 sharding-jdbc)
干貨分享
最近將個人學習筆記整理成冊,使用PDF分享。關(guān)注我,回復(fù)如下代碼,即可獲得百度盤地址,無套路領(lǐng)??!
?001:《Java并發(fā)與高并發(fā)解決方案》學習筆記;?002:《深入JVM內(nèi)核——原理、診斷與優(yōu)化》學習筆記;?003:《Java面試寶典》?004:《Docker開源書》?005:《Kubernetes開源書》?006:《DDD速成(領(lǐng)域驅(qū)動設(shè)計速成)》?007:全部?008:加技術(shù)群討論
加個關(guān)注不迷路
喜歡就點個"在看"唄^_^









