redis_集群

1拼窥、為什么要弄redis集群

集群技術(shù)是構(gòu)建高性能網(wǎng)站架構(gòu)的重要手段拳锚,試想在網(wǎng)站承受高并發(fā)訪問壓力的同時(shí),還需要從海量數(shù)據(jù)中查詢出滿足條件的數(shù)據(jù)情臭,并快速響應(yīng),我們必然想到的是將數(shù)據(jù)進(jìn)行切片玉组,把數(shù)據(jù)根據(jù)某種規(guī)則放入多個(gè)不同的服務(wù)器節(jié)點(diǎn)谎柄,來降低單節(jié)點(diǎn)服務(wù)器的壓力。上篇redis_主從我們講到了 Redis 的主從復(fù)制技術(shù)惯雳,當(dāng)實(shí)現(xiàn)了多節(jié)點(diǎn)的 master-slave 后朝巫,我們也可以把它叫做集群,但我們今天要講的集群主要是利用切片技術(shù)來組建的集群石景。我們最后希望達(dá)到的是類似下圖:

redis集群拓?fù)鋱D

2劈猿、實(shí)現(xiàn)策略

因?yàn)閺?.0開始以后官方已經(jīng)支持了 redis cluster,http://redis.io/topics/cluster-tutorial

集群要實(shí)現(xiàn)的目的是要將不同的 key 分散放置到不同的 redis 節(jié)點(diǎn),這里我們需要一個(gè)規(guī)則或者算法潮孽,通常的做法是獲取 key 的哈希值揪荣,然后根據(jù)節(jié)點(diǎn)數(shù)來求模,但這種做法有其明顯的弊端往史,當(dāng)我們需要增加或減少一個(gè)節(jié)點(diǎn)時(shí)仗颈,會(huì)造成大量的 key 無法命中,這種比例是相當(dāng)高的,所以就有人提出了一致性哈希的概念挨决。

由于官方版本是基于哈希槽(hash slot)的概念來實(shí)現(xiàn)的请祖,我們還是從其官方介紹中翻譯解釋一下:

Redis 集群中內(nèi)置了 16384 個(gè)哈希槽,當(dāng)需要在 Redis 集群中放置一個(gè) key-value 時(shí)脖祈,redis 先對(duì) key 使用 crc16 算法算出一個(gè)結(jié)果肆捕,然后把結(jié)果對(duì) 16384 求余數(shù),這樣每個(gè) key 都會(huì)對(duì)應(yīng)一個(gè)編號(hào)在 0-16383 之間的哈希槽盖高,redis 會(huì)根據(jù)節(jié)點(diǎn)數(shù)量大致均等的將哈希槽映射到不同的節(jié)點(diǎn)慎陵。

使用哈希槽的好處就在于可以方便的添加或移除節(jié)點(diǎn)

當(dāng)需要增加節(jié)點(diǎn)時(shí),只需要把其他節(jié)點(diǎn)的某些哈希槽挪到新節(jié)點(diǎn)就可以了喻奥;

當(dāng)需要移除節(jié)點(diǎn)時(shí)席纽,只需要把移除節(jié)點(diǎn)上的哈希槽挪到其他節(jié)點(diǎn)就行了;

3映凳、集群實(shí)現(xiàn)

對(duì)于我們來說胆筒,在新增或移除節(jié)點(diǎn)的能做到無縫(即不需要重啟集群),這點(diǎn)它做到了诈豌。還是來看看具體的實(shí)現(xiàn)吧:


新建3個(gè)實(shí)例

新建redis_cluster文件夾下面新建6000仆救、6100、6200三個(gè)文件夾矫渔。

把src 目錄下面的redis-server彤蔽、redis.conf這兩個(gè)文件分別拷貝到這三個(gè)目錄里面,拷貝完之后就像這樣子了:

[mysql@localhost 6000]$ ll

-rw-rw-r--. 1 mysql mysql ? ? 116 Aug 21 05:37 redis.conf

-rwxrwxr-x. 1 mysql mysql 7820101 Aug 21 05:29 redis-server

修改每個(gè)目錄下面的redis.conf文件因?yàn)槲覀儐?dòng)的端口是不一樣的,vi redis.conf刪除里面的所有添加如下的:

daemonize yes ? //指定以守護(hù)進(jìn)程啟動(dòng)

port 6000 ? ? //啟動(dòng)端口

cluster-enabled yes

cluster-config-file nodes.conf

cluster-node-timeout 5000

