有关分库分表你想知道的,都在这儿了
面試的時候,聊到高并發或者大數據,很多時候會聊到數據庫分庫分表相關的問題,因為你的數據庫單機抗不了多少并發量,而且用戶量上來之后,數據庫容納的數據量也是有限的。
如果單表數據量過大,SQL稍微復雜點,查詢就會很慢。而且,現在稍微大點的互聯網公司,分庫分表都成為了標配。如果你現在出去面試,面試官問你分庫分表相關的問題,你說你沒做過,人家立馬會覺得你沒有高并發的經驗,做的都是比較簡單的業務系統。
MySQL單表通常500w條數據以內比較合適,不建議超過1000w,如果超過1000w了建議要做分庫分表了。
比如常見的分庫分表面試題:
為什么要分庫分表?
用過哪些分庫分表的中間件?
不同的分庫分表中間件都有什么優缺點?
你們具體是如何對數據庫進行進行垂直拆分或水平拆分的?
你們是如何把系統不停機遷移到分庫分表的?
分庫分表之后全局id咋生成?
一般開發一個新業務系統,由于需要快速打樣,盡快上線,所以一開始基本都是單庫系統。
圖1 單庫
可能業務發展迅猛,過了幾個月,使用用戶就達到了 1000 萬!每天活躍用戶數 100 萬!每天單表數據量 10 萬條!高峰期每秒最大請求達到 1000QPS!
現在大家感覺壓力已經有點大了,為啥呢?因為每天多 10 萬條數據,一個月就新增300 萬條數據,現在咱們單表已經幾百萬數據了,馬上就破千萬了。
目前用戶量還在不斷增長,每天新增的數據量也在不斷變多,照目前這個勢頭,系統恐怕堅持不了多久。業務系統倒是可以很容易的增加一些機器。
圖2?業務系統增加機器
但大多數請求集中在20%的時間,80%的時間請求量還可以支撐。這20%時間段里,每秒并發量和在線用戶量都達到峰值,對數據庫的壓力也是每天最大的時候。這時候,你可以在業務系統與MySQL數據庫中間加一個MQ削峰,比如使用kafka,緩解一下過高的并發請求。假如高峰期每秒8000個請求,異步寫系統每秒消費2000個請求。經過MQ削峰后,會在消息隊列里緩存很多未執行的數據庫操作,等待異步寫系統慢慢的消費掉。
圖3?MQ削峰
業務系統能夠增加機器擴容,沒什么問題,MQ削峰也能撐一撐,但瓶頸在于MySQL。主要有3個問題:
(1)MySQL單機扛不住高并發
(2)磁盤容量快慢了;
(3)SQL越跑越慢;
如果要讓MySQL承擔更高的并發,比如現在是8000請求/s,異步寫系統也可以擴容到多臺機器,MQ消費6000請求/s,這時候該怎么辦?你首先得分庫。
圖4?分庫
假如現在分了3個庫,每個庫的表和表結構都是一模一樣的,MQ分為3個partition,每個異步寫系統都只消費一個partition。每個異步寫系統,會根據每條數據的某個id分發到各個數據庫里去,比如是userId,每個userId相同的數據分發到同一臺機器上去。
分庫前單庫每天可能增加100w數據,現在每個庫增加30多萬條數據。數據庫可以承受的并發增加了3倍,數據庫的磁盤使用率大大降低,本來一個庫磁盤很快就寫滿了,現在大大降低了,同時SQL語句執行性能也提高了。
分庫之后,每個表的數據庫依舊很多,SQL語句執行起來性能依舊不高,所以還是要考慮分表,打造多庫多表的系統。
千萬不能因為技術原因制約了公司業務的發展。
分表
比如你單表都幾千萬數據了,你確定你能扛住么?肯定不行,單表數據量太大,會極大影響你的SQL執行的性能,大量的連接卡在MySQL等待執行,不僅會把你MySQL數據庫拖垮,還會產生連鎖反應,把你的業務系拖垮。一般來說,單表到幾百萬的時候,性能就會越來越差,你就得分表了。
分表是啥意思?
就是把一個表的數據放到多個表中,然后查詢的時候你就查一個表。比如按照用戶 id 來分表,將一個用戶的數據就放在一個表中。然后操作的時候你對一個用戶就操作那個表就好了。這樣可以控制每個表的數據量在可控的范圍內,比如每個表就固定在500萬以內。
分庫
分庫是啥意思?就經驗而言,單庫最多支撐到并發2000,一定要擴容了,而且一個健康的單庫并發值最好保持在每秒1000以內,不要太大。那么你可以將一個庫的數據拆分到多個庫中,訪問的時候就訪問一個庫好了。
常用的分庫分表中間件以及優缺點
ShardingSphere?(Sharding-jdbc)
Mycat
Sharding-Sphere是一套開源的分布式數據庫中間件解決方案,屬于client端方案,也就是你的業務系統只需要引用它的jar包,就可以使用了。Sharding-Sphere目前社區也還一直在開發和維護,還算是比較活躍,個人認為算是一個現在也可以選擇的方案。
mycat是基于Cobar改造的,屬于 proxy 層方案,支持的功能非常完善,而且目前應該是非常火的而且不斷流行的數據庫中間件,社區很活躍,也有一些公司開始在用了。但是確實相比于 Sharding jdbc 來說,年輕一些,經歷的錘煉少一些。
比較:
Sharding-Sphere這種client端方案的優點在于不用部署,運維成本低,不需要代理層的二次轉發請求,性能很高,但是如果遇到升級啥的需要各個業務系統都重新升級版本再發布,各個系統都需要耦合Sharding-Sphere即可。
Mycat 這種proxy層方案的缺點在于需要單獨部署,自己運維一套中間件,運維成本高,但是好處在于對于各個項目是透明的,如果需要升級只需要單獨升級mycat就行了。
通常來說,這兩個方案其實都可以選用,但是個人建議中小型公司選用 Sharding-Sphere,client 層方案輕量級,而且維護成本低,不需要額外增派人手去維護,而且中小型公司系統復雜度會低一些,項目也沒那么多。
但是中大型公司最好還是選用Mycat這類proxy層方案,因為可能大公司系統和項目非常多,團隊很大,人員充足,那么最好是專門弄個人來研究和維護Mycat,然后各個項目直接透明使用即可。
你們是如何對數據庫進行垂直拆分或水平拆分的?
水平拆分的意思,就是把一個表的數據給弄到多個庫的多個表里去,但是每個庫的表結構都一樣,只不過每個庫表放的數據是不同的,所有庫表的數據加起來就是全部數據。水平拆分的意義,就是將數據均勻放更多的庫里,然后用多個庫來扛更高的并發,還有就是用多個庫的存儲容量來進行擴容。
圖5?水平拆分
垂直拆分,就是把一個有很多字段的表給拆分成多個表,或者是多個庫上去。每個庫表的結構都不一樣,每個庫表都包含部分字段。
一般來說,會將訪問頻率很高的字段放到一個表里去,然后將訪問頻率很低的字段放到另外一個表里去。因為數據庫是有緩存的,你訪問頻率高的行字段越少,就可以在緩存里緩存更多的行,性能就越好。這個一般在表層面做的較多一些。
圖6 垂直拆分
假如有600w數據,現在要分庫分表,綜合來看分庫分表可能是這樣的:
圖7 分庫分表示意圖
常見的分庫分表是,是根據某個id取模先定位到庫,再定位到表的。可以根據userId和orderId取模。也可以根據數據的range去分庫分表,比如根據數據的創建時間。
引入了分庫分表中間件,那么我們的系統就不用自己考慮每條數據路由到哪個庫哪張表了。就可以直接將SQL丟給分庫分表中間件,由它根據配置,路由到相應的庫和表里去,此時MQ和異步寫系統也可以去掉了,因為分庫分表后,相當于每個業務系統承擔的壓力就大大減小了。
圖8 分庫分表示意圖
總結
本文分享了分庫分表的由來,業務不斷發展的驅動下,改造系統分庫分表是架構升級的必經之路。同時講了業內常用的分庫分表中間件ShardingSphere和Mycat以及他們的優缺點,最后分享了如何對數據庫進行垂直拆分和水平拆分,以及具體分庫分表數據路由方法。
有道無術,術可成;有術無道,止于術
歡迎大家關注Java之道公眾號
好文章,我在看??
總結
以上是生活随笔為你收集整理的有关分库分表你想知道的,都在这儿了的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: docker -v 覆盖了容器中的文件_
- 下一篇: r语言折线图_R语言做多变量可视化分析?