面試必備:我們?yōu)槭裁匆謳旆直恚?/h1>

目錄

  1. 什么是分庫分表
  2. 為什么需要分庫分表呢
  3. 如何分庫分表
  4. 什么時候開始考慮分庫分表
  5. 分庫分表會導致哪些問題
  6. 分庫分表中間件簡介

1. 什么是分庫分表

數(shù)據(jù)庫:就是一個數(shù)據(jù)庫分成多個數(shù)據(jù)庫凿叠,部署到不同機器。

分表:就是一個數(shù)據(jù)庫表分成多個表。

2. 為什么需要分庫分表

2.1 為什么需要分庫呢左敌?

如果業(yè)務量劇增浙垫,數(shù)據(jù)庫可能會出現(xiàn)性能瓶頸拄踪,這時候我們就需要考慮拆分數(shù)據(jù)庫纯衍。從這幾方面來看:

  • 磁盤存儲

業(yè)務量劇增蔗衡,MySQL單機磁盤容量會撐爆竖共,拆成多個數(shù)據(jù)庫蝙叛,磁盤使用率大大降低。

  • 并發(fā)連接支撐

我們知道數(shù)據(jù)庫連接是有限的公给。在高并發(fā)的場景下借帘,大量請求訪問數(shù)據(jù)庫,MySQL單機是扛不住的淌铐!當前非撤稳唬火的微服務架構出現(xiàn),就是為了應對高并發(fā)腿准。它把訂單际起、用戶、商品等不同模塊吐葱,拆分成多個應用街望,并且把單個數(shù)據(jù)庫也拆分成多個不同功能模塊的數(shù)據(jù)庫(訂單庫、用戶庫弟跑、商品庫)灾前,以分擔讀寫壓力。

2.2 為什么需要分表孟辑?

數(shù)據(jù)量太大的話哎甲,SQL的查詢就會變慢蔫敲。如果一個查詢SQL沒命中索引,千百萬數(shù)據(jù)量級別的表可能會拖垮整個數(shù)據(jù)庫烧给。

即使SQL命中了索引燕偶,如果表的數(shù)據(jù)量超過一千萬的話,查詢也是會明顯變慢的础嫡。這是因為索引一般是B+樹結構指么,數(shù)據(jù)千萬級別的話,B+樹的高度會增高榴鼎,查詢就變慢啦伯诬。

小伙伴們是否還記得,MySQL的B+樹的高度怎么計算的呢巫财? 順便復習一下吧

InnoDB存儲引擎最小儲存單元是頁盗似,一頁大小就是16k。B+樹葉子存的是數(shù)據(jù)平项,內(nèi)部節(jié)點存的是鍵值+指針赫舒。索引組織表通過非葉子節(jié)點的二分查找法以及指針確定數(shù)據(jù)在哪個頁中,進而再去數(shù)據(jù)頁中找到需要的數(shù)據(jù)闽瓢,B+樹結構圖如下:

假設B+樹的高度為2的話接癌,即有一個根結點和若干個葉子結點。這棵B+樹的存放總記錄數(shù)為=根結點指針數(shù)*單個葉子節(jié)點記錄行數(shù)扣讼。

  • 如果一行記錄的數(shù)據(jù)大小為1k缺猛,那么單個葉子節(jié)點可以存的記錄數(shù) =16k/1k =16.
  • 非葉子節(jié)點內(nèi)存放多少指針呢?我們假設主鍵ID為bigint類型椭符,長度為8字節(jié)(面試官問你int類型荔燎,一個int就是32位,4字節(jié))销钝,而指針大小在InnoDB源碼中設置為6字節(jié)有咨,所以就是 8+6=14 字節(jié),16k/14B =16*1024B/14B = 1170

因此蒸健,一棵高度為2的B+樹摔吏,能存放1170 * 16=18720條這樣的數(shù)據(jù)記錄。同理一棵高度為3的B+樹纵装,能存放1170 1170 16 =21902400,大概可以存放兩千萬左右的記錄据某。B+樹高度一般為1-3層橡娄,如果B+到了4層,查詢的時候會多查磁盤**的次數(shù)癣籽,SQL就會變慢挽唉。

因此單表數(shù)據(jù)量太大滤祖,SQL查詢會變慢,所以就需要考慮分表啦瓶籽。

3. 如何分庫分表

3.1 垂直拆分

3.1.1 垂直分庫

在業(yè)務發(fā)展初期匠童,業(yè)務功能模塊比較少,為了快速上線和迭代塑顺,往往采用單個數(shù)據(jù)庫來保存數(shù)據(jù)汤求。數(shù)據(jù)庫架構如下:

