記錄一次經歷的數據庫從單庫到分庫分表的過程


前言

   目前所在的的項目組,由於項目正在處於一個業務爆發期,每天數據的增長量已經給我們數據庫乃至系統造成了很多不確定的因數,前期依靠優化業務和SQL等方式暫時還能夠支撐住。但是最近發現某些表數據達到500W+以后查詢統計性能嚴重下降,高峰時段出現了很多SQL阻塞的情況例如:

 

這種阻塞帶來的災難是滾雪球的,由於越堆越多基本上把數據庫已經拖死,所以我們就面臨數據庫切分的問題。

技術選型

 

   既然要分庫分表那數據庫集群是少不了的,那我們的項目怎樣和這些集群打交道呢?我調研了大概分為以下幾種來完成這個功能(僅僅針對java項目)

 

中間件

例如淘寶開源的cobar,以及后來開源社區根據cobar做二次開發的Mycat(個人建議如果使用中間件的話可以考慮Mycat)

Jar形式的開源工具

例如淘寶的TDDL,以及當當開源出來的,Sharding-JDBC等

動態數據源

根據自己的業務來指定數據源來完成不同庫和表的操作

 

   給予上面三個我最后選擇了估計看起來最LOW的第三種方式:我說一下我自己選擇的依據:

   上述開元產品中淘寶系的cobar沒有維護,TDDL開源出來的和內部版本也不一樣有不少BUG我們這邊人力緊缺,估計沒時間來爬坑。Sharding-JDBC呢,剛推出來沒有項目實戰經驗。Mycat其實是我發現目前比較好的一個解決方案,但是mycat是給予代理模式的需要人維護,如果維護不得力,性能也不會太高,基於我們組人員的能力和我還是最終放棄了。

   之所以選擇動態數據源:主要是因為技術相對簡單,對於業務代碼修改也比較少,可控性較高,減少了加入中間件或者第三方工具所帶來的風險。(申明一下我們項目完全沒有使用JPA事物的,對於事物是采用的補償機制這里就不贅述)

 

  主鍵生成策略

  既然要分庫分表那么全局唯一主鍵也是我們需要考慮的問題,我所知道的和有使用經驗的有如下幾種技術:

 

問題

可行性

基於redis

單點問題,redis重啟問題等

較高,公司有項目使用

給予DB(每次生成多個使用時去取出來)

單點問題,並發量問題

低並發,數據量較小的可以使用

UUID

暫用存儲空間比較大,非可排序的,體現不出增長的趨勢

較高

twitter snowflake

Xx年以后可能存在重復問題,需要配置生產參數

高,分布式的沒單點故障問題,時間上是遞增的。推薦

基於DB步長的方式

不是所有數據庫都支持

  我選擇的是snowflake。

 

實現細節  

   因為分庫分表所以查詢和添加都需要帶上分配策略主鍵。

添加流程

 

查詢邏輯

 

分庫分表后能解決我們的性能問題,但是也帶來了很多其他的問題:我總結了一下分庫分表后的坑

 

1.分完之后只能直接按分片鍵查詢,為了避免掃所有分片,如果按非分片鍵查詢,在OLTP環境中得走搜索引擎。數據庫和搜索引擎同步數據靠binlog
2.按不同維度查詢,比如買家維度和賣家維度查訂單。除了走搜索引擎之外,還可以在不同的系統中各寫一條訂單數據。
3.ID得通過ID生成器。
4.有熱點數據問題,比如一個超級買家,買了好多種商品,然而還有不怎么熱的買家,沒什么訂單。解決方法兩種,熱點數據拿出來放到單獨的系統。或者按數據塊分片,比如十種商品算一個塊,但這種方法具體細節我忘了,只是聽人分享過。
5.跨庫事務問題,NPC一般不用,補償是一種方法,TCC是一種方法,TCC的變種,比如SAGA比如XTS,努力送達是一種方法
6.數據擴展問題,可以看看阿里的愚公。我個人覺得還半夜停機維護比較靠譜。
7.分頁的坑,前期可以用中間件Limit,中期得走搜索引擎,后期OLAP
8.可用性問題,依賴數據庫高可用方案。據說會出現 sharding 算法 會因為網絡抖動 造成部分分區錯誤 導致片出問題
9.配置中心問題。盡量使用配置中心,不要用zookeeper
10.非代理模式,就是JDBC路由模式 每個client都會對 db開啟pool ,數據庫可能會死在數據庫連接上,一種方法是定制
Mysql,設置高低水位,讓超過數據庫處理能力的數據庫連接排隊。第二種方法是在JDBC路由模式之上做Mysql的Proxy

 

 

Mysql海量數據分表分庫如何列表分頁?

1,可以使用ElasticSearch或者solr了。基於Lucene的解決方案

可以將mysql里的數據寫入到類似hbase這樣的分布式數據庫,查詢快。但分頁、查詢的話,可以在hbase前加一層solr,用於建立數據索引

2,我還想了一種思路,就是分表分庫的時候根據查詢條件,比如areaid,productid,userid都進行分庫分表,也就是說入庫的時候一共入了3份insert到3個不同的庫不同的表(當然

可以優先入一個條件的庫,其他2個庫通過隊列延時入庫)。這樣查詢的時候可以根據條件進行查詢不同的表和庫。但是組合條件查詢的時候也有問題。

 

 

我把我現在的項目抽出來了一個簡單的模型放出來:源碼我將放在git上面

https://github.com/bingzhilanmo-bowen/spring-multi-datasource

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM