為什么要分庫分表
一般的機器(4核16G),單庫的MySQL并發(fā)(QPS+TPS)超過了2k,系統(tǒng)基本就完蛋了。最好是并發(fā)量控制在1k左右。這里就引出一個問題,為什么要分庫分表?
分庫分表目的:解決高并發(fā),和數(shù)據(jù)量大的問題。
1、高并發(fā)情況下,會造成IO讀寫頻繁,自然就會造成讀寫緩慢,甚至是宕機。一般單庫不要超過2k并發(fā),NB的機器除外。
2、數(shù)據(jù)量大的問題。主要由于底層索引實現(xiàn)導(dǎo)致,MySQL的索引實現(xiàn)為B+TREE,數(shù)據(jù)量其他,會導(dǎo)致索引樹十分龐大,造成查詢緩慢。第二,innodb的最大存儲限制64TB。
要解決上述問題。最常見做法,就是分庫分表。
分庫分表的目的,是將一個表拆成N個表,就是讓每個表的數(shù)據(jù)量控制在一定范圍內(nèi),保證SQL的性能。 一個表數(shù)據(jù)建議不要超過500W。

分庫分表,又分為垂直拆分和水平拆分。
水平拆分:統(tǒng)一個表的數(shù)據(jù)拆到不同的庫不同的表中。可以根據(jù)時間、地區(qū)、或某個業(yè)務(wù)鍵維度,也可以通過hash進行拆分,最后通過路由訪問到具體的數(shù)據(jù)。拆分后的每個表結(jié)構(gòu)保持一致。
垂直拆分:就是把一個有很多字段的表給拆分成多個表,或者是多個庫上去。每個庫表的結(jié)構(gòu)都不一樣,每個庫表都包含部分字段。一般來說,可以根據(jù)業(yè)務(wù)維度進行拆分,如訂單表可以拆分為訂單、訂單支持、訂單地址、訂單商品、訂單擴展等表;也可以,根據(jù)數(shù)據(jù)冷熱程度拆分,20%的熱點字段拆到一個表,80%的冷字段拆到另外一個表。

不停機分庫分表數(shù)據(jù)遷移
一般數(shù)據(jù)庫的拆分也是有一個過程的,一開始是單表,后面慢慢拆成多表。那么我們就看下如何平滑的從MySQL單表過度到MySQL的分庫分表架構(gòu)。
1、利用mysql+canal做增量數(shù)據(jù)同步,利用分庫分表中間件,將數(shù)據(jù)路由到對應(yīng)的新表中。
2、利用分庫分表中間件,全量數(shù)據(jù)導(dǎo)入到對應(yīng)的新表中。
3、通過單表數(shù)據(jù)和分庫分表數(shù)據(jù)兩兩比較,更新不匹配的數(shù)據(jù)到新表中。
4、數(shù)據(jù)穩(wěn)定后,將單表的配置切換到分庫分表配置上。

分庫分表如何動態(tài)擴容
設(shè)計分庫分表的時候,不管3721直接就分32個庫,每個庫32個表,共1024個表。擴容的時候,申請增加更多的數(shù)據(jù)庫服務(wù)器,裝好mysql,倍數(shù)擴容,4臺服務(wù)器,擴到8臺服務(wù)器,16臺服務(wù)器。最后,將原先數(shù)據(jù)庫服務(wù)器的庫,遷移到新的數(shù)據(jù)庫服務(wù)器上去。
并發(fā)角度:每個庫正常承載的寫入并發(fā)量是1000,那么32個庫就可以承載32 * 1000 = 32000的寫并發(fā),如果每個庫承載1500的寫并發(fā),32 * 1500 = 48000的寫并發(fā),接近5萬/s的寫入并發(fā),前面再加一個MQ,削峰,每秒寫入MQ 8萬條數(shù)據(jù),每秒消費5萬條數(shù)據(jù)。
存儲角度:1024張表,假設(shè)每個表放500萬數(shù)據(jù),在MySQL里可以放50億條數(shù)據(jù)。
讀寫分離也是分庫
都分庫分表了,為什么還要做讀寫分離?其實,讀寫分離跟分庫分表解決的問題都是一樣的。讀寫分離也是分庫的一種。
例如,一個項目單庫達到TPS1K,QPS2k,基本就很慢了。這個時候如果將單庫拆成兩個完全一樣結(jié)構(gòu)的庫,一個負責(zé)寫,一個負責(zé)讀,這樣就可以很好的進行處理性能。
讀寫分離,就需要用到主從同步技術(shù)。如果是寫多讀少,可以使用分庫分表,或者M-M-S架構(gòu);如果讀多寫少,可以使用M-S-S,擴展4~5個S都是可以。
MySQL主從復(fù)制原理:主庫將變更寫binlog日志,然后從庫連接到主庫之后,從庫有一個IO線程,將主庫的binlog日志拷貝到自己本地,寫入一個中繼日志中。接著從庫中有一個SQL線程會從中繼日志讀取binlog,然后執(zhí)行binlog日志中的內(nèi)容,也就是在自己本地再次執(zhí)行一遍SQL,這樣就可以保證自己跟主庫的數(shù)據(jù)是一樣的。

這里就有一個問題了。有數(shù)據(jù)傳輸就會有間延,一旦并發(fā)量大就有可能造成較大的間延,也產(chǎn)生了主從延時問題。
如何解決主從延時問題?
1、分庫,將一個主庫拆分為4個主庫,每個主庫的寫并發(fā)就500/s,此時主從延遲可以忽略不計。
2、打開mysql支持的并行復(fù)制,多個庫并行復(fù)制。如果說某個庫的寫入并發(fā)就是特別高,單庫寫并發(fā)達到了2000/s,并行復(fù)制還是沒意義。28法則,很多時候比如說,就是少數(shù)的幾個訂單表,寫入了2000/s,其他幾十個表10/s。(所謂并行復(fù)制,指的是從庫開啟多個線程,并行讀取relay log中不同庫的日志,然后并行重放不同庫的日志,這是庫級別的并行。)
3、直接查主庫(不推薦)
4、檢查代碼,一般INSERT/UPDATE后,馬上進行SELECT,這種代碼要避免。