appendonly yes

依次啟動(dòng)每一個(gè)實(shí)例文件夾下面的./redis-server ./redis.conf庙洼,這樣的話3個(gè)實(shí)例就啟動(dòng)了顿痪,但是如何將3個(gè)實(shí)例維護(hù)成一個(gè)集群呢,在src目錄下面執(zhí)行:

./redis-trib.rb create --replicas 0 127.0.0.1:6000 127.0.0.1:6100 127.0.0.1:6200

執(zhí)行以后是不是會(huì)發(fā)現(xiàn)執(zhí)行失敗提示沒有redis-trib.rb文件油够,好吧我們還忘了裝一個(gè)蚁袭,因?yàn)槲覀儓?zhí)行的是ruby命令,所以還需要安裝ruby:

https://rubygems.org/gems/redis下載石咬,然后離線安裝揩悄。sudo gem install redis-3.3.1.gem --local

安裝完成以后再src目錄下面就有了redis-trib.rb文件。

執(zhí)行上面的集群命令控制臺(tái)輸出如下:

集群安裝

來試試集群的效果吧:

在6000端口實(shí)例上測(cè)試

[mysql@localhost src]$ ./redis-cli -c -p 6000

127.0.0.1:6000> get name

-> Redirected to slot [5798] located at 127.0.0.1:6100 ? ? ? //發(fā)現(xiàn)當(dāng)沒有指定的key的時(shí)候會(huì)重定向到集群的其它機(jī)器去找

127.0.0.1:6100> set aaa 111

OK

127.0.0.1:6100> get aaa

"111"

//如上索性在6100實(shí)例的機(jī)器上面set aaa的值鬼悠,然后在6200的機(jī)器上面去查

[mysql@localhost src]$ ./redis-cli -c -p 6200

127.0.0.1:6200> get aaa

-> Redirected to slot [10439] located at 127.0.0.1:6100 ? //發(fā)現(xiàn)重定向去6100的端口的實(shí)例上找到了結(jié)果

"111"

//在6200的機(jī)器上面直接重置aaa為1234

127.0.0.1:6200> set aaa 1234

-> Redirected to slot [10439] located at 127.0.0.1:6100 ?//還是重定向去6100的端口的實(shí)例上更新結(jié)果

OK

從上面的結(jié)果可以看出删性,集群中的節(jié)點(diǎn)是會(huì)進(jìn)行通訊的,從而能找到不同的key在不同實(shí)例上焕窝,在機(jī)器固定的情況下蹬挺,key唯一時(shí)后續(xù)對(duì)其的所有更新以及查詢都會(huì)映射到這一臺(tái)機(jī)器上面。

當(dāng)然我們的集群的節(jié)點(diǎn)是不會(huì)一成不變的它掂,我們隨時(shí)有可能擴(kuò)容巴帮、縮容那該怎么來實(shí)現(xiàn)呢?下面來講講集群節(jié)點(diǎn)的變化吧。

4榕茧、集群變更

我們先在上面的基礎(chǔ)上試試添加端口為6300的實(shí)例发乔,重復(fù)操作如上:

[mysql@localhost redis_cluster]$ mkdir 6300

[mysql@localhost redis_cluster]$ ll

total 16

drwxrwxr-x. 2 mysql mysql 4096 Aug 21 05:40 6000

drwxrwxr-x. 2 mysql mysql 4096 Aug 21 05:40 6100

drwxrwxr-x. 2 mysql mysql 4096 Aug 21 05:40 6200

drwxrwxr-x. 2 mysql mysql 4096 Aug 21 06:27 6300

[mysql@localhost redis_cluster]$ cp ../redis/redis-3.2.3/src/redis-server ../redis/redis-3.2.3/redis.conf 6300/

不要忘了修改redis.conf,具體配置如上文提到的雪猪。

[mysql@localhost 6300]$ ?./redis-server ./redis.conf

[mysql@localhost 6300]$ netstat -an | grep 6300

tcp ? ? ? ?0 ? ? ?0 0.0.0.0:16300 ? ? ? ? ? ? ? 0.0.0.0:* ? ? ? ? ? ? ? ? ? LISTEN

tcp ? ? ? ?0 ? ? ?0 0.0.0.0:6300 ? ? ? ? ? ? ? ?0.0.0.0:* ? ? ? ? ? ? ? ? ? LISTEN

tcp ? ? ? ?0 ? ? ?0 :::16300 ? ? ? ? ? ? ? ? ? ?:::* ? ? ? ? ? ? ? ? ? ? ? ?LISTEN

