Redis|集群


1. Redis集群

1.1 概述

Redis3.0以后推出Redis cluster集群方案素标。

1.2 Reids cluster 架構(gòu)圖


架構(gòu)細節(jié)

  1. 所有reids節(jié)點彼此互聯(lián)(PING-PONG機制)报破,內(nèi)部使用二進制協(xié)議傳輸和帶寬。
  2. 節(jié)點的fail是通過集群中超過半數(shù)的節(jié)點檢測失效時才生效。
  3. 客戶端與redis節(jié)點直連耸彪,不需要中間件proxy隘世,客戶端不需要連接集群所有節(jié)點,連接集群中任何一個可用節(jié)點即可怯邪。
  4. reids-cluster把所有的物理節(jié)點映射到[0-16383]slot上绊寻,cluster負責維護node<->slot<->value
  • 集群的整個數(shù)據(jù)庫被分為了16384個槽(slot),數(shù)據(jù)庫的每個鍵都屬于這16384槽中的一個悬秉,集群中的每個節(jié)點可以處理0到16384個槽澄步。
  • 當數(shù)據(jù)庫的16384個槽都有節(jié)點處理時,集群處于上線狀態(tài)(ok)和泌;相反的村缸,如果數(shù)據(jù)庫中有任何一個槽沒得到處理,那么集群處于下線狀態(tài)(fail) 武氓。
  • 當在redis集群放置一個key-value時梯皿,redis先對key使用crcy16算法計算出一個結(jié)果仇箱,然后把這個結(jié)果對16384求余數(shù),這樣每一個key都會對應一個編號在0-16383之間的槽东羹,redis會根據(jù)節(jié)點量大致均等的將槽映射到不同的節(jié)點中剂桥。

1.3 Redis cluster選舉:容錯

  1. 節(jié)點失效判斷:選舉過程是集群中所有master都參與,如果半數(shù)以上的master節(jié)點與master節(jié)點之間的通信超過(cluster-node-timeout)属提,就認為當前master節(jié)點掛掉渊额。
  2. 集群失效判斷:什么時候整個集群不可用(cluster_state:fail)?
    • 如果集群任意master掛掉垒拢,且當前master沒有slave旬迹,則集群進入fail狀態(tài)。也可以理解為集群的[0-16383]slot映射不完全時進入fail狀態(tài)求类。
    • 如果集群超過半數(shù)的master掛掉奔垦,無論是否有slave,集群進入fail狀態(tài)尸疆。

2. redis cluster 安裝

2.1 安裝Ruby環(huán)境

reids cluster需要使用集群管理redis-trib.rb椿猎,它的執(zhí)行相應依賴Ruby環(huán)境。

  • 第一步:安裝ruby
yum   install ruby   
yum   install rubygems 
  • 第二步:安裝ruby和redis的接口程序redis
gem install redis 

安裝到這里就出現(xiàn)問題了寿弱,CentOS 7庫中的ruby的版本支持到2.0.0犯眠,可gem 安裝redis需要最低是2.2.2,下面采用rvm來更新ruby:

# 具體RVM安裝命令地址:http://rvm.io/
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB   # 安裝GPG秘鑰
curl -sSL https://get.rvm.io | bash -s stable    # 安裝RVM
find / -name rvm -print   # 查詢支持rvm的所有版本
rvm list known
rvm install 2.4.5         # 安裝2.4.5版本
rvm use 2.4.5             # 使用rvm 2.4.5
rvm use 2.4.5 --default   # 設置2.4.5 為默認版本
rvm remove 2.3.5          # 刪除2.3.5這個版本
ruby --version            # 查看ruby當前版本
  • 第三步:復制redis-3.2.9/src/redis-trib.rb文件到/usr/local/redis-cluster目錄
    前面我安裝的redis單機版是redis-3.2.9
cd /usr/local/
mkdir redis_cluster  # 創(chuàng)建集群目錄
cp   redis-3.2.9/src/redis-trib.rb /usr/local/redis_cluster/ -r  

2.2 安裝RedisCluster

