爲何要分庫分表(設計高併發系統的時候,數據庫層面該如何設計)?用過哪些分庫分表中間件?不一樣的分庫分表中間件都有什麼優勢和缺點?如何對數據庫如何進行垂直拆分或水平拆分的?面試
其實這塊確定是扯到高併發了,由於分庫分表必定是爲了支撐高併發、數據量大兩個問題的。並且如今說實話,尤爲是互聯網類的公司面試,基本上都會來這麼一下,分庫分表如此廣泛的技術問題,不問實在是不行,而若是你不知道那也實在是說不過去!sql
說白了,分庫分表是兩回事兒,你們可別搞混了,多是光分庫不分表,也多是光分表不分庫,都有可能。數據庫
好比你單表都幾千萬數據了,你肯定你能扛住麼?絕對不行,單表數據量太大,會極大影響你的 sql 執行的性能,到了後面你的 sql 可能就跑的很慢了。通常來講,就以個人經驗來看,單表到幾百萬的時候,性能就會相對差一些了,你就得分表了。緩存
分表是啥意思?就是把一個表的數據放到多個表中,而後查詢的時候你就查一個表。好比按照用戶 id 來分表,將一個用戶的數據就放在一個表中。而後操做的時候你對一個用戶就操做那個表就行了。這樣能夠控制每一個表的數據量在可控的範圍內,好比每一個表就固定在 200 萬之內。服務器
分庫是啥意思?就是你一個庫通常咱們經驗而言,最多支撐到併發 2000,必定要擴容了,並且一個健康的單庫併發值你最好保持在每秒 1000 左右,不要太大。那麼你能夠將一個庫的數據拆分到多個庫中,訪問的時候就訪問一個庫好了。併發
這就是所謂的分庫分表,爲啥要分庫分表?你明白了吧。運維
# | 分庫分表前 | 分庫分表後 |
---|---|---|
併發支撐狀況 | MySQL 單機部署,扛不住高併發 | MySQL從單機到多機,能承受的併發增長了多倍 |
磁盤使用狀況 | MySQL 單機磁盤容量幾乎撐滿 | 拆分爲多個庫,數據庫服務器磁盤使用率大大下降 |
SQL 執行性能 | 單表數據量太大,SQL 越跑越慢 | 單表數據量減小,SQL 執行效率明顯提高 |
這個其實就是看看你瞭解哪些分庫分表的中間件,各個中間件的優缺點是啥?而後你用過哪些分庫分表的中間件。分佈式
比較常見的包括:高併發
阿里 b2b 團隊開發和開源的,屬於 proxy 層方案,就是介於應用服務器和數據庫服務器之間。應用程序經過 JDBC 驅動訪問 cobar 集羣,cobar 根據 SQL 和分庫規則對 SQL 作分解,而後分發到 MySQL 集羣不一樣的數據庫實例上執行。早些年還能夠用,可是最近幾年都沒更新了,基本沒啥人用,差很少算是被拋棄的狀態吧。並且不支持讀寫分離、存儲過程、跨庫 join 和分頁等操做。性能
淘寶團隊開發的,屬於 client 層方案。支持基本的 crud 語法和讀寫分離,但不支持 join、多表查詢等語法。目前使用的也很少,由於還依賴淘寶的 diamond 配置管理系統。
360 開源的,屬於 proxy 層方案,之前是有一些公司在用的,可是確實有一個很大的問題就是社區最新的維護都在 5 年前了。因此,如今用的公司基本也不多了。
噹噹開源的,屬於 client 層方案。確實以前用的還比較多一些,由於 SQL 語法支持也比較多,沒有太多限制,並且目前推出到了 2.0 版本,支持分庫分表、讀寫分離、分佈式 id 生成、柔性事務(最大努力送達型事務、TCC 事務)。並且確實以前使用的公司會比較多一些(這個在官網有登記使用的公司,能夠看到從 2017 年一直到如今,是有很多公司在用的),目前社區也還一直在開發和維護,還算是比較活躍,我的認爲算是一個如今也能夠選擇的方案。
基於 cobar 改造的,屬於 proxy 層方案,支持的功能很是完善,並且目前應該是很是火的並且不斷流行的數據庫中間件,社區很活躍,也有一些公司開始在用了。可是確實相比於 sharding jdbc 來講,年輕一些,經歷的錘鍊少一些。
綜上,如今其實建議考量的,就是 sharding-jdbc 和 mycat,這兩個均可以去考慮使用。
sharding-jdbc 這種 client 層方案的優勢在於不用部署,運維成本低,不須要代理層的二次轉發請求,性能很高,可是若是遇到升級啥的須要各個系統都從新升級版本再發布,各個系統都須要耦合 sharding-jdbc 的依賴;
mycat 這種 proxy 層方案的缺點在於須要部署,本身運維一套中間件,運維成本高,可是好處在於對於各個項目是透明的,若是遇到升級之類的都是本身中間件那裏搞就好了。
一般來講,這兩個方案其實均可以選用,可是我我的建議中小型公司選用 sharding-jdbc,client 層方案輕便,並且維護成本低,不須要額外增派人手,並且中小型公司系統複雜度會低一些,項目也沒那麼多;可是中大型公司最好仍是選用 mycat 這類 proxy 層方案,由於可能大公司系統和項目很是多,團隊很大,人員充足,那麼最好是專門弄我的來研究和維護 mycat,而後大量項目直接透明使用便可。
水平拆分的意思,就是把一個表的數據給弄到多個庫的多個表裏去,可是每一個庫的表結構都同樣,只不過每一個庫表放的數據是不一樣的,全部庫表的數據加起來就是所有數據。水平拆分的意義,就是將數據均勻放更多的庫裏,而後用多個庫來扛更高的併發,還有就是用多個庫的存儲容量來進行擴容。
垂直拆分的意思,就是把一個有不少字段的表給拆分紅多個表,或者是多個庫上去。每一個庫表的結構都不同,每一個庫表都包含部分字段。通常來講,會將較少的訪問頻率很高的字段放到一個表裏去,而後將較多的訪問頻率很低的字段放到另一個表裏去。由於數據庫是有緩存的,你訪問頻率高的行字段越少,就能夠在緩存裏緩存更多的行,性能就越好。這個通常在表層面作的較多一些。
這個其實挺常見的,不必定我說,你們不少同窗可能本身都作過,把一個大表拆開,訂單表、訂單支付表、訂單商品表。
還有表層面的拆分,就是分表,將一個表變成 N 個表,就是讓每一個表的數據量控制在必定範圍內,保證 SQL 的性能。不然單表數據量越大,SQL 性能就越差。通常是 200 萬行左右,不要太多,可是也得看具體你怎麼操做,也多是 500 萬,或者是 100 萬。你的SQL越複雜,就最好讓單錶行數越少。
好了,不管分庫仍是分表,上面說的那些數據庫中間件都是能夠支持的。就是基本上那些中間件能夠作到你分庫分表以後,中間件能夠根據你指定的某個字段值,好比說 userid,自動路由到對應的庫上去,而後再自動路由到對應的表裏去。
你就得考慮一下,你的項目裏該如何分庫分表?通常來講,垂直拆分,你能夠在表層面來作,對一些字段特別多的表作一下拆分;水平拆分,你能夠說是併發承載不了,或者是數據量太大,容量承載不了,你給拆了,按什麼字段來拆,你本身想好;分表,你考慮一下,你若是哪怕是拆到每一個庫裏去,併發和容量都ok了,可是每一個庫的表仍是太大了,那麼你就分表,將這個表分開,保證每一個表的數據量並非很大。
並且這兒還有兩種分庫分表的方式:
range 來分,好處在於說,擴容的時候很簡單,由於你只要預備好,給每月都準備一個庫就能夠了,到了一個新的月份的時候,天然而然,就會寫新的庫了;缺點,可是大部分的請求,都是訪問最新的數據。實際生產用 range,要看場景。
hash 分發,好處在於說,能夠平均分配每一個庫的數據量和請求壓力;壞處在於說擴容起來比較麻煩,會有一個數據遷移的過程,以前的數據須要從新計算 hash 值從新分配到不一樣的庫或表。