redis高級應用(集羣搭建、集羣分區原理、集羣操做)

 

本文是redis學習系列的第四篇,前面咱們學習了redis的數據結構和一些高級特性,點擊下面連接可回看node

《詳細講解redis數據結構(內存模型)以及經常使用命令》git

《redis高級應用(主從、事務與鎖、持久化)》redis

本文咱們繼續學習redis的高級特性——集羣。本文主要內容包括集羣搭建、集羣分區原理和集羣操做的學習。算法

 

Redis集羣簡介

Redis 集羣是3.0以後才引入的,在3.0以前,使用哨兵(sentinel)機制(本文將不作介紹,你們可另行查閱)來監控各個節點之間的狀態。Redis 集羣可謂是讓不少人久等了。sql

Redis 集羣是一組能進行數據共享的Redis 實例(服務或者節點)的設施,集羣可使用的功能是普通單機 Redis 所能使用的功能的一個子集;Redis 集羣一般具備高可用、可擴展性、分佈式、容錯等特性。瞭解redis的集羣后,這些晦澀的概念可結合redis的主從、集羣分區和集羣運維等角度理解體會。緩存

Redis集羣搭建

建立集羣文件夾

在/usr/local/下新建redis-cluster目錄並在redis-cluster下新建7031~7036共6個文件夾,這6個文件夾表明建立redis集羣的6個節點。以下ruby

[root@localhost local]# mkdir -p /usr/local/redis-cluster數據結構

[root@localhost redis-cluster]# mkdir 7031 7032 7033 7034 7035 7036app

拷貝修改配置文件

將已有的/usr/local/redis/etc/下的redis.conf拷貝到新建立的7031目錄中

[root@localhost etc]# cp redis.conf /usr/local/redis-cluster/7031

[root@localhost 7031]# vi redis.conf

修改項以下:

(1)綁定端口,port 7031

(2)綁定IP,bind 192.168.2.128

(3)指定數據存放路徑,dir /usr/local/redis-cluster/7031

(4)啓動集羣模式,cluster-enabled yes

(5)指定集羣節點配置文件,cluster-config-file nodes-7031.conf

(6)後臺啓動,daemonize yes

(7)指定集羣節點超時時間,cluster-node-timeout 5000

(8)指定持久化方式,appendonly yes

上面紅色項目最好所有設置,否則會出意想不到的錯誤,703x最好與節點文件夾保持一致。

將7031的redis.conf改完後再拷貝到剩下的5個目錄中,而後只要全局替換redis.conf中的7031爲相應的節點便可。

安裝ruby

因爲Redis 集羣客戶端實現不多,redis集羣的啓動須要用到ruby實現的redis-trib.rb,因此咱們須要先安裝ruby。

[root@localhost redis-cluster]# yum install ruby

[root@localhost redis-cluster]# yum install rubygems

[root@localhost redis-cluster]# gem install redis

啓動redis實例

[root@localhost redis-cluster]# 

/usr/local/redis/bin/redis-server /usr/local/redis-cluster/7031/redis.conf

 

分別啓動6個redis實例。也能夠用腳本循環啓動,這樣更方便省時

 

[root@localhost redis-cluster]#

for((i=1;i<=6;i++)); do /usr/local/redis/bin/redis-server /usr/local/redis-cluster/703$i/redis.conf; done

 

查看redis實例是否啓動成功

 

[root@localhost redis-cluster]# netstat -tunpl | grep redis-server

#或者

[root@localhost redis-cluster]# ps -ef | grep redis-server

 

 

建立並啓動集羣

進入redis安裝目錄的bin目錄下

[root@localhost ~]# cd /usr/local/redis/bin/

[root@localhost bin]#./redis-trib.rb create --replicas 1 192.168.2.128:7031 192.168.2.128:7032 192.168.2.128:7033 192.168.2.128:7034 192.168.2.128:7035 192.168.2.128:7036 

 

命令的意義以下:

給定 redis-trib.rb 程序的命令是 create,表示建立一個新的集羣。選項 --replicas 1 表示爲集羣中的每一個主節點建立一個從節點。以後跟着的其餘參數則是實例的地址列表, 指定使用這些地址所指示的實例來建立新集羣。

 

>>> Creating cluster

>>> Performing hash slots allocation on 6 nodes...

Using 3 masters:

192.168.2.128:7031

192.168.2.128:7032

192.168.2.128:7033

Adding replica 192.168.2.128:7034 to 192.168.2.128:7031

Adding replica 192.168.2.128:7035 to 192.168.2.128:7032

Adding replica 192.168.2.128:7036 to 192.168.2.128:7033

......

[OK] All nodes agree about slots configuration.

>>> Check for open slots...

>>> Check slots coverage...

