支撐日活百萬用戶的高併發系統,應該如何設計其數據庫架構?【石杉的架構筆記】

歡迎關注我的公衆號:石杉的架構筆記(ID:shishan100)程序員

週一至週五早8點半!精品技術文章準時送上!面試

精品學習資料獲取通道,參見文末算法

目錄:

1.用一個創業公司的發展做爲背景引入 2.用多臺服務器來分庫支撐高併發讀寫 3.大量分表來保證海量數據下查詢性能 4.讀寫分離來支撐按需擴容及性能提高 5.高併發下的數據庫架構設計總結數據庫

「 這篇文章,咱們來聊一下對於一個支撐日活百萬用戶的高並系統,他的數據庫架構應該如何設計?緩存

看到這個題目,不少人第一反應就是:安全

分庫分表啊!性能優化

可是實際上,數據庫層面的分庫分表究竟是用來幹什麼的,他的不一樣的做用如何應對不一樣的場景,我以爲不少同窗可能都沒搞清楚。服務器

(1)用一個創業公司的發展做爲背景引入

假如咱們如今是一個小創業公司,註冊用戶就20萬,天天活躍用戶就1萬,天天單表數據量就1000,而後高峯期每秒鐘併發請求最多就10。網絡

天哪!就這種系統,隨便找一個有幾年工做經驗的高級工程師,而後帶幾個年輕工程師,隨便乾乾均可以作出來。架構

由於這樣的系統,實際上主要就是在前期快速的進行業務功能的開發,搞一個單塊系統部署在一臺服務器上,而後鏈接一個數據庫就能夠了。

接着你們就是不停的在一個工程裏填充進去各類業務代碼,儘快把公司的業務支撐起來,以下圖所示。

結果呢,沒想到咱們運氣這麼好,碰上個優秀的CEO帶着咱們走上了康莊大道!

公司業務發展迅猛,過了幾個月,註冊用戶數達到了2000萬!天天活躍用戶數100萬!天天單表新增數據量達到50萬條!高峯期每秒請求量達到1萬!

同時公司還順帶着融資了兩輪,估值達到了驚人的幾億美金!一隻朝氣蓬勃的幼年獨角獸的節奏!

好吧,如今你們感受壓力已經有點大了,爲啥呢?

由於天天單表新增50萬條數據,一個月就多1500萬條數據,一年下來單表會達到上億條數據。

通過一段時間的運行,如今我們單表已經兩三千萬條數據了,勉強還能支撐着。

可是,眼見着系統訪問數據庫的性能怎麼愈來愈差呢,單表數據量愈來愈大,拖垮了一些複雜查詢SQL的性能啊!

而後高峯期請求如今是每秒1萬,我們的系統在線上部署了20臺機器,平均每臺機器每秒支撐500請求,這個還能抗住,沒啥大問題。

可是數據庫層面呢?

若是說此時你仍是一臺數據庫服務器在支撐每秒上萬的請求,負責任的告訴你,每次高峯期會出現下述問題:

你的數據庫服務器的磁盤IO、網絡帶寬、CPU負載、內存消耗,都會達到很是高的狀況,數據庫所在服務器的總體負載會很是重,甚至都快不堪重負了

高峯期時,原本你單表數據量就很大,SQL性能就不太好,這時加上你的數據庫服務器負載過高致使性能降低,就會發現你的SQL性能更差了

最明顯的一個感受,就是你的系統在高峯期各個功能都運行的很慢,用戶體驗不好,點一個按鈕可能要幾十秒纔出來結果

若是你運氣不太好,數據庫服務器的配置不是特別的高的話,弄很差你還會經歷數據庫宕機的狀況,由於負載過高對數據庫壓力太大了

(2)多臺服務器分庫支撐高併發讀寫

首先咱們先考慮第一個問題,數據庫每秒上萬的併發請求應該如何來支撐呢?

要搞清楚這個問題,先得明白通常數據庫部署在什麼配置的服務器上。

一般來講,假如你用普通配置的服務器來部署數據庫,那也起碼是16核32G的機器配置。