tcp ? ? ? ?0 ? ? ?0 :::6300 ? ? ? ? ? ? ? ? ? ? :::* ? ? ? ? ? ? ? ? ? ? ? ?LISTEN

新的redis實(shí)例已經(jīng)啟動(dòng)好了,然后需要把它加到已有的集群啦:

./redis-trib.rb add-node 127.0.0.1:6300 127.0.0.1:6000

新的集群實(shí)例圖

如上已經(jīng)能查看到新的實(shí)例啦起愈,為什么6300這個(gè)新的實(shí)例的connected后面沒有分配hash槽呢只恨,別慌我們還沒有reshard

執(zhí)行命令:./redis-trib.rb reshard 127.0.0.1:6300?

我們想從6000節(jié)點(diǎn)中分配1000個(gè)hash槽位出來:

摘自重新分配的一段操作日志

這樣有hash槽了,當(dāng)crc16(key) / 16384 的結(jié)果在該節(jié)點(diǎn)的所在區(qū)間時(shí)抬虽,數(shù)據(jù)就放在該節(jié)點(diǎn)上官觅。

redis 采用的crc16算法詳見:http://blog.csdn.net/guodongxiaren/article/details/44706613

如果后續(xù)有時(shí)間的話我也會(huì)找一個(gè)java版的crc16 demo.

如何為每一個(gè)主節(jié)點(diǎn)增加從節(jié)點(diǎn)呢?

好吧阐污,先創(chuàng)建6400端口實(shí)例看看休涤,具體新建文件夾以及配置和重啟實(shí)例我就不再講了,上面以及有了笛辟。

./redis-trib.rb add-node --slave 127.0.0.1:6400 127.0.0.1:6000

為集群的節(jié)點(diǎn)添加從節(jié)點(diǎn)

我們也可以試試在從節(jié)點(diǎn)6400上面做set操作:

127.0.0.1:6400> set da87

(error) ERR wrong number of arguments for 'set' command

127.0.0.1:6400> set da

(error) ERR wrong number of arguments for 'set' command

很不幸功氨,確實(shí)不能做set操作會(huì)報(bào)錯(cuò),從節(jié)點(diǎn)只能用于做讀工作手幢。

我們?nèi)绾蝸韯h除一個(gè)節(jié)點(diǎn)呢:

[mysql@localhost src]$ ./redis-trib.rb del-node 127.0.0.1:6000 'eb868ce2c102b897ee0a48cd8893288c36bacf5c'

>>> Removing node eb868ce2c102b897ee0a48cd8893288c36bacf5c from cluster 127.0.0.1:6000

[ERR] Node 127.0.0.1:6000 is not empty! Reshard data away and try again.

[mysql@localhost src]$

我們發(fā)現(xiàn)刪除6000端口的實(shí)例失敗了捷凄,應(yīng)該是上面還有一些數(shù)據(jù)如果直接刪除就有數(shù)據(jù)丟失,我們應(yīng)該把數(shù)據(jù)移到別的節(jié)點(diǎn)去:

./redis-trib.rb reshard 127.0.0.1:6000 ?//移除6000實(shí)例的數(shù)據(jù)

然后輸出了很多信息围来,很多數(shù)值和ID都可以從這段信息中找到跺涤。

How many slots do you want to move (from 1 to 16384)? 5461

會(huì)問你要移動(dòng)多少個(gè)哈希槽,我們把 6000上的所有哈希槽都移走监透,5461 這個(gè)數(shù)字可以從終端上看到桶错,或許你的實(shí)際情況不是這個(gè)數(shù)字。

What is the receiving node ID? d4467ece7cca245345b71cc1f639508f4f7831c4 ?//選定移動(dòng)到6300端口的實(shí)例上面胀蛮,實(shí)例ID

Please enter all the source node IDs.

Type 'all' to use all the nodes as source nodes for the hash slots.

Type 'done' once you entered all the source nodes IDs.

Source node #1:eb868ce2c102b897ee0a48cd8893288c36bacf5c?//選定移除掉6000端口的實(shí)例上面院刁,實(shí)例ID

Source node #2:done

之后,redis 列出了重新分片計(jì)劃醇滥,最后問你

Do you want to proceed with the proposed reshard plan (yes/no)? yes

中間有一些重新分配的刷屏信息省略黎比。

[mysql@localhost src]$ ./redis-cli -p 6300

127.0.0.1:6300> keys *

