{eval=Array;=+count(Array);}
分庫分表是比較靠后的優化手段,因為成本比較高。
遇到數據庫瓶頸:
- 首先考慮sql優化,這是最簡單的方法。對現有系統基本沒有影響。
- 其次就是考慮數據庫的讀寫分離,這也是相對簡單的方法。在數據庫層面進行配置,系統層面只需要調整一下獲取數據庫連接的邏輯。讀數據時即可以獲取主庫連接,也可以獲取從庫連接。寫數據時只獲取主庫連接。
- 再考慮增加緩存層。將數據緩存到緩存中,當再次訪問時不再從數據庫獲取。一般緩存層對系統是透明的,基本對系統本身沒有影響。但是引入緩存,也引入了相應的需要考慮的問題,比如雪崩,命中率,分布式緩存等
- 還有一種非技術手段,就是改需求。引起性能問題的原因是否是需求不合理?或者需求太復雜?是否可以簡化需求?此方法對系統的影響也相對較小。
- 最后才考慮分庫分表。優先分庫,因為相對分表更簡單。將對應的表移動到新庫,調整系統獲取數據庫連接的邏輯。這里需要考慮要移動哪些表,在提高性能的前提下,首先盡量避免分布式事務。
- 最最后,考慮分表。分表的主要原因是單表數據量太大。分表又分縱切和橫切。縱切就是按列切,比如用戶表,常用信息為基本信息表,其它信息為詳情表。橫切就是按行切,比如一億數據量的表切分為十張一千萬的表。這里就涉及數據該存放到哪張表,或從哪張表里取。分表后又可以分庫,來進一步優化。
- 如果涉及到分布式事務,又要考慮如何保證分布式事務。理論方面2pc,3pc,paxos,cap,base。對應的中間件的使用。
對系統的設計和優化不是人云亦云,需要根據實際的場景來進行處理。
大部分的軟件架構、組件或解決方案,都是在解決一些問題的同時,會帶來另外的問題。
數據庫的分庫分表,又可以分為垂直拆分和水平拆分(可能大家常說的分庫分表主要指的是后者):
垂直拆分:這是一種比較常見的數據庫設計方法,就是把一個字段比較多的大表,拆分成多個小表,特別是在現在分布式、微服務的架構下,可以把各個小表按照業務模型,劃分到不同的數據庫中,這樣就可以利用多臺數據庫服務器的性能;但當被拆分出來小表的數據量不斷增長,到了一個極限的時候,還是需要考慮水平拆分。
水平拆分:將表中的數據,按照一定的規則分布到不同的數據庫中,比如對主鍵進行Hash和取模操作后,按照結果把數據路由到對應的數據庫上;水平分庫分表,可以降低每張表的數據量,這也是現在大部分公司所使用的方法。
上文中說到,水平拆分常用的手段是對主鍵進行Hash和取模操作后,按照結果把數據路由到對應的數據庫上;但如果被拆分的子表,數據量也達到極限值以后,就要面對數據庫擴容的問題,比如開始規劃分成8個庫,現在要擴到16個庫;
路由規則發生變化:hash(id)%8 變成了 hash(id)%16,那么歷史數據也就要面臨遷移的問題;這種情況,要么做數據遷移,要么增加分表算法的復雜性,讓算法可以兼容增加分表前后的數據路由。
在單庫時代,復雜的關聯查詢是很容易實現的,但是數據庫被拆分后,數據被保存在了不同的數據庫服務器上,那么夸庫的join就成了很大的問題。通常解決方案有:
如果是垂直拆分,那么可以考慮做一定程度的字段冗余,避免跨表關聯;或者可以做數據同步,把需要的表同步到同一個庫中,進行表關聯;
代碼層面組裝,也就是把兩邊的數據都拿出來,然后在代碼里面關聯組裝;或者先獲取主表數據,再把其余字段補齊;但是從實際情況來看,這個方案在大多數場景下,實現起來都比較困難;
現在一個比較主流的做法,是引入ES或ES+HBase或solr+HBase,把部分字段的全量數據保存在同一個地方。
在水平拆分的場景下,一單一張表被拆分成多張表部署在多個數據庫中,那么就不能使用數據庫自身的主鍵生成機制了;這時候就需要由我們自己來考慮主鍵生成策略:
主鍵生成中心:可以利用數據庫、Redis、MongoDB、zookeeper等組件實現,需要生產主鍵的時候,調用主鍵生成中心的接口;缺點也很明顯,增加了網絡開銷,并且主鍵生成中心如果發生問題,后果會很嚴重。
UUID:本地生成,不需要第三方組件,生成比較簡單,性能好;不過缺點也不少,長度長,不利于存儲,并且沒有排序,是個字符串,不利于查詢。
一些唯一性ID的生成算法:比如Snowflake、UidGenerator、Leaf等等。
單庫的時候,解決事務問題很簡單,但是現在要保證跨庫的事務問題,需要額外的成本;
這種場景下(性能要求高,一致性要求不是那么的高),大部分公司會放棄事務的【實時】一致性,只要在一定的時間內,事務【最終】一致即可。
1.優化SQL加索引
2.業務是否可以垂直拆分,業務拆分了可以分庫
3.業務單邊數據量還是大,是否可以把一些字段獨立出去,表垂直拆分。水平拆分表可以按時間,或者id的has值進行拆分
4.分庫分表必然帶來很多問題,比如關聯查詢,聚合等操作,可以嘗試下NewSQL,業務不再關心分庫分表操作了。國內開源實現有TiDB,可以了解下,NewSQL應該是未來的趨勢。
可以關注我,后面分享一些存儲方面的文章。
不到萬不得已,不要分庫分表。
數據庫遇到瓶頸,應該首先考慮優化。sql服務器硬件優化,sql語句優化,索引優化,讀寫分離,緩存層。
如果都不行,那就只能考慮分庫分表了,可以利用mycat,DBProxy等中間件。
一旦分庫分表,就會引出分布式事物,應該盡量避免。關聯查詢,聚合統計等操作等地方也有坑,一定要注意!
個人建議:一般到了分庫分表的地步,都是因為數據量到了一定級別,單臺服務器無法承受。一般都是某幾張表或者某個庫數據量過大。與其費力分庫分表,倒不如考慮一些新興的數據庫,例如HBase或者TiDB等newSQL甚至ES。如果這些大表,不涉及復雜,需要考慮事物的業務,完全可以頂上。
回答完畢,謝謝,希望對你有所幫助!!
本人專注互聯網前沿動態,大數據,數據采集,數據處理,數據治理,望交流!
0
回答0
回答1
回答0
回答0
回答0
回答0
回答0
回答0
回答0
回答