Redis集群最少需要三臺主服務器症革,三臺從服務器筐咧。
端口號分別為:7000~7001

  • 第一步:在local目錄下創(chuàng)建 7000 7001 7002 7003 7004 7005,并且拷貝單機版安裝時噪矛,生成的bin目錄里面的所有文件量蕊,到7000 7001...文件中。
mkdir 7000 7001 7002  # 創(chuàng)建文件夾7000 70001 7002 ....
cp  /redis/bin/* /usr/local/7000/  -r
cp  /redis/bin/* /usr/local/7001/  -r
.......
  • 第二步:修改7000艇挨、7001....目錄下的redis.conf配置文件残炮,修改端口:和目錄相對應7000、7001缩滨,打開Cluster-enable yes
  • 第三步:啟動所有的實例
./redis-server redis.conf -p 7000
....
  • 第四步:創(chuàng)建redis集群
./redis-trib.rb create --replicas 1 172.19.165.143:7000 172.19.165.143:7001 172.19.165.143:7002 172.19.165.143:7003 172.19.165.143:7004 172.19.165.143:7005
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
172.19.165.143:7000
172.19.165.143:7001
172.19.165.143:7002
Adding replica 172.19.165.143:7003 to 172.19.165.143:7000
Adding replica 172.19.165.143:7004 to 172.19.165.143:7001
Adding replica 172.19.165.143:7005 to 172.19.165.143:7002
M: f649719d25e833a2cfa28877686334e4bee592b4 172.19.165.143:7000
   slots:0-5460 (5461 slots) master
M: 87cbfb735fc468193e3e8fd06b028f7079478f16 172.19.165.143:7001
   slots:5461-10922 (5462 slots) master
M: 5988d3d9be04d3b01b0b1028add0ee5b3ac793b8 172.19.165.143:7002
   slots:10923-16383 (5461 slots) master
S: a9bc31025e9188826a4fde74f1379d10ac8f96de 172.19.165.143:7003
   replicates f649719d25e833a2cfa28877686334e4bee592b4
S: 13bee88df50bf50a763d42135201c10e61762957 172.19.165.143:7004
   replicates 87cbfb735fc468193e3e8fd06b028f7079478f16
S: 5fe655116e404a989c9bce4a4aa206b30eb65905 172.19.165.143:7005
   replicates 5988d3d9be04d3b01b0b1028add0ee5b3ac793b8
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join...
>>> Performing Cluster Check (using node 172.19.165.143:7000)
M: f649719d25e833a2cfa28877686334e4bee592b4 172.19.165.143:7000
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
S: a9bc31025e9188826a4fde74f1379d10ac8f96de 172.19.165.143:7003
   slots: (0 slots) slave
   replicates f649719d25e833a2cfa28877686334e4bee592b4
S: 13bee88df50bf50a763d42135201c10e61762957 172.19.165.143:7004
   slots: (0 slots) slave
   replicates 87cbfb735fc468193e3e8fd06b028f7079478f16
M: 5988d3d9be04d3b01b0b1028add0ee5b3ac793b8 172.19.165.143:7002
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
M: 87cbfb735fc468193e3e8fd06b028f7079478f16 172.19.165.143:7001
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
S: 5fe655116e404a989c9bce4a4aa206b30eb65905 172.19.165.143:7005
   slots: (0 slots) slave
   replicates 5988d3d9be04d3b01b0b1028add0ee5b3ac793b8
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

創(chuàng)建過程中遇到問題參考這篇文章

3. 命令客戶端連接集群

命令:

./redis-cli –h 127.0.0.1 –p 7000 –c
set key1 123

注意:-c 表示是以redis集群方式進行連接

./redis-cli -p 7001 -c
127.0.0.1:7001>get key1
-> Redirected to slot [9189] located at 127.0.0.1:7000
OK
127.0.0.1:7000>

4. 查看集群命令

查看集群狀態(tài)

127.0.0.1:7000> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:3
cluster_stats_messages_sent:926
cluster_stats_messages_received:926

查看集群中的節(jié)點:

127.0.0.1:7000> cluster nodes

5. 維護節(jié)點

集群創(chuàng)建成功后可以繼續(xù)向集群中添加節(jié)點

5.1 添加主節(jié)點

  • 還是向前面一樣先創(chuàng)建7007節(jié)點
  • 添加7007節(jié)點作為新節(jié)點
./redis-trib.rb add-node 127.0.0.1:7007 127.0.0.1:7000
  • 查看集群節(jié)點會發(fā)現(xiàn)7007已添加在集群中

5.2 槽分配(數(shù)據(jù)遷移)

添加完主節(jié)點需要對主節(jié)點進行hash槽分配势就,這樣該主節(jié)才可以存儲數(shù)據(jù)。
給剛添加的7007結(jié)點分配槽:

  • 第一步:連接上集群(連接集群中任意一個可用節(jié)點都可以)
./redis-trib.rb reshard 172.19.165.143 :7000
  • 第二步:輸入要分配槽的數(shù)量
    出現(xiàn)提示:How many slots do you want to move (from 1 to 16384)?這個提示時脉漏,直接輸入要分配的數(shù)量苞冯,如:3000。
  • 第三步:輸入接收槽的結(jié)點id
    這里準備給7007分配槽鸠删,通過cluster nodes 查看7007節(jié)點id:15b809eadae88955e36bcdbb8144f61bbbaf38fb
    出現(xiàn)what is the receiving node ID?提示時輸入上面的id抱完。
  • 第四步:輸入源節(jié)點id:all
    注意:輸入源節(jié)點id,槽將從源節(jié)點中拿刃泡,分配后的槽在源節(jié)點中就不存在了巧娱,輸入all從所有源節(jié)點中獲取槽碉怔,輸入done取消分配。
  • 第五部:輸入yes開始移動槽到目標結(jié)點id

5.3 添加從節(jié)點

添加7008從結(jié)點禁添,將7008作為7007主節(jié)點的從結(jié)點
命令:

./redis-trib.rb add-node --slave --master-id  主節(jié)點id   新節(jié)點的ip和端口   舊節(jié)點ip和端口(集群中任一節(jié)點都可以)

注意:如果原來該結(jié)點在集群中的配置信息已經(jīng)生成到cluster-config-file指定的配置文件中(如果cluster-config-file沒有指定則默認為nodes.conf)撮胧,這時可能會報錯:

[ERR] Node XXXXXX is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0

解決方法是刪除生成的配置文件nodes.conf,刪除后再執(zhí)行./redis-trib.rb add-node指令

5.4刪除節(jié)點

./redis-trib.rb del-node 127.0.0.1:7005 節(jié)點id

刪除已經(jīng)占有hash槽的結(jié)點會失敗老翘,報錯:

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

解決辦法芹啥,把已經(jīng)占用的槽分配出去

6. jedis連接集群

代碼實現(xiàn)

@Test
public void testJedisCluster() throws Exception {
    //創(chuàng)建一連接,JedisCluster對象,在系統(tǒng)中是單例存在
    Set<HostAndPort> nodes = new HashSet<>();
    nodes.add(new HostAndPort("172.19.165.143", 7000));
    nodes.add(new HostAndPort("172.19.165.143", 7001));
    nodes.add(new HostAndPort("172.19.165.143", 7002));
    nodes.add(new HostAndPort("172.19.165.143", 7003));
    nodes.add(new HostAndPort("172.19.165.143", 7004));
    nodes.add(new HostAndPort("172.19.165.143", 7005));
    JedisCluster cluster = new JedisCluster(nodes);
    //執(zhí)行JedisCluster對象中的方法铺峭,方法和redis一一對應墓怀。
    cluster.set("cluster-test", "my jedis cluster test");
    String result = cluster.get("cluster-test");
    System.out.println(result);
    //程序結(jié)束時需要關(guān)閉JedisCluster對象
    cluster.close();
}


Spring
配置applicationContext.xml

<!-- 連接池配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <!-- 最大連接數(shù) -->
    <property name="maxTotal" value="30" />
    <!-- 最大空閑連接數(shù) -->
    <property name="maxIdle" value="10" />
    <!-- 每次釋放連接的最大數(shù)目 -->
    <property name="numTestsPerEvictionRun" value="1024" />
    <!-- 釋放連接的掃描間隔(毫秒) -->
    <property name="timeBetweenEvictionRunsMillis" value="30000" />
    <!-- 連接最小空閑時間 -->
    <property name="minEvictableIdleTimeMillis" value="1800000" />
    <!-- 連接空閑多久后釋放, 當空閑時間>該值 且 空閑連接>最大空閑連接數(shù) 時直接釋放 -->
    <property name="softMinEvictableIdleTimeMillis" value="10000" />
    <!-- 獲取連接時的最大等待毫秒數(shù),小于零:阻塞不確定的時間,默認-1 -->
    <property name="maxWaitMillis" value="1500" />
    <!-- 在獲取連接的時候檢查有效性, 默認false -->
    <property name="testOnBorrow" value="true" />
    <!-- 在空閑時檢查有效性, 默認false -->
    <property name="testWhileIdle" value="true" />
    <!-- 連接耗盡時是否阻塞, false報異常,ture阻塞直到超時, 默認true -->
    <property name="blockWhenExhausted" value="false" />
</bean>
<!-- redis集群 -->
<bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
    <constructor-arg index="0">
        <set>
            <bean class="redis.clients.jedis.HostAndPort">
                <constructor-arg index="0" value="172.19.165.143"></constructor-arg>
                <constructor-arg index="1" value="7000"></constructor-arg>
            </bean>
            <bean class="redis.clients.jedis.HostAndPort">
                <constructor-arg index="0" value="172.19.165.143"></constructor-arg>
                <constructor-arg index="1" value="7001"></constructor-arg>
            </bean>
            <bean class="redis.clients.jedis.HostAndPort">
                <constructor-arg index="0" value="172.19.165.143"></constructor-arg>
                <constructor-arg index="1" value="7002"></constructor-arg>
            </bean>
            <bean class="redis.clients.jedis.HostAndPort">
                <constructor-arg index="0" value="172.19.165.143"></constructor-arg>
                <constructor-arg index="1" value="7003"></constructor-arg>
            </bean>
            <bean class="redis.clients.jedis.HostAndPort">
                <constructor-arg index="0" value="172.19.165.143"></constructor-arg>
                <constructor-arg index="1" value="7004"></constructor-arg>
            </bean>
            <bean class="redis.clients.jedis.HostAndPort">
                <constructor-arg index="0" value="172.19.165.143"></constructor-arg>
                <constructor-arg index="1" value="7005"></constructor-arg>
            </bean>
        </set>
    </constructor-arg>
    <constructor-arg index="1" ref="jedisPoolConfig"></constructor-arg>
</bean>

學習
Redis3.2.1集群搭建

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市卫键,隨后出現(xiàn)的幾起案子傀履,更是在濱河造成了極大的恐慌,老刑警劉巖莉炉,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钓账,死亡現(xiàn)場離奇詭異,居然都是意外死亡絮宁,警方通過查閱死者的電腦和手機梆暮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绍昂,“玉大人啦粹,你說我怎么就攤上這事≈巫ǎ” “怎么了卖陵?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵遭顶,是天一觀的道長张峰。 經(jīng)常有香客問我,道長棒旗,這世上最難降的妖魔是什么喘批? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮铣揉,結(jié)果婚禮上饶深,老公的妹妹穿的比我還像新娘。我一直安慰自己逛拱,他們只是感情好敌厘,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著朽合,像睡著了一般俱两。 火紅的嫁衣襯著肌膚如雪饱狂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天宪彩,我揣著相機與錄音休讳,去河邊找鬼。 笑死尿孔,一個胖子當著我的面吹牛俊柔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播活合,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼雏婶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了白指?” 一聲冷哼從身側(cè)響起尚骄,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎侵续,沒想到半個月后倔丈,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡状蜗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年需五,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片轧坎。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡宏邮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出缸血,到底是詐尸還是另有隱情蜜氨,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布捎泻,位于F島的核電站飒炎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏笆豁。R本人自食惡果不足惜郎汪,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望闯狱。 院中可真熱鬧煞赢,春花似錦、人聲如沸哄孤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至凝危,卻和暖如春饭弓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背媒抠。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工弟断, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人趴生。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓阀趴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親苍匆。 傳聞我的和親對象是個殘疾皇子刘急,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

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