这里使用的 redis 版本是 redis-3.0.0-beta8(2.9.57)来安装和配置的。
 
整个安装和配置过程都是参考的 redis 官方的 cluster 手册: http://redis.io/topics/cluster-tutorial
 
其他的一些 API 和 redis cluster 相关的开源项目有:
 
https://github.com/xetorthio/jedis
https://github.com/antirez/redis-rb-cluster
https://github.com/Grokzen/redis-py-cluster
 
在安装配置之前对 redis cluster 有了一点初步的了解:
 
+ 每一个 redis cluster 节点都至少需要两个 tcp 连接,一个是用于为 client 服务的监听端口(如: 6379),另一个则用于为 cluster 节点通信提供的通道(cluster bus,如:6379+10000 = 16379);
+ cluster 节点之间传输的协议为 binary protocol,主要用于 故障检测(failure detection),配置更新(configuration update),故障转移授权(failover authorization)等等;
+ Redis Cluster 并没有采用一致性 hash 算法来对 data 进行 sharding,而是采用了简单的 hash slot 机制来实现 -- 计算给定 key 的 hash slot 槽位 -- CRC16(key) % 16384 ;
+ Redis Cluster 最多能够支持 16384 个节点;
+ 为了把所有 slot 占满,当节点少的时候,需要每一个节点分配一定范围的 slots,如:
  - Node A contains hash slots from 0 to 5500
  - Node B contains hash slots from 5501 to 11000
  - Node C contains hash slots from 11001 to 16384
  当有新的 node 进来,那需要从 A,B,C 中移出一些 slots 分配给 D。
  当有节点要退出(如:A),那就需要将 A 上的 slots 再分配给 B 和 C。
+ Redis Cluster 支持 master-slave 模型来实现高可用性,一个节点退出,可以再次选举出该节点的某一个 slave 节点作为新的 master 节点来服务;
 

下面开始安装配置:

 

1,创建本地测试目录:
 

$ mkdir -p /root/test/redis-cluster

 
2,本次测试以在同台主机上测试集群,端口从 7000~7005 的 6 个节点
 

$ cd /root/test/redis-cluster
$ mkdir 7000 7001 7002 7003 7004 7005

 
3,在每个节点目录下分别创建 redis.conf 配置文件,这里的配置文件内容都如下(端口除外):
 

port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

 
创建好后,结构如下:
 

[redis-cluster]# tree
.
├── 7000
│   └── redis.conf
├── 7001
│   └── redis.conf
├── 7002
│   └── redis.conf
├── 7003
│   └── redis.conf
├── 7004
│   └── redis.conf
└── 7005
    └── redis.conf
  
6 directories, 6 files

   
4,启动这 6 个节点,如下示例:
 

$ cd 7000/
$ redis-server redis.conf

 
  运行后在每个节点的目录下可以看到新增了 nodes.conf 配置,如 7000 节点的配置如下:
   

123ed65d59ff22370f2f09546f410d31207789f6 :0 myself,master - 0 0 0 connected
vars currentEpoch 0 lastVoteEpoch 0

   
  其中 123ed65d59ff22370f2f09546f410d31207789f6 为每个节点给自己分配的 NodeID,该 ID 在之后的 cluster 环境中唯一的标识该节点实例,每一个节点也都是通过这个 ID 来表示其他的节点的。
 
5,查看网络监听,可以看到同时监听 700* + 10000

tcp        0      0 :::17003                    :::*                        LISTEN      10614/redis-server  
tcp        0      0 :::17004                    :::*                        LISTEN      10655/redis-server  
tcp        0      0 :::17005                    :::*                        LISTEN      10696/redis-server  
tcp        0      0 :::7000                     :::*                        LISTEN      10483/redis-server  
tcp        0      0 :::7001                     :::*                        LISTEN      10549/redis-server  
tcp        0      0 :::7002                     :::*                        LISTEN      10573/redis-server  
tcp        0      0 :::7003                     :::*                        LISTEN      10614/redis-server  
tcp        0      0 :::7004                     :::*                        LISTEN      10655/redis-server  
tcp        0      0 :::7005                     :::*                        LISTEN      10696/redis-server  
tcp        0      0 :::17000                    :::*                        LISTEN      10483/redis-server  
tcp        0      0 :::17001                    :::*                        LISTEN      10549/redis-server  
tcp        0      0 :::17002                    :::*                        LISTEN      10573/redis-server

 

6,下面开始搭建集群,这里使用源码中自带的 ruby 脚本 redis-trib.rb 来创建集群,因此首先确保系统已经安装了最新版本的 ruby 环境
 
  redis-trib.rb 除了创建集群,还可以 check,reshard 一个存在的 cluster。
   