[OK] All 16384 slots covered.

 

「All 16384 slots covered.」表示集羣中的 16384 個槽都有至少一個主節點在處理, 集羣運做正常。從打印出來的信息也能夠看出,7031,7032,7033是主節點,其它三個是從節點。

客戶端鏈接集羣

集羣啓動成功後,咱們就能夠用任意一個客戶端鏈接集羣了,以下

 

[root@localhost bin]# /usr/local/redis/bin/redis-cli -c -h 192.168.2.128 -p 7031

192.168.2.128:7031> info

# Server

redis_version:3.2.0

redis_git_sha1:00000000

redis_git_dirty:0

redis_build_id:f8fcffd133fe3364

redis_mode:cluster

os:Linux 2.6.32-504.el6.x86_64 x86_64

arch_bits:64

 

可使用 cluster info命令查看集羣信息,cluster nodes命令查看集羣節點信息。

集羣關閉

關閉集羣須要逐個關閉

[root@localhost redis-cluster]#

for((i=1;i<=6;i++)); do /usr/local/redis/bin/redis-cli -c -h 192.168.2.128 -p 703$i shutdown; done

 

若是從新啓動集羣報如下錯誤

 

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

 

須要清除殺掉redis實例,而後刪除每一個節點下的臨時數據文件appendonly.aof,dump.rdb,nodes-703x.conf,而後再從新啓動redis實例便可啓動集羣。

 

[root@localhost redis-cluster]#for((i=1;i<=6;i++)); do cd 703$i; rm -rf appendonly.aof; rm -rf dump.rdb; rm -rf nodes-703$i.conf; cd ..; done

 

集羣測試

下面咱們先來體驗一下集羣的set,get簡單操做,後面咱們會進一步學習集羣的更多操做。

 

192.168.2.128:7031> set name "zhangsan"

-> Redirected to slot [5798] located at 192.168.2.128:7032

OK

192.168.2.128:7032> set age 20

-> Redirected to slot [741] located at 192.168.2.128:7031

OK

192.168.2.128:7031> set sex "man"

OK

192.168.2.128:7031>

 

若是在鏈接客戶端的時候不加-c選項set key時則會報MOVED 的錯誤:

 

[root@localhost bin]# /usr/local/redis/bin/redis-cli -h 192.168.2.128 -p 7031

192.168.2.128:7031> set name "zhangsan"

(error) MOVED 5798 192.168.2.128:7032

192.168.2.128:7031> set age 20

OK

192.168.2.128:7031> set sex "man"

OK

192.168.2.128:7031>

 

來看看取值又是怎麼樣

 

192.168.2.128:7031> get name

-> Redirected to slot [5798] located at 192.168.2.128:7032

"zhangsan"

192.168.2.128:7032> get age

-> Redirected to slot [741] located at 192.168.2.128:7031

"20"

192.168.2.128:7031> get sex

"man"

192.168.2.128:7031>

 

能夠看到,客戶端鏈接加-c選項的時候,存儲和提取key的時候不斷在7031和7032之間跳轉,這個稱爲客戶端重定向。之因此發生客戶端重定向,是由於Redis Cluster中的每一個Master節點都會負責一部分的槽(slot),存取的時候都會進行鍵值空間計算定位key映射在哪一個槽(slot)上,若是映射的槽(slot)正好是當前Master節點負責則直接存取,不然就跳轉到其餘Master節點負的槽(slot)中存取,這個過程對客戶端是透明的。繼續看下文的集羣分區原理。

Redis集羣分區原理

槽(slot)的基本概念

從上面集羣的簡單操做中,咱們已經知道redis存取key的時候,都要定位相應的槽(slot)。

Redis 集羣鍵分佈算法使用數據分片(sharding)而非一致性哈希(consistency hashing)來實現: 一個 Redis 集羣包含 16384 個哈希槽(hash slot), 它們的編號爲0、一、二、3……1638二、16383,這個槽是一個邏輯意義上的槽,實際上並不存在。redis中的每一個key都屬於這 16384 個哈希槽的其中一個,存取key時都要進行key->slot的映射計算。

下面咱們來看看啓動集羣時候打印的信息:

 

>>> Creating cluster

>>> Performing hash slots allocation on 6 nodes...

Using 3 masters:

192.168.2.128:7031

192.168.2.128:7032

192.168.2.128:7033

Adding replica 192.168.2.128:7034 to 192.168.2.128:7031

Adding replica 192.168.2.128:7035 to 192.168.2.128:7032

Adding replica 192.168.2.128:7036 to 192.168.2.128:7033

M: bee706db5ae182c5be9b9bdf94c2d6f3f8c8ec5c 192.168.2.128:7031

   slots:0-5460 (5461 slots) master

M: 72826f06dbf3be163f2f456ca24caed76a15bdf4 192.168.2.128:7032

   slots:5461-10922 (5462 slots) master

M: ab6e9d1dfc471225eef01e57be563157f81d26b3 192.168.2.128:7033

   slots:10923-16383 (5461 slots) master

......

[OK] All nodes agree about slots configuration.

>>> Check for open slots...

>>> Check slots coverage...

[OK] All 16384 slots covered.

 

從上面信息能夠看出,建立集羣的時候,哈希槽被分配到了三個主節點上,從節點是沒有哈希槽的。7031負責編號爲0-5460 共5461個 slots,7032負責編號爲 5461-10922共5462 個 slots,7033負責編號爲10923-16383 共5461個 slots。

鍵-槽映射算法

和memcached同樣,redis也採用必定的算法進行鍵-槽(key->slot)之間的映射。memcached採用一致性哈希(consistency hashing)算法進行鍵-節點(key-node)之間的映射,而redis集羣使用集羣公式來計算鍵 key 屬於哪一個槽:

 

HASH_SLOT(key)= CRC16(key) % 16384

 

其中 CRC16(key) 語句用於計算鍵 key 的 CRC16 校驗和 。key通過公式計算後獲得所對應的哈希槽,而哈希槽被某個主節點管理,從而肯定key在哪一個主節點上存取,這也是redis將數據均勻分佈到各個節點上的基礎。

 

 

 

 

鍵-槽-節點(key->slot->node)映射示意圖

集羣分區好處

不管是memcached的一致性哈希算法,仍是redis的集羣分區,最主要的目的都是在移除、添加一個節點時對已經存在的緩存數據的定位影響儘量的降到最小。redis將哈希槽分佈到不一樣節點的作法使得用戶能夠很容易地向集羣中添加或者刪除節點, 好比說:

l 若是用戶將新節點 D 添加到集羣中, 那麼集羣只須要將節點 A 、B 、 C 中的某些槽移動到節點 D 就能夠了。

l 與此相似, 若是用戶要從集羣中移除節點 A , 那麼集羣只須要將節點 A 中的全部哈希槽移動到節點 B 和節點 C , 而後再移除空白(不包含任何哈希槽)的節點 A 就能夠了。

由於將一個哈希槽從一個節點移動到另外一個節點不會形成節點阻塞, 因此不管是添加新節點仍是移除已存在節點, 又或者改變某個節點包含的哈希槽數量, 都不會形成集羣下線,從而保證集羣的可用性。下面咱們就來學習下集羣中節點的增長和刪除。

集羣操做

集羣操做包括查看集羣信息,查看集羣節點信息,向集羣中增長節點、刪除節點,從新分配槽等操做。

查看集羣信息

cluster info 查看集羣狀態,槽分配,集羣大小等,cluster nodes也可查看主從節點。

 

192.168.2.128:7031> 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:1

cluster_stats_messages_sent:119

cluster_stats_messages_received:119

192.168.2.128:7031>

新增節點

(1)新增節點配置文件

執行下面的腳本建立腳本配置文件

 

[root@localhost redis-cluster]# mkdir /usr/local/redis-cluster/7037 && cp /usr/local/redis-cluster/7031/redis.conf /usr/local/redis-cluster/7037/redis.conf && sed -i "s/7031/7037/g" /usr/local/redis-cluster/7037/redis.conf

 

(2)啓動新增節點

 

[root@localhost bin]# /usr/local/redis/bin/redis-server /usr/local/redis-cluster/7037/redis.conf

 

(3)添加節點到集羣

如今已經添加了新增一個節點所需的配置文件,可是這個這點尚未添加到集羣中,如今讓它成爲集羣中的一個主節點

 

[root@localhost redis-cluster]# cd /usr/local/redis/bin/

[root@localhost bin]# ./redis-trib.rb add-node 192.168.2.128:7037 192.168.2.128:7036

>>> Adding node 192.168.2.128:7037 to cluster 192.168.2.128:7036

>>> Performing Cluster Check (using node 192.168.2.128:7036)

S: 2c8d72f1914f9d6052065f7e9910cc675c3c717b 192.168.2.128:7036

   slots: (0 slots) slave

   replicates 6dbb4aa323864265c9507cf336ef7d3b95ea8d1b

M: 6dbb4aa323864265c9507cf336ef7d3b95ea8d1b 192.168.2.128:7033

   slots:10923-16383 (5461 slots) master

   1 additional replica(s)

S: 791a7924709bfd7ef5c36d9b9c838925e41e3c2e 192.168.2.128:7034

   slots: (0 slots) slave

   replicates d9e3c78a7c49689c29ab67a8a17be9d95cb08452