這種很是普通的機器配置部署的數據庫,通常線上的經驗是:不要讓其每秒請求支撐超過2000,通常控制在2000左右。

控制在這個程度,通常數據庫負載相對合理,不會帶來太大的壓力,沒有太大的宕機風險。

因此首先第一步,就是在上萬併發請求的場景下,部署個5臺服務器,每臺服務器上都部署一個數據庫實例。

而後每一個數據庫實例裏,都建立一個同樣的庫,好比說訂單庫。

此時在5臺服務器上都有一個訂單庫,名字能夠相似爲:db_order_01,db_order_02,等等。

而後每一個訂單庫裏,都有一個相同的表,好比說訂單庫裏有訂單信息表,那麼此時5個訂單庫裏都有一個訂單信息表。

好比db_order_01庫裏就有一個tb_order_01表,db_order_02庫裏就有一個tb_order_02表。

這就實現了一個基本的分庫分表的思路,原來的一臺數據庫服務器變成了5臺數據庫服務器,原來的一個庫變成了5個庫,原來的一張表變成了5個表。

而後你在寫入數據的時候,須要藉助數據庫中間件,好比sharding-jdbc,或者是mycat,均可以。

你能夠根據好比訂單id來hash後按5取模,好比天天訂單表新增50萬數據,此時其中10萬條數據會落入db_order_01庫的tb_order_01表,另外10萬條數據會落入db_order_02庫的tb_order_02表,以此類推。

這樣就能夠把數據均勻分散在5臺服務器上了,查詢的時候,也能夠經過訂單id來hash取模,去對應的服務器上的數據庫裏,從對應的表裏查詢那條數據出來便可。

依據這個思路畫出的圖以下所示,你們能夠看看。

作這一步有什麼好處呢?

第一個好處,原來好比訂單表就一張表,這個時候不就成了5張表了麼,那麼每一個表的數據就變成1/5了。

假設訂單表一年有1億條數據,此時5張表裏每張表一年就2000萬數據了。

那麼假設當前訂單表裏已經有2000萬數據了,此時作了上述拆分,每一個表裏就只有400萬數據了。

並且天天新增50萬數據的話,那麼每一個表才新增10萬數據,這樣是否是初步緩解了單表數據量過大影響系統性能的問題?

另外就是每秒1萬請求到5臺數據庫上,每臺數據庫就承載每秒2000的請求,是否是一會兒把每臺數據庫服務器的併發請求下降到了安全範圍內?

這樣,下降了數據庫的高峯期負載,同時還保證了高峯期的性能。

(3)大量分表來保證海量數據下的查詢性能

可是上述的數據庫架構還有一個問題,那就是單表數據量仍是過大,如今訂單表才分爲了5張表,那麼若是訂單一年有1億條,每一個表就有2000萬條,這也仍是太大了。

因此還應該繼續分表,大量分表。

好比能夠把訂單表一共拆分爲1024張表,這樣1億數據量的話,分散到每一個表裏也就才10萬量級的數據量,而後這上千張表分散在5臺數據庫裏就能夠了。

在寫入數據的時候,須要作兩次路由,先對訂單id hash後對數據庫的數量取模,能夠路由到一臺數據庫上,而後再對那臺數據庫上的表數量取模,就能夠路由到數據庫上的一個表裏了。

經過這個步驟,就可讓每一個表裏的數據量很是小,每一年1億數據增加,可是到每一個表裏才10萬條數據增加,這個系統運行10年,每一個表裏可能才百萬級的數據量。

這樣能夠一次性爲系統將來的運行作好充足的準備,看下面的圖,一塊兒來感覺一下:

(4)讀寫分離來支撐按需擴容以及性能提高

這個時候總體效果已經挺不錯了,大量分表的策略保證可能將來10年,每一個表的數據量都不會太大,這能夠保證單表內的SQL執行效率和性能。

而後多臺數據庫的拆分方式,能夠保證每臺數據庫服務器承載一部分的讀寫請求,下降每臺服務器的負載。

