架構師方案-分庫分表

前言

分庫分表是一個老生常談的問題,但網(wǎng)上的大多數(shù)文章只是概要式講述,一些核心步驟一筆帶過渺杉。 這篇文章給大家講述所有可行性方案的同時,系統(tǒng)性挪钓、完整性闡述其思想內(nèi)核是越。

1. 拆分形式

分庫分表拆分形式分為垂直分庫分表和水平分庫分表,這篇文章將聚焦于水平分庫分表碌上。
原因在于組織倚评、業(yè)務劃分的之初或者大數(shù)據(jù)量之前,在一些開發(fā)人員素質比較高的公司馏予,庫天梧、表先天的就垂拆分的比較清晰了,剩下只是數(shù)據(jù)字段微調吗蚌。 水平分庫分表是側重于技術的問題腿倚,垂直分庫分表是側重于業(yè)務劃分問題纯出。注意是側重蚯妇,為啥這么說了,以訂單表為例暂筝,用戶下單是訂單補充信息過長箩言,把它拆分出來,放在其它數(shù)據(jù)庫里焕襟,用訂單號關聯(lián)陨收,這是垂直拆分的一種形式,但顯然對業(yè)務操作沒什么影響鸵赖。

從上我們可以得出务漩,大數(shù)據(jù)量下必然要水平分庫分表,不一定要垂直分庫分表它褪。

image.png

image.png

2.切分策略

2.1 取模切分(Hash取模)

我們一般會用對某個路由Key的Hash值取模饵骨,使數(shù)據(jù)分散到各個表中更加均衡。

比如原始訂單表信息茫打,我們把它分成4張分表:

image.png

優(yōu)點:可以較為均勻的將數(shù)據(jù)切分居触,不會有熱點問題

缺點:擴容時需要重新計算切分后的值,涉及到大量的數(shù)據(jù)遷移

2.2 Range切分

image.png

優(yōu)點:單表大小可控老赤,天然水平擴展轮洋。
缺點:無法解決集中寫入瓶頸,有熱點問題抬旺。

2.3 查詢切分

image.png

查詢切分的好處弊予,是可以解決Hash取模的水平擴展問題和Range切分的熱點問題。

2.3.1基于查詢配置結合ShardGroup方式解決水平擴展問題和熱點問題
(1)表數(shù)據(jù)演示
image.png
image.png
image.png

總得來看表結構呈現(xiàn)share group->share db->share table的樹形結構

(2) 核心流程
image.png

step1:通過id所處的范圍找到group_id
step2:通過id取模和groupid找到db_id
step3:通過id所處的范圍和db_id找到table_id

優(yōu)點:理論上根據(jù)數(shù)據(jù)實際增長情況开财,調整ID和庫块促、表的Mapping關系荣堰,將hash和range結合起來可以解決熱點和水平擴展問題。
缺點:引入額外的配置表竭翠,降低性能振坚,有漏配、錯配的風險斋扰。

2.4 一致性Hash切分

image.png
  1. 建立一個2^32 hash節(jié)點環(huán)渡八,計算database的hash值(常用:hash(節(jié)點前綴 +(ip+端口))%2^32),并映射到hash環(huán)的具體位置
  2. 將待切分數(shù)據(jù)取值hash(sharding key) % 2^32传货,映射到hash 環(huán)上屎鳍,并按照規(guī)則從root節(jié)點開始順時針查找
if hash(node_0) %2^32 < hash(sharding key) %2^32 <= hash(node_1) %2^32 ;該數(shù)據(jù)歸屬 node_1(database1)
if hash(node_1) %2^32 < hash(sharding key) %2^32 <= hash(node_2) %2^32 ;該數(shù)據(jù)歸屬 node_2(database2)
if hash(node_2) %2^32 < hash(sharding key) %2^32 <= hash(node_3) %2^32 ;該數(shù)據(jù)歸屬 node_3(database3)
...
  1. 擴容時遷移數(shù)據(jù)時,如新增節(jié)點node_4(database4) 在node_1和 node_2之間问裕,則需要將data_key落在node_1到 node_4的數(shù)據(jù)從原node_2(database2)遷移到node_4(database4)
image.png

優(yōu)點:擴容時只需要遷移小部分的數(shù)據(jù)

缺點:如果節(jié)點不夠分散逮壁,會出現(xiàn)Hash環(huán)的傾斜,導致節(jié)點數(shù)據(jù)不均勻

增加虛擬Hash節(jié)點解決數(shù)據(jù)傾斜問題
image.png

基于一致性Hash 增加了虛擬節(jié)點粮宛,這些節(jié)點會映射到真實的物理節(jié)點窥淆,這樣就可以調控節(jié)點數(shù)據(jù)分配

優(yōu)點:減少了Hash環(huán)傾斜帶來的影響

缺點:增加復雜度

3.數(shù)據(jù)遷移

數(shù)據(jù)庫拆分一般是業(yè)務發(fā)展到一定規(guī)模后的優(yōu)化和重構,為了支持業(yè)務快速上線,很難一開始就分庫分表,這時候就需要進行數(shù)據(jù)遷移了僧凰。

3.1同步腳本停機遷移(不建議)

寫個腳本老庫的數(shù)據(jù)寫到新庫中。比如词裤,在系統(tǒng)使用的人數(shù)非常少的時候,凌晨1點鳖宾,掛一個公告說系統(tǒng)要維護升級預計N小時吼砂。個腳本將老庫的數(shù)據(jù)都同步到新庫中。
優(yōu)點:操作簡單
缺點:一但數(shù)據(jù)量大鼎文,加上數(shù)據(jù)核對時間渔肩,遷移時間會超出公告時間。

3.2 雙寫數(shù)據(jù)遷移

3.2.1 在業(yè)務代碼中直接雙寫
Step1.數(shù)據(jù)庫雙寫(事務成功以老模型為準)漂问,查詢走老模型赖瞒。
image.png

舊數(shù)據(jù)如何遷移到新庫?
通過job導歷史數(shù)據(jù)寫入到新庫蚤假,同時建立映射關系栏饮。

如何保證新庫里的數(shù)據(jù)是最新且完整的?
我們對老庫的更新操作(增刪改)磷仰,同時也要寫入新庫(雙寫)袍嬉。如果操作的數(shù)據(jù)不存在于新庫的話,需要插入到新庫中。同時每日job數(shù)據(jù)對賬伺通,并將差異數(shù)據(jù)補平箍土。這樣就能保證,咱們新庫里的數(shù)據(jù)是最新且完整的罐监。

不在同一庫如何保證事務吴藻?
只保證舊庫寫入事務,差異數(shù)據(jù)由數(shù)據(jù)對賬服務補償弓柱。

Step2.數(shù)據(jù)庫雙寫沟堡,但是事務成功與否以新模型為準,在線查詢切新模型矢空。

在歷史數(shù)據(jù)導入完畢并且數(shù)據(jù)對賬無誤后航罗,執(zhí)行該步驟。


image.png

如何查詢舊訂單屁药?
通過order mapping數(shù)據(jù)找到新庫id粥血,在新庫中查詢。

Step3.老模型不再同步寫入酿箭,在線查詢切新模型复亏。

在查詢無異常后,執(zhí)行該步驟七问。

image.png

在業(yè)務代碼中直接雙寫方案
優(yōu)點:平滑遷移
缺點:雙寫影響響應時間蜓耻,減少吞吐量

3.2.1 通過數(shù)據(jù)同步工具雙寫

數(shù)據(jù)同步數(shù)據(jù)同步整體方案見下圖

image.png

上述方案中不難發(fā)現(xiàn)茫舶,業(yè)務寫一條數(shù)據(jù)到舊實例的一張表械巡,于是產(chǎn)生了一條binlog;data-sync中間件接到binlog后饶氏,將該記錄寫入到新實例讥耗,于是在新實例也產(chǎn)生了一條binlog;此時data-sync中間件又接到了該binlog......不斷循環(huán)

如何解決雙向同步時的binlog循環(huán)消費問題疹启?

采用數(shù)據(jù)染色方案解決古程,只要能夠標識寫入到數(shù)據(jù)庫中的數(shù)據(jù)使data-sync中間件寫入而非業(yè)務寫入,當下次接收到該binlog數(shù)據(jù)的時候就不需要進行再次消息流轉喊崖。所以data-sync中間件要求挣磨,每個數(shù)據(jù)庫實例創(chuàng)建一個事務表,該事務表tb_transaction只有id荤懂、tablename茁裙、status、create_time节仿、update_time幾個字段晤锥,status默認為0。操作如下:

# 開啟事務,用事務保證一下sql的原子性和一致性
start transaction;
set autocommit = 0;
# 更新事務表status=1矾瘾,標識后面的業(yè)務數(shù)據(jù)開始染色
update tb_transaction set status = 1 where tablename = ${tableName};
# 以下是業(yè)務產(chǎn)生
binloginsert xxx;update xxx;update xxx;
# 更新事務表status=0女轿,標識后面的業(yè)務數(shù)據(jù)失去染色,后面業(yè)務正常繼續(xù)消費
update tb_transaction set status = 0 where tablename = ${tableName};
commit;
image.png

數(shù)據(jù)同步工具DTS


image.png

4.平滑擴容

4.1 全局增量分區(qū)局部散列擴容方案

對于Range和查詢切分切分策略壕翩,增加數(shù)據(jù)庫實例和映射配置即可

4.2 基于主從同步的擴容方案

核心思想是蛉迹,啟動更多的從服務器(取決于希望擴容的服務器量),當從服務器從主服務器同步完成之后放妈,將所有從服務器升級為主服務器婿禽,然后調整路由規(guī)則,再根據(jù)路由規(guī)則刪除每個主服務器中的冗余數(shù)據(jù)大猛。

image.png

4.3 基于數(shù)據(jù)遷移的擴容方案

