0 Github
1 面試題
為什么要分庫分表(設計高并發(fā)系統(tǒng)的時候棚愤,數(shù)據(jù)庫層面該如何設計)岸裙?用過哪些分庫分表中間件似嗤?不同的分庫分表中間件都有什么優(yōu)點和缺點领虹?你們具體是如何對數(shù)據(jù)庫如何進行垂直拆分或水平拆分的?
2 分析
其實這塊肯定是扯到高并發(fā)了睦优,因為分庫分表一定是為了支撐高并發(fā)渗常、數(shù)據(jù)量大兩個問題的。而且現(xiàn)在說實話汗盘,尤其是互聯(lián)網(wǎng)類的公司面試皱碘,基本上都會來這么一下,分庫分表如此普遍的技術問題隐孽,不問實在是不行癌椿,而如果你不知道那也實在是說不過去!
3 業(yè)務分析
說白了菱阵,分庫分表是兩回事兒踢俄,大家可別搞混了,可能是光分庫不分表晴及,也可能是光分表不分庫都办,都有可能。我先給大家拋出來一個場景虑稼。
業(yè)務發(fā)展迅猛琳钉,注冊用戶數(shù)達到了2000萬!每天活躍用戶數(shù)100萬蛛倦!每天單表數(shù)據(jù)量10萬條歌懒!高峰期每秒最大請求達到1000!感覺壓力已經(jīng)有點大了溯壶,為啥呢及皂?因為每天多10萬條數(shù)據(jù),一個月就多300萬條數(shù)據(jù)且改,現(xiàn)在咱們單表已經(jīng)幾百萬數(shù)據(jù)了验烧,馬上就破千萬了。但是勉強還能撐著又跛。高峰期請求現(xiàn)在是1000碍拆,咱們線上部署了幾臺機器,負載均衡搞了一下,數(shù)據(jù)庫撐1000 QPS也還湊合倔监。但是大家現(xiàn)在開始感覺有點擔心了直砂,接下來咋整呢。浩习。静暂。。谱秽。洽蛀。
此時每天活躍用戶數(shù)上千萬,每天單表新增數(shù)據(jù)多達50萬疟赊,目前一個表總數(shù)據(jù)量都已經(jīng)達到了兩三千萬了郊供!扛不住啊近哟!數(shù)據(jù)庫磁盤容量不斷消耗掉驮审!高峰期并發(fā)達到驚人的5000~8000!別開玩笑了吉执,哥疯淫。我跟你保證,你的系統(tǒng)支撐不到現(xiàn)在戳玫,已經(jīng)掛掉了熙掺!
看到你這里你差不多就理解分庫分表是怎么回事兒了,實際上這是跟著公司業(yè)務發(fā)展走的咕宿,你公司業(yè)務發(fā)展越好币绩,用戶就越多,數(shù)據(jù)量越大府阀,請求量越大缆镣,那你單個數(shù)據(jù)庫一定扛不住。
比如你單表都幾千萬數(shù)據(jù)了肌似,你確定你能抗住么费就?
絕對不行诉瓦,單表數(shù)據(jù)量太大川队,會極大影響你的sql執(zhí)行的性能,到了后面你的sql可能就跑的很慢了睬澡。一般來說固额,以經(jīng)驗來看,單表到幾百萬的時候煞聪,性能就會相對差一些了斗躏,你就得分表了。
4 分表
把一個表的數(shù)據(jù)放到多個表中昔脯,然后查詢的時候你就查一個表
比如按照用戶id來分表啄糙,將一個用戶的數(shù)據(jù)就放在一個表中笛臣。然后操作的時候你對一個用戶就操作那個表就好了。這樣可以控制每個表的數(shù)據(jù)量在可控的范圍內(nèi)隧饼,比如每個表就固定在200萬以內(nèi)沈堡。
5 分庫
一個庫一般我們經(jīng)驗而言,最多支撐到并發(fā)2000燕雁,一定要擴容了诞丽,而且一個健康的單庫并發(fā)值你最好保持在每秒1000左右,不要太大拐格。那么你可以將一個庫的數(shù)據(jù)拆分到多個庫中僧免,訪問的時候就訪問一個庫好了。
這就是所謂的分庫分表捏浊,為啥要分庫分表懂衩?你明白了吧
-
分庫分表的由來
6 分庫分表中間件
不同的分庫分表中間件都有什么優(yōu)點和缺點?
比較常見的包括:cobar金踪、TDDL勃痴、atlas、sharding-jdbc热康、mycat
6.1 cobar
阿里b2b團隊開發(fā)和開源的沛申,屬于proxy層方案
早些年還可以用,但是最近幾年都沒更新了
基本沒啥人用了姐军,差不多算是被拋棄的狀態(tài)吧铁材。而且不支持讀寫分離、存儲過程奕锌、跨庫join和分頁等操作著觉。
6.2 TDDL
淘寶團隊開發(fā)的,屬于client層方案
不支持join惊暴、多表查詢等語法饼丘,就是基本的crud語法是ok,但是支持讀寫分離辽话。
目前使用的也不多肄鸽,因為還依賴淘寶的diamond配置管理系統(tǒng),而且已被商用,不再開源
6.3 atlas
360開源的,屬于proxy層方案油啤,以前是有一些公司在用的典徘,但是確實有一個很大的問題就是社區(qū)最新的維護都在6年前了。所以益咬,現(xiàn)在用的公司基本也很少了逮诲。
6.4 sharding-jdbc
當初由當當開源的,屬于client層方案。確實之前用的還比較多一些梅鹦,因為SQL語法支持也比較多裆甩,沒有太多限制,而且目前推出到了2.0版本齐唆,支持分庫分表淑掌、讀寫分離、分布式id生成蝶念、柔性事務(最大努力送達型事務抛腕、TCC事務)。而且確實之前使用的公司會比較多一些(這個在官網(wǎng)有登記使用的公司媒殉,可以看到從2017年一直到現(xiàn)在担敌,是不少公司在用的),目前社區(qū)也還一直在開發(fā)和維護廷蓉,還算是比較活躍全封,算是一個現(xiàn)在也可以選擇的方案。現(xiàn)在已經(jīng)升級為Apache組織的項目
sharding-jdbc這種client層方案的優(yōu)點在于不用部署桃犬,運維成本低刹悴,不需要代理層的二次轉發(fā)請求,性能很高攒暇,但是如果遇到升級啥的需要各個系統(tǒng)都重新升級版本再發(fā)布土匀,各個系統(tǒng)都需要耦合sharding-jdbc的依賴;
6.5 mycat
基于cobar改造的形用,屬于proxy層方案就轧,支持的功能非常完善,而且目前應該是非程锒龋火的而且不斷流行的數(shù)據(jù)庫中間件妒御,社區(qū)很活躍,也有一些公司開始在用了镇饺。但是確實相比于sharding jdbc來說乎莉,年輕一些,經(jīng)歷的錘煉少一些奸笤。
mycat這種proxy層方案的缺點在于需要部署惋啃,自己及運維一套中間件,運維成本高揭保,但是好處在于對于各個項目是透明的肥橙,如果遇到升級之類的都是自己中間件那里搞就行了魄宏。
6.6 小結
所以綜上所述秸侣,現(xiàn)在其實建議考量的,就是sharding-jdbc和mycat,這兩個都可以去考慮使用味榛。
通常來說椭坚,這兩個方案其實都可以選用,但是我個人建議中小型公司選用sharding-jdbc搏色,client層方案輕便善茎,而且維護成本低,不需要額外增派人手频轿,而且中小型公司系統(tǒng)復雜度會低一些垂涯,項目也沒那么多;
但是中大型公司最好還是選用mycat這類proxy層方案航邢,因為可能大公司系統(tǒng)和項目非常多耕赘,團隊很大,人員充足膳殷,那么最好是專門弄個人來研究和維護mycat操骡,然后大量項目直接透明使用即可。
7 數(shù)據(jù)庫的垂直拆分或水平拆分
-
數(shù)據(jù)庫如何拆分
7.1 水平拆分
把一個表的數(shù)據(jù)給弄到多個庫的多個表里赚窃,但每個庫的表結構都一樣册招,只不過每個庫中表放的數(shù)據(jù)是不同的,所有庫表的數(shù)據(jù)加起來就是全部數(shù)據(jù)
水平拆分的意義
將數(shù)據(jù)均勻放更多的庫里勒极,然后用多個庫來抗更高的并發(fā)是掰,還有就是用多個庫的存儲容量來進行擴容。
7.2 垂直拆分
把一個有很多字段的表給拆分成多個表辱匿,或者是多個庫
每個庫表的結構都不一樣冀惭,每個庫表都包含部分字段。一般來說掀鹅,會將較少的訪問頻率很高的字段放到一個表里去散休,然后將較多的訪問頻率很低的字段放到另外一個表里去
因為數(shù)據(jù)庫是有緩存的,訪問頻率高的行字段越少乐尊,就可以在緩存里緩存更多的行戚丸,性能就越好。這個一般在表層面做的較多一些扔嵌。
這個其實挺常見的限府,很多同學可能自己都做過,把一個大表拆開痢缎,訂單表胁勺、訂單支付表、訂單商品表独旷。
還有表層面的拆分署穗,就是分表寥裂,將一個表變成N個表,就是讓每個表的數(shù)據(jù)量控制在一定范圍內(nèi)案疲,保證SQL的性能
否則單表數(shù)據(jù)量越大封恰,SQL性能就越差。一般是200萬行左右褐啡,不要太多诺舔,但是也得看具體你怎么操作,也可能是500萬备畦,或者是100萬低飒。你的SQL越復雜,就最好讓單表行數(shù)越少
無論是分庫還是分表懂盐,上面說的那些數(shù)據(jù)庫中間件都是可以支持的逸嘀。就是基本上那些中間件可以做到你分庫分表之后,中間件可以根據(jù)你指定的某個字段值允粤,比如說userid崭倘,自動路由到對應的庫上去,然后再自動路由到對應的表里去类垫。
你就得考慮一下司光,你的項目里該如何分庫分表?一般來說
- 垂直拆分悉患,你可以在表層面來做残家,對一些字段特別多的表做一下拆分
- 水平拆分,你可以說是并發(fā)承載不了售躁,或者是數(shù)據(jù)量太大坞淮,容量承載不了,你給拆了陪捷,按什么字段來拆回窘,你自己想好
- 分表,你考慮一下市袖,你如果哪怕是拆到每個庫里去啡直,并發(fā)和容量都ok了,但是每個庫的表還是太大了苍碟,那么你就分表酒觅,將這個表分開,保證每個表的數(shù)據(jù)量并不是很大
8 分庫分表的方式
8.1 按照range分
就是每個庫一段連續(xù)的數(shù)據(jù)微峰,一般按比如時間范圍來的舷丹,但是這種一般較少用,因為很容易產(chǎn)生熱點問題蜓肆,大量的流量都打在最新的數(shù)據(jù)上了
好處
后面擴容的時候颜凯,就很容易谋币,因為你只要預備好,給每個月都準備一個庫就可以了装获,到了一個新的月份的時候瑞信,自然而然厉颤,就會寫新的庫了
缺點
但是大部分的請求穴豫,都是訪問最新的數(shù)據(jù)。實際生產(chǎn)用range逼友,要看場景精肃,你的用戶不是僅僅訪問最新的數(shù)據(jù),而是均勻的訪問現(xiàn)在的數(shù)據(jù)以及歷史的數(shù)據(jù)
8.2 按照某個字段hash
一下均勻分散帜乞,較為常用司抱。
好處
可以平均分配沒給庫的數(shù)據(jù)量和請求壓力
壞處
擴容起來比較麻煩,會有一個數(shù)據(jù)遷移的過程
參考
- 《Java工程師面試突擊第1季-中華石杉老師》