可是此時還有一個問題,假如說每臺數據庫服務器承載每秒2000的請求,而後其中400請求是寫入,1600請求是查詢。

也就是說,增刪改的SQL才佔到了20%的比例,80%的請求是查詢。

此時假如說隨着用戶量愈來愈大,假如說又變成每臺服務器承載4000請求了。

那麼其中800請求是寫入,3200請求是查詢,若是說你按照目前的狀況來擴容,就須要增長一臺數據庫服務器.

可是此時可能就會涉及到表的遷移,由於須要遷移一部分表到新的數據庫服務器上去,是否是很麻煩?

其實徹底不必,數據庫通常都支持讀寫分離,也就是作主從架構。

寫入的時候寫入主數據庫服務器,查詢的時候讀取從數據庫服務器,就可讓一個表的讀寫請求分開落地到不一樣的數據庫上去執行。

這樣的話,假如寫入主庫的請求是每秒400,查詢從庫的請求是每秒1600,那麼圖大概以下所示。

寫入主庫的時候,會自動同步數據到從庫上去,保證主庫和從庫數據一致。

而後查詢的時候都是走從庫去查詢的,這就經過數據庫的主從架構實現了讀寫分離的效果了。

如今的好處就是,假如說如今主庫寫請求增長到800,這個無所謂,不須要擴容。而後從庫的讀請求增長到了3200,須要擴容了。

這時,你直接給主庫再掛載一個新的從庫就能夠了,兩個從庫,每一個從庫支撐1600的讀請求,不須要由於讀請求增加來擴容主庫。

實際上線上生產你會發現,讀請求的增加速度遠遠高於寫請求,因此讀寫分離以後,大部分時候就是擴容從庫支撐更高的讀請求就能夠了。

並且另一點,對同一個表,若是你既寫入數據(涉及加鎖),還從該表查詢數據,可能會牽扯到鎖衝突等問題,不管是寫性能仍是讀性能,都會有影響。

因此一旦讀寫分離以後,對主庫的表就僅僅是寫入,沒任何查詢會影響他,對從庫的表就僅僅是查詢。

(5)高併發下的數據庫架構設計總結

其實從大的一個簡化的角度來講,高併發的場景下,數據庫層面的架構確定是須要通過精心的設計的。

尤爲是涉及到分庫來支撐高併發的請求,大量分表保證每一個表的數據量別太大,讀寫分離實現主庫和從庫按需擴容以及性能保證。

這篇文章就是從一個大的角度來梳理了一下思路,各位同窗能夠結合本身公司的業務和項目來考慮本身的系統如何作分庫分表應該怎麼作。

另外就是,具體的分庫分表落地的時候,須要藉助數據庫中間件來實現分庫分表和讀寫分離,你們能夠本身參考 sharding-jdbc 或者 mycat 的官網便可,裏面的文檔都有詳細的使用描述。

(封面圖源網絡,侵權刪除)

END

掃描下方二維碼,備註:「資料」,獲取更多「祕製」 精品學習資料

若有收穫,請幫忙轉發,您的鼓勵是做者最大的動力,謝謝!

一大波微服務、分佈式、高併發、高可用的原創系列文章正在路上

歡迎掃描下方二維碼,持續關注:

石杉的架構筆記(id:shishan100)

十餘年BAT架構經驗傾囊相授

推薦閱讀:

一、拜託!面試請不要再問我Spring Cloud底層原理

二、【雙11狂歡的背後】微服務註冊中心如何承載大型系統的千萬級訪問?

三、【性能優化之道】每秒上萬併發下的Spring Cloud參數優化實戰

四、微服務架構如何保障雙11狂歡下的99.99%高可用

五、兄弟,用大白話告訴你小白都能聽懂的Hadoop架構原理

六、大規模集羣下Hadoop NameNode如何承載每秒上千次的高併發訪問

七、【性能優化的祕密】Hadoop如何將TB級大文件的上傳性能優化上百倍

八、拜託,面試請不要再問我TCC分佈式事務的實現原理!

九、【坑爹呀!】最終一致性分佈式事務如何保障實際生產中99.99%高可用?

