分庫分表和一致性hash

分庫分表的原則

  1. 當(dāng)數(shù)據(jù)量較大時(shí)芭商,需要分庫分表。通常為保證某個(gè)用戶的數(shù)據(jù)在同一個(gè)庫同一個(gè)表中,都是按照customerId進(jìn)行分庫分表的再愈。
  2. 有時(shí)每天產(chǎn)生大量數(shù)據(jù),這些數(shù)據(jù)只是為了對(duì)賬护戳,也可以按月分庫翎冲,按天分表。比如分為12個(gè)庫媳荒,366張表(考慮閏年)抗悍,但數(shù)據(jù)每天用完后,可以把這些數(shù)據(jù)再遷移到歷史表中钳枕,或者類似hdfs這樣的表中缴渊。
  3. 分庫分表后考慮數(shù)據(jù)庫的擴(kuò)容問題,同時(shí)還要保證在業(yè)務(wù)系統(tǒng)不停機(jī)的時(shí)候繼續(xù)正常的讀寫數(shù)據(jù)鱼炒,需要保證
    3.1 如何保證業(yè)務(wù)系統(tǒng)不停機(jī)衔沼?
    3.2 如何保證擴(kuò)容時(shí)候盡量少的遷移數(shù)據(jù)?

分庫分表的流水號(hào)

一般情況下昔瞧,我們使用customerId作為分庫分表鍵指蚁,但有時(shí)我們也會(huì)產(chǎn)生一個(gè)業(yè)務(wù)ID,并把該業(yè)務(wù)ID暴露出去自晰,供其他業(yè)務(wù)系統(tǒng)來查詢凝化。這就要求暴露出去的業(yè)務(wù)ID也是一個(gè)分庫分表鍵,這里只需要將分庫分表的信息記錄在該ID中即可酬荞。
比如ID為:01110001002817070500000001036815
這個(gè)ID一共32位缘圈,由以下幾個(gè)含義組成
01:Version
11:區(qū)域信息
0001:代表這是某個(gè)類型的數(shù)據(jù)
0028:代表數(shù)據(jù)位于第28張表,
170705:數(shù)據(jù)產(chǎn)生與17年7月5號(hào)
00000001036815:Sequence睦尽,全局唯一的流水號(hào)
我們可以看到酒贬,0028 這個(gè)字段就含有分庫分表信息八毯。通過算法可以推導(dǎo)出位于第0000庫的第0028表乓梨。

一致性hash

概述

假如我們用sharding-jdbc分了15張表,之后業(yè)務(wù)需要擴(kuò)展到20張表遣疯,那問題就來了雄可,之前根據(jù)order_id取模15后的數(shù)據(jù)分散在了各個(gè)表中,現(xiàn)在需要重新對(duì)所有數(shù)據(jù)重新取模20來分配數(shù)據(jù)缠犀,工作量太大数苫,有沒有更好的方法呢?答案是有的:一致性hash辨液。

先了解下一致性hash, 例子中四個(gè)節(jié)點(diǎn)一般都是用節(jié)點(diǎn)前綴 +(ip+端口).hahcode%n作為名稱虐急。

一致性hash 是個(gè)可以理解為圓形,這個(gè)圓形稱為hash環(huán)滔迈,環(huán)上可以最多建立2的32次方減1個(gè)節(jié)點(diǎn)止吁。

存數(shù)據(jù): 一般根據(jù)key.hashcode%n=k,如果k 的范圍 1<k<2100,按照順時(shí)針方向燎悍,把數(shù)據(jù)放在node_2100這個(gè)節(jié)點(diǎn)上敬惦。

查找數(shù)據(jù):用同樣方式取模key.hashcode%n得到的值,然后順時(shí)針查找谈山,剛好卡在1到2100之間俄删,那就去獲node_2100上取數(shù)據(jù),如果沒找到奏路,就去第一個(gè)節(jié)點(diǎn)上找畴椰。這里的key就是表里的某個(gè)屬性。例如user表用戶id作為分表策略就是1001.hashcode%n鸽粉。

userId userName Sex
1001 張三 0
1002 李四 1
節(jié)點(diǎn)信息