上文數(shù)據(jù)遷移中扭倾,通過數(shù)據(jù)同步工具雙寫就是此方法。數(shù)據(jù)遷移的過程中就涉及到了平滑擴容挽绩,我在這里把它拿出來膛壹,是為了大家更好理解它。

image.png

4.查詢問題

4.1 數(shù)據(jù)多維度查詢

水平切分后唉堪,查詢的條件一定要在切分的維度內(nèi)模聋,比如查詢具體某個用戶下的各位訂單等;禁止不帶切分的維度的查詢唠亚,即使中間件可以支持這種查詢链方,可以在內(nèi)存中組裝,但是這種需求往往不應該在在線庫查詢灶搜,或者可以通過其他方法轉換到切分的維度來實現(xiàn)祟蚀。

但是我非要多維度查詢怎么辦?
4.1.1 多維度查詢雙寫

比如割卖,對于訂單表我可以同時以user_id前酿、order_id為sharding key冗余分庫分表數(shù)據(jù)。
優(yōu)點:查詢實時性
缺點:寫入性能有影響鹏溯,數(shù)據(jù)冗余

4.1.2 增加全局二級索引庫

每個全局二級索引庫對應一張分布式索引表罢维,和其他分布式表一樣,按照指定的分區(qū)規(guī)則水平拆分為多張物理表丙挽。


image.png

優(yōu)點類似ES 倒排索引肺孵,首先通過value 找到id,在通過id找到完整數(shù)據(jù)颜阐。
優(yōu)點:查詢實時性,相較于數(shù)據(jù)冗余
缺點:寫入性能有影響平窘,數(shù)據(jù)冗余

4.1.3 通過binlog數(shù)據(jù)異構查詢

比如,可以把mysql通過binlog寫入到OLAP數(shù)據(jù)庫瞬浓,比如Elasticsearch初婆、 Clickhouse查詢。
優(yōu)點:讀寫分離,方便支持多維度或者全字段索引
缺點:查詢會有實時性問題磅叛,可以用于非實時場景

4.2 order排序查詢

基于上述分片聚合方式我們清晰的了解到如何可以進行跨分片下降數(shù)據(jù)獲取到內(nèi)存中屑咳,但是通過圖中結果可以清晰的了解到返回的數(shù)據(jù)并不像我們預期的那樣有序,那是因為各個節(jié)點下的所有數(shù)據(jù)都是僅遵循各自節(jié)點的數(shù)據(jù)庫排序而不受其他節(jié)點分片影響。 那么如果我們對數(shù)據(jù)進行分片聚合+排序那么又會是什么樣的場景呢

4.2.1 內(nèi)存排序

todo

4.2.2 流式排序

todo

5.灰度發(fā)布

后續(xù)在補充弊琴。兆龙。。

6.總結

分庫分表要考慮的細節(jié)還是很多的敲董,所有才有了NewSql數(shù)據(jù)庫紫皇,但是上面這些解決方案,還是需要掌握的腋寨。

參考

https://blog.csdn.net/mouzeping123/article/details/120061298
https://tech.meituan.com/2016/11/18/dianping-order-db-sharding.html
https://cloud.tencent.com/developer/article/2124399
https://mp.weixin.qq.com/s?https://juejin.cn/post/7085132195190276109
https://bbs.csdn.net/topics/605500717
https://blog.51cto.com/u_11475121/2954464
https://zhuanlan.zhihu.com/p/635219596

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末聪铺,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子萄窜,更是在濱河造成了極大的恐慌铃剔,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件查刻,死亡現(xiàn)場離奇詭異键兜,居然都是意外死亡,警方通過查閱死者的電腦和手機穗泵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門普气,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人佃延,你說我怎么就攤上這事现诀。” “怎么了苇侵?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵赶盔,是天一觀的道長企锌。 經(jīng)常有香客問我榆浓,道長,這世上最難降的妖魔是什么撕攒? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任陡鹃,我火速辦了婚禮,結果婚禮上抖坪,老公的妹妹穿的比我還像新娘萍鲸。我一直安慰自己,他們只是感情好擦俐,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布脊阴。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嘿期。 梳的紋絲不亂的頭發(fā)上品擎,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音备徐,去河邊找鬼萄传。 笑死,一個胖子當著我的面吹牛蜜猾,可吹牛的內(nèi)容都是我干的秀菱。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼蹭睡,長吁一口氣:“原來是場噩夢啊……” “哼衍菱!你這毒婦竟也來了?” 一聲冷哼從身側響起肩豁,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤梦碗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蓖救,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體洪规,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年循捺,在試婚紗的時候發(fā)現(xiàn)自己被綠了斩例。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡从橘,死狀恐怖念赶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情恰力,我是刑警寧澤叉谜,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站踩萎,受9級特大地震影響停局,放射性物質發(fā)生泄漏。R本人自食惡果不足惜香府,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一董栽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧企孩,春花似錦锭碳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽推汽。三九已至,卻和暖如春歧沪,著一層夾襖步出監(jiān)牢的瞬間民泵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工槽畔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留栈妆,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓厢钧,卻偏偏與公主長得像鳞尔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子早直,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容