為什麼要分庫分表
在大型**中,當使用者量以及使用者產生的業務資料量達到單庫單錶效能極限時,為了支撐業務可持續發展,對於重要的核心業務必然要進行分庫分表來儲存業務資料。
對於非核心業務產生的大量資料,例如爬蟲爬取的資訊,論壇產生的資料等,可以考慮把資料儲存在像mongodb這樣的nosql儲存裡面,這些儲存會自動分片儲存業務資料,不需要業務邏輯進行干預。
分庫分表的缺點
分庫分表之後實際會產生一系列問題,對於每種問題我們需要針對性進行解決,保障系統穩定執行。
下面就分庫分表會產生的問題進行列舉:
資料的獲取需要通過改寫路由去多個分片獲取資料,然後進行聚合。對於某些sql需要全庫表路由來獲取資料,有的sql甚至需要把sql語句改寫成笛卡爾積去獲取分片資料,這中間會產生大量資料庫連線造成資料庫資源浪費。
分庫分表之後需要分布式事務來保證資料一致性。對於不同業務可以採用不同的分布式事務實現方式來對資料一致性提供不同的保障級別,這其實是一種業務的權衡。
對於分頁資料的獲取,最好是採用異構資料到elasticsearch或者其他分布式儲存中,既能提供高效能的檢索,也能避免由於分庫分表導致分頁資料獲取困難的問題。當然是用彙總表對業務資料彙總,提供乙個兜底方案也是很有必要的。
什麼是分庫分表
分庫分表就是把使用者資料進行拆分,儲存到不同的資料庫的不同資料表中。
分庫分表主要是用來承載使用者的寫負載,使用者資料在單庫單錶儲存量太大,會導致使用者讀取阻塞,進而導致使用者無法寫入。
對於讀負載可以通過讀寫分離,異構到elasticsearch等方案進行很好的解決。
對於寫負載只能通過分庫分表的方案進行解決。
怎麼進行分庫分表
分庫分庫的第乙個要點是如何拆分資料。
大體有以下幾種拆分方案,每種方案都有優點也有缺點:
按時間段進行拆分
取模法查表法
一般業務中使用的都是取模法,因為通過取模法,業務資料可以均勻分布在資料庫中,使用者請求也可以均勻的請求不同的資料庫,可以避免熱點表,但是對於不同使用者的資料的互動或者聯合查詢就需要進行多次查詢。
當然在某些業務場景下使用其他拆分方案可能會更好,例如歷史日誌,可以採用日誌資料按照時間拆分,進行歸檔的方式來進行分庫分表。
分庫分表的第二個要點就是拆分之後sql如何路由,如何執行。
對於這一點一般採用現有的框架來進行實現,如mycat,sharding-jdbc等,他們基於不同的模式為我們封裝好了拆分之後sql路由和執行的細節。
其中mycat是使用**伺服器的方式實現,sharding-jdbc是使用嵌入應用系統中直接呼叫資料庫的方式實現的。
實踐中可以根據不同專案組的情況使用不同的方案。
分庫分表實踐
下面介紹通過sharding-jdbc來實現分庫分表。通過sharding-jdbc可以很方便地實現資料庫的拆分,sql自動改寫,路由,請求結果歸併等具體的資料處理細節。
引入jar包
org.apache.shardingsphere
sharding-jdbc-core
4.1.1
配置資料來源
map datasourcemap = new hashmap<>();
*// 配置第 1 個資料來源*
druiddatasource datasource1 = new druiddatasource();
datasource1.setdriverclassname("com.mysql.cj.jdbc.driver");
datasource1.seturl("jdbc:mysql://localhost:3306/continuous?useunicode=true&characterencoding=utf-8&usessl=false");
datasource1.setusername("root");
datasource1.setpassword("12345678");
datasourcemap.put("ds0", datasource1);
*// 配置第 2 個資料來源*
druiddatasource datasource2 = new druiddatasource();
datasource2.setdriverclassname("com.mysql.cj.jdbc.driver");
datasource2.seturl("jdbc:mysql://localhost:3306/continuous2?useunicode=true&characterencoding=utf-8&usessl=false");
datasource2.setusername("root");
datasource2.setpassword("12345678");
datasourcemap.put("ds1", datasource2);
配置分庫分表的方案
*// 配置 t_order 表規則*
tableruleconfiguration ordertableruleconfig =
new tableruleconfiguration("t_order", "ds0.order0, ds1.order1");
*// 配置分庫策略*
ordertableruleconfig.setdatabaseshardingstrategyconfig(
new standardshardingstrategyconfiguration("user_id", databaseshardingalgorithm));
*// 配置分表策略*
ordertableruleconfig.settableshardingstrategyconfig(
new standardshardingstrategyconfiguration("user_id", tableshardingalgorithm));
*// 配置業務主鍵id生成方案*
ordertableruleconfig.setkeygeneratorconfig(
new keygeneratorconfiguration("snowflake", "user_id"));
*// 配置分片規則*
shardingruleconfiguration shardingruleconfig = new shardingruleconfiguration();
shardingruleconfig.gettableruleconfigs().add(ordertableruleconfig);
*// 設定屬性*
properties properties = new properties();
properties.put("sql.show", true);
*// 建立 shardingspheredatasource*
return shardingdatasourcefactory.*createdatasource*(datasourcemap, shardingruleconfig, properties);
基於業務進行不同的定製
對於不同業務的查詢,有時需要使用hint的方式進行分庫分表。
最佳實踐和好的資料
文章中說明什麼情況下分庫,什麼情況下分表。
資料量大,就分表;併發高,就分庫。
還詳細比較了三種資料庫拆分方案的細節。
hit分片方式的使用,有幾篇文章寫很不錯
mysql分表分庫實現 MySql分表分庫思路
一.資料庫瓶頸 1.1io瓶頸 第一種 磁碟讀io瓶頸,熱點資料太多,資料庫快取放不下,每次查詢時會產生大量的io 分庫和垂直分表 第二種 網路io瓶頸,請求的資料太多,網路頻寬不夠 分庫 1.2cpu瓶頸 第一種 sql問題,如sql中包含join,group by,order by,非索引字段條...
MySQL範圍分表分庫 mysql 分表分庫策略
唯一id的生成 下面列舉幾種常見的唯一id生成方案,需要滿足兩大核心需求 1.全域性唯一 2趨勢有序 1.用資料庫的auto increment 自增id 來生成,每次通過寫入資料庫一條記錄,利用資料庫id自增的特性獲取唯一,有序的id。優點 使用資料庫原有的功能,相對簡單 能夠保證唯一 能夠保證遞...
mysql分庫分表備份 mysql分庫分表備份
一 單獨備份資料庫 mysqldump uroot poldboy oldboy opt oldboy.sql 最簡單的備份 1 mysql基於myisam引擎 mysqldump uroot poldboy b x f oldboy gzip opt oldboy.sql.gz 2 5.5以後預設...