假如查找數(shù)據(jù)的時(shí)候根據(jù)key.hashcode%n=1000,那順時(shí)針找1<1000<2100,數(shù)據(jù)就落在了node_2100這個(gè)節(jié)點(diǎn)上斜脂,存取數(shù)據(jù)都是這個(gè)規(guī)則。

擴(kuò)容節(jié)點(diǎn)

假如我們現(xiàn)在需要增加第五個(gè)節(jié)點(diǎn)潜叛,這時(shí)候只需要把緊鄰第五個(gè)節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)重新做一次hashcode%5取模就行,不用改動(dòng)其它節(jié)點(diǎn)數(shù)據(jù)壶硅。

擴(kuò)容節(jié)點(diǎn)

原來應(yīng)該落在node_7100和node_1之間的數(shù)據(jù)威兜,現(xiàn)在中間多了一個(gè)node_7200,數(shù)據(jù)就有可能被分配到node_7200上庐椒,然后我們?nèi)?shù)據(jù)會(huì)發(fā)現(xiàn)有時(shí)候7200>key.hashcode%5>7100的數(shù)據(jù)取不到椒舵,因?yàn)槔蠑?shù)據(jù)在node_1節(jié)點(diǎn)上,那怎么辦呢约谈?很簡單只需要對(duì)該節(jié)點(diǎn)重新key.hashcode%5取模分配就好笔宿,其它節(jié)點(diǎn)數(shù)據(jù)不用動(dòng)犁钟。

一致性hash的優(yōu)勢(shì)

分庫分表的算法,通過一致性hash泼橘,擴(kuò)容數(shù)據(jù)只需要遷移一半的數(shù)據(jù)
比如我們有32個(gè)庫涝动,每庫32張表,則
0庫:存在下標(biāo)為0,1,2......31的表
1庫:存在下標(biāo)為32,33,34......63的表
.......
31庫:存在下標(biāo)為992,993,994,1023的表
對(duì)于這樣的分庫分表炬灭,假定按照customerId來分庫分表醋粟,請(qǐng)看分庫分表的算法

//取得customerId的hashCode
int customerIdHashCode = Math.abs(customerId.hashCode());
//使用一致性Hash算法取得customerId應(yīng)該位于的數(shù)據(jù)庫
int dbIndex = (customerIdHashCode % 4096) / (4096 / 32);
//假定每庫為32張表
int tableCountPerDb = 32; 
//取得customerId位于的數(shù)據(jù)庫的啟始表索引
int tableStartIndex = dbIndex * tableCountPerDb;
//用customerId % 每庫表的數(shù)量,得到customerId的步長
int tableStep = customerIdHashCode % tableCountPerDb;
//表的起始索引+步長就是customerId應(yīng)該位于的數(shù)據(jù)表
int tableIndex = tableStartIndex + tableStep;
return tableIndex

弊端:數(shù)據(jù)傾斜容易造成雪崩

節(jié)點(diǎn)不是均勻分配的重归,這樣我們會(huì)造成數(shù)據(jù)分配不均(傾斜)米愿,比如上圖中node_7100和node_4100之間的距離比較大,那落在這一區(qū)間的概率也比較大鼻吮,造成node_7100的數(shù)據(jù)量過大育苟,請(qǐng)求量過大導(dǎo)致雪崩。

解決辦法就是建立虛擬節(jié)點(diǎn)

虛擬節(jié)點(diǎn)并非是一個(gè)真實(shí)的節(jié)點(diǎn)椎木,而是和真實(shí)節(jié)點(diǎn)之間的一個(gè)映射违柏,落在虛擬節(jié)點(diǎn)上的數(shù)據(jù)最終會(huì)被轉(zhuǎn)移到真實(shí)節(jié)點(diǎn)上。

虛擬節(jié)點(diǎn)

虛擬節(jié)點(diǎn)的重建

  • node_6100和node_8100就是虛擬節(jié)點(diǎn)拓哺。這兩個(gè)節(jié)點(diǎn)并非真實(shí)節(jié)點(diǎn)勇垛,而是我們自己添加的節(jié)點(diǎn)。
  • 當(dāng)有數(shù)據(jù)落在node_6100和node_4100之間時(shí)士鸥,數(shù)據(jù)會(huì)落在node_6100上闲孤,這個(gè)時(shí)候我們做判斷發(fā)現(xiàn)node_6100是虛擬節(jié)點(diǎn)并且映射到了node_4100上,然后我們把數(shù)據(jù)直接放在node_4100上就可以了烤礁。
  • node_8100也是虛擬節(jié)點(diǎn)操作和node_6100一樣被映射到了node_2100上讼积。