$ ./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
>>> Creating cluster
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7001: OK
... ...
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
127.0.0.1:7000
127.0.0.1:7001
127.0.0.1:7002
Adding replica 127.0.0.1:7003 to 127.0.0.1:7000
Adding replica 127.0.0.1:7004 to 127.0.0.1:7001
Adding replica 127.0.0.1:7005 to 127.0.0.1:7002
  
// M 开头的为 master 节点
// S 开头的为 slave 节点,同时 replicates 后面的 NodeID 为 master 节点ID
M: 123ed65d59ff22370f2f09546f410d31207789f6 127.0.0.1:7000
   slots:0-5460 (5461 slots) master
M: 82578e8ec9747e46cbb4b8cc2484c71b9b2c91f4 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
M: f5bdda1518cd3826100a30f5953ed82a5861ed48 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
S: 35e0f6fdadbf81a00a1d6d1843698613e653867b 127.0.0.1:7003
   replicates 123ed65d59ff22370f2f09546f410d31207789f6
S: 61dfb1055760d5dcf6519e35435d60dc5b207940 127.0.0.1:7004
   replicates 82578e8ec9747e46cbb4b8cc2484c71b9b2c91f4
S: bfc910f924d772fe03d9fe6a19aabd73d5730d26 127.0.0.1:7005
   replicates f5bdda1518cd3826100a30f5953ed82a5861ed48
   
// 回复 yes 表示接受 redis-trib 的 master-slave 的配置
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
  
// 等待 cluster 的 node 加入
Waiting for the cluster to join...
  
// 加入后开始给各个 node 分配 slots 槽位
// 如:127.0.0.1:7000 的 master 节点分配了 0-5460 的槽位
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: 123ed65d59ff22370f2f09546f410d31207789f6 127.0.0.1:7000
   slots:0-5460 (5461 slots) master
M: 82578e8ec9747e46cbb4b8cc2484c71b9b2c91f4 127.0.0.1:7001
   slots:5461-10922 (5462 slots) master
M: f5bdda1518cd3826100a30f5953ed82a5861ed48 127.0.0.1:7002
   slots:10923-16383 (5461 slots) master
M: 35e0f6fdadbf81a00a1d6d1843698613e653867b 127.0.0.1:7003
   slots: (0 slots) master
   replicates 123ed65d59ff22370f2f09546f410d31207789f6
M: 61dfb1055760d5dcf6519e35435d60dc5b207940 127.0.0.1:7004
   slots: (0 slots) master
   replicates 82578e8ec9747e46cbb4b8cc2484c71b9b2c91f4
M: bfc910f924d772fe03d9fe6a19aabd73d5730d26 127.0.0.1:7005
   slots: (0 slots) master
   replicates f5bdda1518cd3826100a30f5953ed82a5861ed48
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@sasd redis-cluster]#

 

下面为使用 cluster nodes 和 slots 命令查看节点以及 slot 的信息:
 

$ redis-cli -c -p 7000
// 查看节点分布信息
127.0.0.1:7000> cluster nodes
35e0f6fdadbf81a00a1d6d1843698613e653867b 127.0.0.1:7003 slave 123ed65d59ff22370f2f09546f410d31207789f6 0 1410835785216 4 connected
61dfb1055760d5dcf6519e35435d60dc5b207940 127.0.0.1:7004 slave 82578e8ec9747e46cbb4b8cc2484c71b9b2c91f4 0 1410835784715 5 connected
82578e8ec9747e46cbb4b8cc2484c71b9b2c91f4 127.0.0.1:7001 master - 0 1410835786217 2 connected 5461-10922
123ed65d59ff22370f2f09546f410d31207789f6 127.0.0.1:7000 myself,master - 0 0 1 connected 0-5460
bfc910f924d772fe03d9fe6a19aabd73d5730d26 127.0.0.1:7005 slave f5bdda1518cd3826100a30f5953ed82a5861ed48 0 1410835786717 6 connected
f5bdda1518cd3826100a30f5953ed82a5861ed48 127.0.0.1:7002 master - 0 1410835785715 3 connected 10923-16383
127.0.0.1:7000> 
// 查看 slots 分布信息
127.0.0.1:7000> cluster slots
1) 1) (integer) 5461      // slots 的其实槽位索引
   2) (integer) 10922     // slots 的结束槽位索引
                          // 即 [5461, 10922]
   3) 1) "127.0.0.1"
      2) (integer) 7001   // master
   4) 1) "127.0.0.1"
      2) (integer) 7004   // 对应的 slave 节点
2) 1) (integer) 0
   2) (integer) 5460
   3) 1) "127.0.0.1"
      2) (integer) 7000
   4) 1) "127.0.0.1"
      2) (integer) 7003
3) 1) (integer) 10923
   2) (integer) 16383
   3) 1) "127.0.0.1"
      2) (integer) 7002
   4) 1) "127.0.0.1"
      2) (integer) 7005
127.0.0.1:7000>