但是隨著業(yè)務蒸蒸日上,系統(tǒng)功能逐漸完善严拒。這時候扬绪,可以按照系統(tǒng)中的不同業(yè)務進行拆分,比如拆分成用戶庫裤唠、訂單庫挤牛、積分庫、商品庫种蘸,把它們部署在不同的數(shù)據(jù)庫服務器墓赴,這就是垂直分庫

垂直分庫航瞭,將原來一個單數(shù)據(jù)庫的壓力分擔到不同的數(shù)據(jù)庫诫硕,可以很好應對高并發(fā)場景。數(shù)據(jù)庫垂直拆分后的架構如下:

3.1.2 垂直分表

如果一個單表包含了幾十列甚至上百列沧奴,管理起來很混亂痘括,每次都select 的話,還占用IO資源滔吠。這時候纲菌,我們可以將一些不常用的、數(shù)據(jù)較大或者長度較長的列*表拆分到另外一張表疮绷。

比如一張用戶表翰舌,它包含user_id、user_name冬骚、mobile_no椅贱、age、email只冻、nickname庇麦、address、user_desc喜德,如果email山橄、address、user_desc等字段不常用舍悯,我們可以把它拆分到另外一張表航棱,命名為用戶詳細信息表睡雇。這就是垂直分表

3.2 水平拆分

3.2.1 水平分庫

水平分庫是指,將表的數(shù)據(jù)量切分到不同的數(shù)據(jù)庫服務器上饮醇,每個服務器具有相同的庫和表它抱,只是表中的數(shù)據(jù)集合不一樣。它可以有效地緩解單機單庫的性能瓶頸和壓力朴艰。

用戶庫的水平拆分架構如下:

3.2.2 水平分表

如果一個表的數(shù)據(jù)量太大观蓄,可以按照某種規(guī)則(如hash取模、range)呵晚,把數(shù)據(jù)切分到多張表去蜘腌。

一張訂單表,按時間range拆分如下:

3.3. 水平分庫分表策略

分庫分表策略一般有幾種饵隙,適用于不同的場景:

  • range范圍
  • hash取模
  • range+hash取拇橹椋混合

3.3.1 range范圍

range,即范圍策略劃分表金矛。比如我們可以將表的主鍵芯急,按照從01000萬劃分為一個表,10002000萬劃分到另外一個表驶俊。如下圖:

當然娶耍,有時候我們也可以按時間范圍來劃分,如不同年月的訂單放到不同的表饼酿,它也是一種range的劃分策略榕酒。

這種方案的優(yōu)點是:

  • 這種方案有利于擴容,不需要數(shù)據(jù)遷移故俐。假設數(shù)據(jù)量增加到5千萬想鹰,我們只需要水平增加一張表就好啦,之前0~4000萬的數(shù)據(jù)药版,不需要遷移辑舷。

缺點:

  • 這種方案會有熱點問題,因為訂單id是一直在增大的槽片,也就是說最近一段時間都是匯聚在一張表里面的何缓。比如最近一個月的訂單都在1000萬~2000萬之間,平時用戶一般都查最近一個月的訂單比較多还栓,請求都打到order_1表啦碌廓,這就導致數(shù)據(jù)熱點問題。

3.3.2 hash取模

hash取模策略:指定的路由key(一般是user_id剩盒、訂單id作為key)對分表總數(shù)進行取模谷婆,把數(shù)據(jù)分散到各個表中。

比如原始訂單表信息,我們把它分成4張分表:

  • 比如id=1波材,對4取模,就會得到1身隐,就把它放到t_order_1;
  • id=3廷区,對4取模,就會得到3贾铝,就把它放到t_order_3;

這種方案的優(yōu)點:

  • hash取模的方式隙轻,不會存在明顯的熱點問題。

缺點:

  • 如果一開始按照hash取模分成4個表了垢揩,未來某個時候玖绿,表數(shù)據(jù)量又到瓶頸了,需要擴容叁巨,這就比較棘手了斑匪。比如你從4張表,又擴容成8張表锋勺,那之前id=5的數(shù)據(jù)是在(5%4=1蚀瘸,即t_order_1),現(xiàn)在應該放到(5%8=5庶橱,即t_order_5)贮勃,也就是說歷史數(shù)據(jù)要做遷移了

3.3.3 range+hash取乃照拢混合

既然range存在熱點數(shù)據(jù)問題寂嘉,hash取模擴容遷移數(shù)據(jù)比較困難,我們可以綜合兩種方案一起嘛枫绅,取之之長泉孩,棄之之短。

比較簡單的做法就是撑瞧,在拆分庫的時候棵譬,我們可以先用range范圍方案,比如訂單id在04000萬的區(qū)間预伺,劃分為訂單庫1;id在4000萬8000萬的數(shù)據(jù)订咸,劃分到訂單庫2,將來要擴容時悉稠,id在8000萬~1.2億的數(shù)據(jù)团滥,劃分到訂單庫3。然后訂單庫內(nèi)擎场,再用hash取模的策略瞒御,把不同訂單劃分到不同的表父叙。