1) "aaa"

127.0.0.1:6300>

數(shù)據(jù)移到6300實(shí)例上面啦,我們?cè)賮碓囋噭h除6000端口實(shí)例吧:

[mysql@localhost src]$ ./redis-trib.rb del-node 127.0.0.1:6000 'eb868ce2c102b897ee0a48cd8893288c36bacf5c'

>>> Removing node eb868ce2c102b897ee0a48cd8893288c36bacf5c from cluster 127.0.0.1:6000

>>> Sending CLUSTER FORGET messages to the cluster...

>>> SHUTDOWN the node.

[mysql@localhost src]$ ./redis-cli -c -p 6000

Could not connect to Redis at 127.0.0.1:6000: Connection refused

Could not connect to Redis at 127.0.0.1:6000: Connection refused

最終我們還是刪除成功啦鸳玩!維護(hù)一個(gè)redis集群就是這么簡(jiǎn)單阅虫。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市不跟,隨后出現(xiàn)的幾起案子颓帝,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,686評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件购城,死亡現(xiàn)場(chǎng)離奇詭異吕座,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)瘪板,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,668評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門吴趴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人侮攀,你說我怎么就攤上這事锣枝。” “怎么了兰英?”我有些...
    開封第一講書人閱讀 158,160評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵撇叁,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我畦贸,道長(zhǎng)陨闹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,736評(píng)論 1 284
  • 正文 為了忘掉前任薄坏,我火速辦了婚禮趋厉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘胶坠。我一直安慰自己觅廓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,847評(píng)論 6 386
  • 文/花漫 我一把揭開白布涵但。 她就那樣靜靜地躺著杈绸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪矮瘟。 梳的紋絲不亂的頭發(fā)上瞳脓,一...
    開封第一講書人閱讀 50,043評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音澈侠,去河邊找鬼劫侧。 笑死,一個(gè)胖子當(dāng)著我的面吹牛哨啃,可吹牛的內(nèi)容都是我干的烧栋。 我是一名探鬼主播,決...
    沈念sama閱讀 39,129評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼拳球,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼审姓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起祝峻,我...
    開封第一講書人閱讀 37,872評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤魔吐,失蹤者是張志新(化名)和其女友劉穎扎筒,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酬姆,經(jīng)...
    沈念sama閱讀 44,318評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嗜桌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,645評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辞色。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骨宠。...
    茶點(diǎn)故事閱讀 38,777評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖相满,靈堂內(nèi)的尸體忽然破棺而出诱篷,到底是詐尸還是另有隱情,我是刑警寧澤雳灵,帶...
    沈念sama閱讀 34,470評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站闸盔,受9級(jí)特大地震影響悯辙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜迎吵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,126評(píng)論 3 317
  • 文/蒙蒙 一躲撰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧击费,春花似錦拢蛋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,861評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至圆仔,卻和暖如春垃瞧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背坪郭。 一陣腳步聲響...
    開封第一講書人閱讀 32,095評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工个从, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人歪沃。 一個(gè)月前我還...
    沈念sama閱讀 46,589評(píng)論 2 362
  • 正文 我出身青樓嗦锐,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親沪曙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子奕污,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,687評(píng)論 2 351

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

  • 本文檔翻譯自 http://redis.io/topics/cluster-tutorial 。 本文檔是 Red...
    會(huì)跳舞的機(jī)器人閱讀 66,924評(píng)論 2 21
  • 前言 Redis 是我們目前大規(guī)模使用的緩存中間件液走,由于它強(qiáng)大高效而又便捷的功能菊值,得到了廣泛的使用外驱。單節(jié)點(diǎn)的Red...
    Kevin_ZGJ閱讀 11,675評(píng)論 19 133
  • 轉(zhuǎn)自:https://www.zybuluo.com/phper/note/195558 前言 redis 是我們...
    yannhuang閱讀 1,680評(píng)論 0 2
  • 開始部署之前昵宇,務(wù)必先看最后一條 從官網(wǎng)下載和編譯redis安裝包 配置redis創(chuàng)建redis.conf, 內(nèi)容如...
    yandaren閱讀 3,341評(píng)論 0 3
  • 日更第十二天 愛上寫作,好像有二十余年了儿子。 在那青蔥年少輕狂的學(xué)生時(shí)期瓦哎,好像就有這個(gè)想法和行動(dòng)了,但沒有持續(xù)柔逼,或者...
    白豐閣閱讀 315評(píng)論 0 1