M: d9e3c78a7c49689c29ab67a8a17be9d95cb08452 192.168.2.128:7031

   slots:0-5460 (5461 slots) master

   1 additional replica(s)

M: 69b63d8db629fa8a689dd1ed25ed941c076d4111 192.168.2.128:7032

   slots:5461-10922 (5462 slots) master

   1 additional replica(s)

S: e669a91866225279aafcac29bf07b826eb5be91c 192.168.2.128:7035

   slots: (0 slots) slave

   replicates 69b63d8db629fa8a689dd1ed25ed941c076d4111

[OK] All nodes agree about slots configuration.

>>> Check for open slots...

>>> Check slots coverage...

[OK] All 16384 slots covered.

>>> Send CLUSTER MEET to node 192.168.2.128:7037 to make it join the cluster.

[OK] New node added correctly.

[root@localhost bin]#

 

./redis-trib.rb add-node 命令中,7037 是新增的主節點,7036 是集羣中已有的從節點。再來看看集羣信息

 

192.168.2.128:7031> cluster info

cluster_state:ok

cluster_slots_assigned:16384

cluster_slots_ok:16384

cluster_slots_pfail:0

cluster_slots_fail:0

cluster_known_nodes:7

cluster_size:3

cluster_current_epoch:6

cluster_my_epoch:1

cluster_stats_messages_sent:11256

cluster_stats_messages_received:11256

 

 

 

(4)分配槽

從添加主節點輸出信息和查看集羣信息中能夠看出,咱們已經成功的向集羣中添加了一個主節點,可是這個主節尚未成爲真正的主節點,由於尚未分配槽(slot),也沒有從節點,如今要給它分配槽(slot)

 

[root@localhost bin]# ./redis-trib.rb reshard 192.168.2.128:7031

>>> Performing Cluster Check (using node 192.168.2.128:7031)

M: 1a544a9884e0b3b9a73db80633621bd90ceff64a 192.168.2.128:7031

   ......

[OK] All nodes agree about slots configuration.

>>> Check for open slots...

>>> Check slots coverage...

[OK] All 16384 slots covered.

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

What is the receiving node ID?

 

系統提示要移動多少個配槽(slot),而且配槽(slot)要移動到哪一個節點,任意輸入一個數,如1024,再輸入新增節點的ID cf48228259def4e51e7e74448e05b7a6c8f5713f.

 

What is the receiving node ID? cf48228259def4e51e7e74448e05b7a6c8f5713f

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:

 

而後提示要從哪幾個節點中移除1024個槽(slot),這裏輸入‘all’表示從全部的主節點中隨機轉移,湊夠1024個哈希槽,而後就開始重新分配槽(slot)了。重新分配完後再次查看集羣節點信息

 

 

 

可見,0-340 5461-5802 10923-11263的槽(slot)被分配給了新增長的節點。三個加起來恰好1024個槽(slot)。

(5)指定從節點

如今從節點7036的主節點是7033,如今咱們要把他變爲新增長節點(7037)的從節點,須要登陸7036的客戶端

[root@localhost bin]#  /usr/local/redis/bin/redis-cli -c -h 192.168.2.128 -p 7036

192.168.2.128:7036> cluster replicate cf48228259def4e51e7e74448e05b7a6c8f5713f

OK

 

再來查看集羣節點信息

 

 

 

可見,7036成爲了新增節點7037的從節點。

刪除節點

指定刪除節點的ID便可,以下

[root@localhost bin]#

./redis-trib.rb del-node 192.168.2.128:7037 'a56461a171334560f16652408c2a45e629d268f6'

>>> Removing node a56461a171334560f16652408c2a45e629d268f6 from cluster 192.168.2.128:7037

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

>>> SHUTDOWN the node.

[root@localhost bin]#

 

集羣操做小結

從上面過程能夠看出,添加節點、分配槽、刪除節點的過程,不用中止集羣,不阻塞集羣的其餘操做。命令小結

 

#向集羣中添加節點,7037是新增節點,7036是集羣中已有的節點

./redis-trib.rb add-node 192.168.2.128:7037 192.168.2.128:7036

#從新分配槽

./redis-trib.rb reshard 192.168.2.128:7031

#指定當前節點的主節點

cluster replicate cf48228259def4e51e7e74448e05b7a6c8f5713f

#刪除節點

./redis-trib.rb del-node 192.168.2.128:7037 'a56461a171334560f16652408c2a45e629d268f6'

 

到此,redis的集羣搭建、分區原理、集羣增長節點以及刪除節點的主要內容已經簡要介紹完畢。

參考文檔

http://redisdoc.com/topic/cluster-tutorial.html

http://blog.51yip.com/nosql/1726.html

相關文章
相關標籤/搜索