4. 什么時候才考慮分庫分表呢?

4.1 什么時候分表?

如果你的系統(tǒng)處于快速發(fā)展時期趾唱,如果每天的訂單流水都新增幾十萬涌乳,并且,訂單表的查詢效率明變慢時甜癞,就需要規(guī)劃分庫分表了夕晓。一般B+樹索引高度是2~3層最佳,如果數(shù)據(jù)量千萬級別悠咱,可能高度就變4層了蒸辆,數(shù)據(jù)量就會明顯變慢了。不過業(yè)界流傳析既,一般500萬數(shù)據(jù)就要考慮分表了躬贡。

4.2 什么時候分庫

業(yè)務發(fā)展很快,還是多個服務共享一個單體數(shù)據(jù)庫眼坏,數(shù)據(jù)庫成為了性能瓶頸拂玻,就需要考慮分庫了。比如訂單空骚、用戶等纺讲,都可以抽取出來,新搞個應用(其實就是微服務思想)囤屹,并且拆分數(shù)據(jù)庫(訂單庫熬甚、用戶庫)。

5. 分庫分表會導致哪些問題

分庫分表之后肋坚,也會存在一些問題:

  • 事務問題
  • 跨庫關聯(lián)
  • 排序問題
  • 分頁問題
  • 分布式ID

5.1 事務問題

分庫分表后乡括,假設兩個表在不同的數(shù)據(jù)庫,那么本地事務已經(jīng)無效啦智厌,需要使用分布式事務了诲泌。

5.2 跨庫關聯(lián)

跨節(jié)點Join的問題:解決這一問題可以分兩次查詢實現(xiàn)

5.3 排序問題

跨節(jié)點的count,order by,group by以及聚合函數(shù)等問題:可以分別在各個節(jié)點上得到結果后在應用程序端進行合并。

5.4 分頁問題

  • 方案1:在個節(jié)點查到對應結果后铣鹏,在代碼端匯聚再分頁敷扫。
  • 方案2:把分頁交給前端,前端傳來pageSize和pageNo诚卸,在各個數(shù)據(jù)庫節(jié)點都執(zhí)行分頁葵第,然后匯聚總數(shù)量前端。這樣缺點就是會造成空查合溺,如果分頁需要排序卒密,也不好搞。

5.5 分布式ID

數(shù)據(jù)庫被切分后棠赛,不能再依賴數(shù)據(jù)庫自身的主鍵生成機制啦哮奇,最簡單可以考慮UUID膛腐,或者使用雪花算法生成分布式ID。

6. 分庫分表中間件

目前流行的分庫分表中間件比較多:

  • cobar
  • Mycat
  • Sharding-JDBC
  • Atlas
  • TDDL(淘寶)
  • vitess
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者

  • 序言:七十年代末鼎俘,一起剝皮案震驚了整個濱河市哲身,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌贸伐,老刑警劉巖律罢,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異棍丐,居然都是意外死亡,警方通過查閱死者的電腦和手機沧踏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門歌逢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人翘狱,你說我怎么就攤上這事秘案。” “怎么了潦匈?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵阱高,是天一觀的道長。 經(jīng)常有香客問我茬缩,道長赤惊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任凰锡,我火速辦了婚禮未舟,結果婚禮上,老公的妹妹穿的比我還像新娘掂为。我一直安慰自己裕膀,他們只是感情好,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布勇哗。 她就那樣靜靜地躺著昼扛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪欲诺。 梳的紋絲不亂的頭發(fā)上抄谐,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音瞧栗,去河邊找鬼斯稳。 笑死,一個胖子當著我的面吹牛迹恐,可吹牛的內(nèi)容都是我干的挣惰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼憎茂!你這毒婦竟也來了珍语?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤竖幔,失蹤者是張志新(化名)和其女友劉穎板乙,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拳氢,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡募逞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了馋评。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片放接。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖留特,靈堂內(nèi)的尸體忽然破棺而出纠脾,到底是詐尸還是另有隱情,我是刑警寧澤蜕青,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布苟蹈,位于F島的核電站,受9級特大地震影響右核,放射性物質(zhì)發(fā)生泄漏慧脱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一贺喝、第九天 我趴在偏房一處隱蔽的房頂上張望磷瘤。 院中可真熱鬧,春花似錦搜变、人聲如沸采缚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽扳抽。三九已至,卻和暖如春殖侵,著一層夾襖步出監(jiān)牢的瞬間贸呢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工拢军, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留楞陷,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓茉唉,卻偏偏與公主長得像固蛾,于是被迫代替她去往敵國和親结执。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容