十、拜託,面試請不要再問我Redis分佈式鎖的實現原理!

十一、【眼前一亮!】看Hadoop底層算法如何優雅的將大規模集羣性能提高10倍以上?

十二、億級流量系統架構之如何支撐百億級數據的存儲與計算

1三、億級流量系統架構之如何設計高容錯分佈式計算系統

1四、億級流量系統架構之如何設計承載百億流量的高性能架構

1五、億級流量系統架構之如何設計每秒十萬查詢的高併發架構

1六、億級流量系統架構之如何設計全鏈路99.99%高可用架構

1七、七張圖完全講清楚ZooKeeper分佈式鎖的實現原理

1八、大白話聊聊Java併發面試問題之volatile究竟是什麼?

1九、大白話聊聊Java併發面試問題之Java 8如何優化CAS性能?

20、大白話聊聊Java併發面試問題之談談你對AQS的理解?

2一、大白話聊聊Java併發面試問題之公平鎖與非公平鎖是啥?

2二、大白話聊聊Java併發面試問題之微服務註冊中心的讀寫鎖優化

2三、互聯網公司的面試官是如何360°無死角考察候選人的?(上篇)

2四、互聯網公司面試官是如何360°無死角考察候選人的?(下篇)

2五、Java進階面試系列之一:哥們,大家的系統架構中爲何要引入消息中間件?

2六、【Java進階面試系列之二】:哥們,那你說說系統架構引入消息中間件有什麼缺點?

2七、【行走的Offer收割機】記一位朋友斬獲BAT技術專家Offer的面試經歷

2八、【Java進階面試系列之三】哥們,消息中間件在大家項目裏是如何落地的?

2九、【Java進階面試系列之四】扎心!線上服務宕機時,如何保證數據100%不丟失?

30、一次JVM FullGC的背後,竟隱藏着驚心動魄的線上生產事故!

3一、【高併發優化實踐】10倍請求壓力來襲,你的系統會被擊垮嗎?

3二、【Java進階面試系列之五】消息中間件集羣崩潰,如何保證百萬生產數據不丟失?

3三、億級流量系統架構之如何在上萬併發場景下設計可擴展架構(上)?

3四、億級流量系統架構之如何在上萬併發場景下設計可擴展架構(中)?

3五、億級流量系統架構之如何在上萬併發場景下設計可擴展架構(下)?

3六、億級流量架構第二彈:你的系統真的無懈可擊嗎?

3七、億級流量系統架構之如何保證百億流量下的數據一致性(上)

3八、億級流量系統架構之如何保證百億流量下的數據一致性(中)?

3九、億級流量系統架構之如何保證百億流量下的數據一致性(下)?

40、互聯網面試必殺:如何保證消息中間件全鏈路數據100%不丟失(1)

4一、互聯網面試必殺:如何保證消息中間件全鏈路數據100%不丟失(2

4二、面試大殺器:消息中間件如何實現消費吞吐量的百倍優化?

4三、高併發場景下,如何保證生產者投遞到消息中間件的消息不丟失?

4四、兄弟,用大白話給你講小白都能看懂的分佈式系統容錯架構

4五、從團隊自研的百萬併發中間件系統的內核設計看Java併發性能優化

4六、【非廣告,純乾貨】英語差的程序員如何才能無障礙閱讀官方文檔?

4七、若是20萬用戶同時訪問一個熱點緩存,如何優化你的緩存架構?

4八、【非廣告,純乾貨】中小公司的Java工程師應該如何逆襲衝進BAT?

4九、拜託,面試請不要再問我分佈式搜索引擎的架構原理!

50、【金三銀四跳槽季】Java工程師如何在1個月內作好面試準備?

5一、【offer收割機必備】我簡歷上的Java項目都好low,怎麼辦?

5二、【offer去哪了】我一連面試了十個Java崗,通通石沉大海!

做者:石杉的架構筆記 連接:juejin.im/post/5c263a… 來源:掘金 著做權歸做者全部,轉載請聯繫做者得到受權!

相關文章
相關標籤/搜索