分庫分表的幾個面試題


分庫分表是高並發高可用系統的一個重要的點,互聯網公司面試常常會問道。

為什么要分庫分表(設計高並發系統的時候,數據庫層面應該如何設計)?

首先要清楚,分庫和分表是兩回事,是兩個獨立的概念。分庫和分表都是為了防止數據庫服務因為同一時間的訪問量(增刪查改)過大導致宕機而設計的一種應對策略。

為什么要分庫

按一般的經驗來說,一個單庫最多支持並發量到2000,且最好保持在1000。如果有20000並發量的需求,這時就需要擴容了,可以將一個庫的數據拆分到多個庫中,訪問的時候根據一定條件訪問單庫,緩解單庫的性能壓力。

為什么要分表

分表也是一樣的,如果單表的數據量太大,就會影響SQL語句的執行性能。分表就是按照一定的策略將單表的數據拆分到多個表中,查詢的時候也按照一定的策略去查詢對應的表,這樣就將一次查詢的數據范圍縮小了。比如按照用戶id來分表,將一個用戶的數據就放在一個表中,crud先通過用戶id找到那個表在進行操作就可以了。這樣就把每個表的數據量控制在一定范圍內,提升SQL語句的執行性能。

用過哪些分庫分表的中間件?不同的分庫分表中間件都有什么優點和缺點?

分庫分表常見的中間件有:cobar、TDDL、atlas、sharding-jdbc和mycat等。

cobar

cobar是阿里的b2b團隊開發和開源的,屬於proxy層方案,介於應用服務器和數據庫服務器之間。應用程序通過JDBC驅動訪問cobar集群,cobar根據SQL和分庫規則對SQL做分解,然后分發到MySQL集群不同的數據庫實例上執行。cobar並不支持讀寫分離、存儲過程、跨庫join和分頁等操作。早些年還可以用,但是最近幾年都沒更新了,基本沒啥人用,算是淘汰了。

TDDL

TDDL是淘寶團隊開發的,屬於client層方案。支持基本的crud語法和讀寫分離,但是並不支持join、多表查詢等語法。目前使用的也不多,因為使用還需要依賴淘寶的diamond配置管理系統。

atlas

atlas是360開源的,屬於proxy層方案。以前是有一些公司再用的,但是社區最新的維護都在5年前了,現在用的公司也基本沒有了。

sharding-jdbc

sharding-jdbc是當當開源的,屬於client層方案。這個中間件對SQL語法的支持比較多,沒有太多限制。2.0版本也開始支持分庫分表、讀寫分離、分布式id生成、柔性事務(最大努力送達型事務、TCC事務)。目前社區也還一直在開發和維護,算是比較活躍,是一個現在也可以選擇的方案。

mycat

mycat是基於cobar改造的,屬於proxy層方案。其支持的功能十分完善,是目前非常火的一個數據庫中間件。社區很活躍,不斷在更新。相比於sharding-jdbc來說,年輕一些,經歷的錘煉也少一些。

總結

綜上所述,現在建議考量使用的就是sharding-jdbc和mycat。

sharding-jdbc這種client層的優點在於不用部署,因此運維成本也就比較低。同時因為不需要代理層的二次轉發請求,性能很高。但是如果遇到升級的話,需要各個系統都重新升級版本再發布,因為各個系統都需要耦合sharding-jdbc的依賴。

mycat這種proxy方案的缺點在於需要部署,因此運維成本也就比較高。但是優點在於其對於各個項目是透明(解耦)的,如果要升級的話只需要在中間件處理就行了。

通常來說,這兩個方案都是可以選用的。但是建議中小型公司選用sharding-jdbc比較好,因為client層方案輕便,維護成本低;建議中大型公司選用mycat比較好,因為proxy層方案可以應對多個系統和項目大量使用,雖然維護成本相對來說會較高,但是中大型公司還缺這點人力嗎。

具體如何對數據庫進行垂直拆分或水平拆分?

水平拆分的概念

水平拆分的意思,就是把一個表的數據拆分到多個庫的多個表里面去。這里面的每個庫的表結構都是一樣的,只不過是表中存放的數據不一樣,每個庫表的數據匯總起來就是全部數據。水平拆分的意義在於將數據均勻地存放在各個庫表里,依靠多個庫來杠更高的並發,而且還能借助多個庫的存儲容量來進行擴容。

垂直拆分的概念

垂直拆分的意思,就是把一個有很多字段的表給拆分成多個表或者多個庫上面去,每個庫表的結構都不一樣,每個庫表都包含部分字段。一般來說,會將較少的訪問頻率很高的字段放到一個表里面去,然后將較多的訪問頻率很低的字段放到另外一個表里面去。因為數據庫是有緩存的,你訪問頻率高的行字段越少,就可以在緩存里面緩存更多的行,性能也就越好。這個一般在表層面做的較多一些。

水平拆分和垂直拆分的場景

所謂表層面的拆分,就是分表。具體就是將一個表拆分為N個表,讓每個表的數據量控制在一定的范圍內,保證SQL的性能。否則,單表的數據量越大,SQL的性能也就越差,一般是200萬行左右,不要太多。如果你的SQL越復雜,就盡量讓單表的行數越少。

無論是分庫還是分表,主流的數據庫中間件都是可以支持的。這些中間件可以在你分庫分表之后,根據指定的某個字段值自動路由到對應的庫和對應的表上面。這時就只要考慮項目如何分庫分表就行了。一般來說,垂直拆分,可以在表層面做,即對一些字段特別多的表做一下拆分;水平拆分的話,可能是因為並發承載不了或容量承載不了,也就可以按某個字段去分布到不同的庫表里面去。

分庫分表的兩個方案

這里說一下兩種分庫分表的方案和它們的優缺點。

1.按照range來分。比如說按照時間范圍來分庫分表,每個庫表中存放的都是連續時間范圍的數據。但是這種方式一般很少用,因為很容易會產生熱點問題,大量的流量都打在最新的數據上了。這種方案的優點在於擴容的時候非常簡單,比如只要預備好每個月都准備一個庫就可以了,到了下一個新的月份自動將數據寫入新的庫。缺點則是,如果大部分請求都是訪問最新的數據,那么在這里,分庫分表的設計目的就只是簡單的擴容,而不是為了應對高並發了。

2.按照hash分發。按照某個字段的hash值均勻分散,這個較為常用。優點在於可以平均分配每個庫表的數據量和請求壓力;缺點在於擴容比較麻煩,因為會存在一個數據遷移的過程,即之前的數據需要重新計算hash值並重新分配到不同的庫表中。

 

"一個人最幸福的時刻,就是找對了人。TA會包容你的不足,並愛着你的一切。"


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM