資料庫分庫分表估計很多夥伴都沒有實踐過,就是因為自己公司的業務不是很多,沒有那麼多數據。假如有一天項目的人數上來了,你寫的系統支撐不住了,希望這篇文章帶給你一絲絲的思路。
前言
在面試過程中你是不是會經常遇到對於資料庫分庫分表你有什麼方案啊!
在平時看博客時你是不是也經常刷到MySQL如何分庫分表。
然而你是不是點進去看了不到10秒就直接退出窗口。
那是因為寫的文章不是什麼水平切分,就是垂直切割,在一個自身所在的公司根本使用不到。
如果你只知道分庫分表但是不知道怎麼弄的話,花個五分鐘看完你會收穫到不一樣的思路。
一、初始架構
公司的規模小,項目針對的用戶群體屬於小眾。日活就幾千、幾萬的用戶這樣的數據每天的資料庫單表增加一般不會超過10萬。並發更不沾邊了。
這種項目規模,我們就是認真、快速開發業務邏輯,提升用戶體驗,從而提升項目的用戶粘度並達到收納更多用戶的準備。
這個時候我們項目一臺16核32G的伺服器就完全可以了,可以將資料庫單獨放一個伺服器,也可以都放在一個伺服器。
這個時候項目架構圖是這個樣子的。
二、用戶開始激增解決方案
在經歷了第一階段後,由於項目的用戶體驗度極高,項目又吸引了大量的用戶。
這時我們項目日活達到了百萬級別,註冊用戶也超過了千萬。這個數據是咔咔根據之前公司項目數據推算的。
這時每天單表數據新增達到了100萬,並發請求每秒也達到了上萬。這時單系統就扛不住了。
假設每天就固定新增100萬,每月就是3000萬 ,一年就是接近5億數據。
資料庫以這種速度運行下去,數據到2000W到3000W還能勉強撐住,但是你會發現資料庫日誌會出現越來越多的慢查詢。
雖說並發1W,但是我們可以部署個10臺機器或者20臺機器,平均每臺機器承擔500到1000的請求,還是綽綽有餘的。
但是資料庫方面還是用一臺伺服器支撐著每秒上萬的請求,那麼你將會遇到以下問題。
資料庫所在的伺服器磁碟IO、網絡帶寬、CPU負載、內存消耗都會非常高
單表數據已經很大,SQL性能已經已經出現下坡階段,加上資料庫伺服器負載太高導致性能下降,會直接導致SQL性能更差
這個時候最明顯的感覺,就是用戶獲取一個數據可能需要10s以上的時間才會返回。
如果前期伺服器配置不是很高的話,你就會面臨資料庫宕機的情況
那麼這個時候我們要怎麼對項目進行架構的優化呢!
根據大佬們的經驗是資料庫的連接數每秒控制在2000即可、那麼我們1W並發的情況下部署5臺機器,每臺機器都部署一個同樣結構的資料庫。
此時在5臺資料庫擁有同樣的資料庫。表名規則可以這樣設置。
這時每個project庫都有一個相同的表,比如db_project1有tb_play_recode1、db_project2有tb_play_recode2......
這樣就實現了一個基本的分庫分表的思路,從原來一臺資料庫伺服器變成了5臺資料庫伺服器,從原來一個庫變成了5個庫,原來的一張表變成了5張表。
這時我們就需要藉助資料庫中間件來完成寫數據,例如mycat。
這個時候就需要使用播放記錄表的自增ID進行取模5,比如每天播放記錄新增100W數據。此時20W數據會落到db_project1的db_play_recode1,其它的四個庫分別也會落入20W數據。
查詢數據時就根據播放記錄的自增ID進行取模5,就可以去對應的資料庫,從對應的表裡查詢數據即可。
實現了這個架構後,我們再來分析一下。
原來播放記錄就一張表,現在變成了5張表,那麼每個表就變成了1/5
按照原項目的推算,一年如有1億數據,每張表就只有2000w數據。
按照每天新增50W數據,每張表每天新增10W數據,這樣是不是就初步緩解了單表數據量過大影響系統性能問題了。
另外每秒1W的請求,這時每臺伺服器平均就2000,瞬間就把並發請求降低到了安全範圍了。
三、保證查詢性能
在上邊的資料庫架構會遇到一個問題,就是單表數據量還是很大,按照每年1億的數據,單表就會有2000W數據,還是太大了。
比如可以將播放記錄表拆分為100張表,然後分散到5臺資料庫伺服器,這時單表的數據就只有100W,那查詢起來還不是灑灑水的啦!
在寫數據時就需要經過倆次路由,先對播放記錄ID取模資料庫數量,這時可以路由到一臺資料庫上,然後再對那臺資料庫上的表數量進行取模,最終就會路由到數據上的一個表裡了。
通過這個步驟就可以讓每個表的數據都非常少,按照100張表,1億數據,落到每個表的數據就只有100W。
這時的系統架構是這個樣子的。
四、配置讀寫分離來按需擴容
以上的架構整體效果已經很不錯了,假設上邊分了100張表還是不滿足需求,可以通過用戶增量計算來配置合理的表。同時還可以保證單表內的SQL執行效率。
這時還會遇到一個問題,假如每臺伺服器承載每秒2000的請求,其中就400是寫入,1600是查詢。
也就是說,增刪改查中增刪改的SQL才佔到了20%的比例,80%的請求都是查詢。
安裝之前的推理,現在所有數據進行翻倍計算,每臺伺服器並發達到了4000請求了。
那麼其中800請求是寫入,3200請求是查詢,如果說安裝目前的情況來擴容,就只需要增加一臺資料庫伺服器即可。但是就會涉及到表的遷移,因為需要遷移一部分表到新的資料庫上,那是很麻煩的事情了。
其實沒有這個必要的,可以使用讀寫分離來解決這個問題,也就是主從複製。
寫的時候走主庫,讀數據時走從庫,這樣就可以讓一個表的讀寫請求分開落到不同的資料庫上去執行。
這樣的設計後,我們在推算一下,假如寫入主庫的請求是400/s ,查詢從庫的請求是就是1800/s,只需要在主庫下配置倆臺從庫即可。
這時的架構是如下的。
實際的生產環境,讀請求的增長速度遠遠高於寫的請求,所以讀寫分離之後,大部分就是擴容從庫支撐更高的讀請求就可以了。
而且另外一個點,對同一個表,如果既寫數據,還讀數據,可能會牽扯到鎖衝突問題,無論讀還是寫性能都會有影響。
所以一旦讀寫分離之後,對主庫的表就僅僅是寫入,沒任何查詢會影響主庫。對從庫就僅僅是查詢了。
五、並發資料庫結構總結
關於並發場景下,資料庫層面的架構是需要進行精心的設計的。
並且在配置主複製時,也會有很多的問題來等著去解決。
本文就是從一個大的角度來梳理一個思路給大家,可以根據自己公司的業務和項目來考慮自己的系統如何分庫分表。
分庫分表的落地需要藉助mycat或者其他資料庫中間件來實現。
這幾天就會再出一篇文章對於本文的一個實現,並且還有很多問題等著去解決。
例如:自增ID問題,主從複製數據不一致問題,在主從複製這塊很多問題,作為程式設計師的我們就是需要不停的打boos獲得最終的勝利。
堅持學習、堅持寫博、堅持分享是咔咔從業以來一直所秉持的信念。希望在偌大網際網路中咔咔的文章能帶給你一絲絲幫助。