那虛擬節(jié)點(diǎn)什么時(shí)候加呢?

肯定不是在后期加的脚仔,盡量在真實(shí)節(jié)點(diǎn)確認(rèn)后就設(shè)定虛擬節(jié)點(diǎn)勤众,虛擬節(jié)點(diǎn)沒有數(shù)量限制,原則上設(shè)定的越多分配就越越均勻鲤脏。不過太多也不便于管理们颜。

這個(gè)一致性分表也一樣,如果我們key.hashcode%3 我們會(huì)創(chuàng)建table_1,table_2,table_3三張表猎醇,三張表是后綴是連續(xù)的窥突,所以我們盡量不要這么做,而是在2^32-1的范圍內(nèi)自己計(jì)算好硫嘶,均勻的起名均勻的分布阻问。

文章轉(zhuǎn)載自:
一致性hash與分庫分表
高可用性實(shí)現(xiàn)方式:一致性hash
一致性哈希算法的應(yīng)用及其優(yōu)化

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市沦疾,隨后出現(xiàn)的幾起案子称近,更是在濱河造成了極大的恐慌第队,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刨秆,死亡現(xiàn)場(chǎng)離奇詭異凳谦,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)坛善,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門晾蜘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人眠屎,你說我怎么就攤上這事剔交。” “怎么了改衩?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵岖常,是天一觀的道長。 經(jīng)常有香客問我葫督,道長竭鞍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任橄镜,我火速辦了婚禮偎快,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘洽胶。我一直安慰自己晒夹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布姊氓。 她就那樣靜靜地躺著丐怯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪翔横。 梳的紋絲不亂的頭發(fā)上读跷,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天,我揣著相機(jī)與錄音禾唁,去河邊找鬼效览。 笑死,一個(gè)胖子當(dāng)著我的面吹牛荡短,可吹牛的內(nèi)容都是我干的丐枉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼肢预,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼矛洞!你這毒婦竟也來了洼哎?” 一聲冷哼從身側(cè)響起烫映,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤沼本,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后锭沟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抽兆,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年族淮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辫红。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡祝辣,死狀恐怖贴妻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蝙斜,我是刑警寧澤名惩,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站孕荠,受9級(jí)特大地震影響娩鹉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜稚伍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一弯予、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧个曙,春花似錦锈嫩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至悼沿,卻和暖如春等舔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背糟趾。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來泰國打工慌植, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人义郑。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓蝶柿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親非驮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子交汤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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

  • 這兩天項(xiàng)目中接到一個(gè)需求,好友系統(tǒng),由于用戶量比較多芙扎,好友關(guān)系又是多對(duì)多的關(guān)系星岗,因此,到后期數(shù)據(jù)會(huì)急劇上升戒洼,因此需...
    Newzer閱讀 2,049評(píng)論 0 1
  • 問題場(chǎng)景 近年來B2C俏橘、O2O等商業(yè)概念的提出和移動(dòng)端的發(fā)展,使得分布式系統(tǒng)流行了起來圈浇。分布式系統(tǒng)相對(duì)于單系統(tǒng)寥掐,解...
    JaJian閱讀 530評(píng)論 0 0
  • 業(yè)務(wù)場(chǎng)景 近年來,由于互聯(lián)網(wǎng)的興起磷蜀,B2C召耘、O2O等商業(yè)概念的提出和移動(dòng)端的發(fā)展,使得分布式系統(tǒng)流行起來褐隆。分布式系...
    Christopher若有光閱讀 415評(píng)論 0 1
  • 分布式系統(tǒng)中一致性哈希 問題場(chǎng)景 近年來B2C怎茫、O2O等商業(yè)概念的提出和移動(dòng)端的發(fā)展,使得分布式系統(tǒng)流行了起來妓灌。分...
    符文杰9527閱讀 365評(píng)論 0 0
  • 夜鶯2517閱讀 127,718評(píng)論 1 9