前言
目前所在的的項目組,由於項目正在處於一個業務爆發期,每天數據的增長量已經給我們數據庫乃至系統造成了很多不確定的因數,前期依靠優化業務和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 |
暫用存儲空間比較大,非可排序的,體現不出增長的趨勢 |
較高 |
Xx年以后可能存在重復問題,需要配置生產參數 |
高,分布式的沒單點故障問題,時間上是遞增的。推薦 |
|
基於DB步長的方式 |
不是所有數據庫都支持 |
低 |
我選擇的是snowflake。
實現細節
因為分庫分表所以查詢和添加都需要帶上分配策略主鍵。
添加流程
查詢邏輯
分庫分表后能解決我們的性能問題,但是也帶來了很多其他的問題:我總結了一下分庫分表后的坑
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