為什么分庫分表?(設(shè)計(jì)高并發(fā)系統(tǒng)時(shí)候昼窗,數(shù)據(jù)庫層面該如何設(shè)計(jì)是趴?)
分庫和分表是兩回事,大家別搞混了澄惊,可能是光分庫不分表唆途,也可能是光分表不分庫,都有可能掸驱。
分表:
就是把一個(gè)表的數(shù)據(jù)放到多個(gè)表中肛搬,然后查詢的時(shí)候你就查一個(gè)表。比如按照用戶id來分表毕贼,將一個(gè)用戶的數(shù)據(jù)就放在一個(gè)表中温赔。然后操作的時(shí)候你對一個(gè)用戶就操作那個(gè)表就好了。這樣可以控制每個(gè)表的數(shù)據(jù)量在可控的范圍內(nèi)鬼癣,比如每個(gè)表就固定在200萬以內(nèi)陶贼。
分庫:
就是你一個(gè)庫一般我們經(jīng)驗(yàn)而言,最多支撐到并發(fā)2000待秃,一定要擴(kuò)容了骇窍,而且一個(gè)健康的單庫并發(fā)值你最好保持在每秒1000左右,不要太大锥余。那么你可以將一個(gè)庫的數(shù)據(jù)拆分到多個(gè)庫中腹纳,訪問的時(shí)候就訪問一個(gè)庫好了。
分庫分表中間件,不同的分庫分表中間件有什么優(yōu)點(diǎn)和缺點(diǎn)嘲恍?
常見的中間件:cobar足画、TDDL、atlas佃牛,sharding-jdbc淹辞、mycat
- cobar:阿里b2b團(tuán)隊(duì)開發(fā)和開源的,屬于proxy層方案俘侠。早些年還可以用象缀,但是最近幾年都沒更新了,基本沒啥人用爷速,差不多算是被拋棄的狀態(tài)吧央星。而且不支持讀寫分離、存儲過程惫东、跨庫join和分頁等操作莉给。
- TDDL:淘寶團(tuán)隊(duì)開發(fā)的,屬于client層方案廉沮。不支持join颓遏、多表查詢等語法,就是基本的crud語法是ok滞时,但是支持讀寫分離叁幢。目前使用的也不多,因?yàn)檫€依賴淘寶的diamond配置管理系統(tǒng)坪稽。
- atlas:360開源的曼玩,屬于proxy層方案,以前是有一些公司在用的刽漂,但是確實(shí)有一個(gè)很大的問題就是社區(qū)最新的維護(hù)都在5年前了演训。所以,現(xiàn)在用的公司基本也很少了贝咙。
- sharding-jdbc:當(dāng)當(dāng)開源的样悟,屬于client層方案。確實(shí)之前用的還比較多一些庭猩,因?yàn)镾QL語法支持也比較多窟她,沒有太多限制,而且目前推出到了2.0版本蔼水,支持分庫分表震糖、讀寫分離、分布式id生成趴腋、柔性事務(wù)(最大努力送達(dá)型事務(wù)吊说、TCC事務(wù))论咏。而且確實(shí)之前使用的公司會比較多一些(這個(gè)在官網(wǎng)有登記使用的公司,可以看到從2017年一直到現(xiàn)在颁井,是不少公司在用的)厅贪,目前社區(qū)也還一直在開發(fā)和維護(hù),還算是比較活躍雅宾,個(gè)人認(rèn)為算是一個(gè)現(xiàn)在也可以選擇的方案养涮。
- mycat:基于cobar改造的,屬于proxy層方案眉抬,支持的功能非常完善贯吓,而且目前應(yīng)該是非常火的而且不斷流行的數(shù)據(jù)庫中間件蜀变,社區(qū)很活躍悄谐,也有一些公司開始在用了。但是確實(shí)相比于sharding jdbc來說昏苏,年輕一些尊沸,經(jīng)歷的錘煉少一些威沫。
sharding-jdbc這種client層方案的優(yōu)點(diǎn)在于不用部署贤惯,運(yùn)維成本低,不需要代理層的二次轉(zhuǎn)發(fā)請求棒掠,性能很高孵构,但是如果遇到升級啥的需要各個(gè)系統(tǒng)都重新升級版本再發(fā)布,各個(gè)系統(tǒng)都需要耦合sharding-jdbc的依賴烟很。
mycat這種proxy層方案的缺點(diǎn)在于需要部署颈墅,自己及運(yùn)維一套中間件,運(yùn)維成本高雾袱,但是好處在于對于各個(gè)項(xiàng)目是透明的恤筛,如果遇到升級之類的在中間件那里搞就好。
如何對數(shù)據(jù)庫垂直拆分或水平拆分的
水平拆分:把一個(gè)表的數(shù)據(jù)給弄到多個(gè)庫的多個(gè)表中芹橡,但是每個(gè)庫的表結(jié)構(gòu)都一樣毒坛,只不過每個(gè)庫表放的數(shù)據(jù)是不同的,所有庫表的數(shù)據(jù)加起來就是全部數(shù)據(jù)林说,水平拆分的意義煎殷,就是將數(shù)據(jù)均勻放到更多庫中,然后用多個(gè)庫來抗高并發(fā)腿箩,還有就是用多個(gè)庫的存儲容量來進(jìn)行擴(kuò)容豪直。
垂直拆分:就是把一個(gè)很多字段的表拆分成多個(gè)表,或多個(gè)庫中珠移,每個(gè)庫的結(jié)構(gòu)都不一樣弓乙,每個(gè)庫表都包含部分字段末融,一般來說,將較少的訪問頻率很高字段放在一個(gè)表暇韧,然后將較多的訪問頻率很低的字段放到另外一個(gè)表中滑潘,因?yàn)閿?shù)據(jù)庫是有緩存的,你訪問頻率高的行字段越少锨咙,就可以在緩存里緩存更多行语卤,性能就越好,這個(gè)一般在表層面做的較多酪刀。
兩種分表分庫方式(range&hash)
- range:
每個(gè)庫一段連續(xù)的數(shù)據(jù)粹舵,這個(gè)一般都是按比如時(shí)間范圍來的,但是這種一般較少用骂倘,很容易產(chǎn)生熱點(diǎn)問題眼滤,大量的流量打在最新的數(shù)據(jù)上。
好處在于历涝,后面擴(kuò)展時(shí)诅需,很容易,因?yàn)槟阒灰A(yù)備好荧库,給每個(gè)月都準(zhǔn)備一個(gè)庫堰塌,到了一個(gè)新的月份,自然就寫新的庫分衫。
缺點(diǎn)在于场刑,大部分請求都是訪問新的數(shù)據(jù),實(shí)際生產(chǎn)使用range蚪战,要看場景牵现,用戶不僅僅訪問最新的數(shù)據(jù),而是均勻的訪問現(xiàn)在的數(shù)據(jù)以及歷史數(shù)據(jù)邀桑。 - hash:
按照某個(gè)字段hash一下均勻分散
好處在于瞎疼,可以平均分配每個(gè)庫的數(shù)據(jù)量和請求壓力。
壞處在于壁畸,擴(kuò)容起來比較麻煩贼急,會有一個(gè)數(shù)據(jù)遷移的過程。