利用docker搭建redis集群

参考文档:http://redis.io/topics/cluster-tutorial

##!搭建后的redis集群只能通过redis-cli连接使用,暂时不能对外提供访问(主要是由于redis本身的机制导致,官方文档说要将容器指定为–network=host方式)

1. 先下载redis镜像

1
docker pull redis:3.0.7

2. 构建一个支持集群化的镜像

dockerfile如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
FROM redis:3.0.7
MAINTAINER Louz
ENV REDIS_HOME /usr/local
RUN mkdir $REDIS_HOME/conf
WORKDIR $REDIS_HOME/conf
## 创建一个redis.conf文件,打开集群相关配置
RUN echo "cluster-enabled yes" > redis.conf
RUN echo "cluster-config-file nodes_6379.conf" >> redis.conf
## 初始化容器时启动redis实例
CMD ["redis-server","/usr/local/conf/redis.conf"]

通过以下命令构建出镜像

1
docker build -f Dockerfile -t louz/redis-cluster .

3. 启动6个节点(3主3备)

1
2
3
4
5
6
docker run -d --name redis-node1 -p 6379:6379 louz/redis-cluster #映射6379端口,以便外部应用访问
docker run -d --name redis-node2 louz/redis-cluster
docker run -d --name redis-node3 louz/redis-cluster
docker run -d --name redis-node4 louz/redis-cluster
docker run -d --name redis-node5 louz/redis-cluster
docker run -d --name redis-node6 louz/redis-cluster

这样就启动了6个独立的redis实例,但现在还没有形成集群。可以启动一个redis-cli测试各个节点是否启动成功

1
$ docker run -it --link redis-node1:redis-node1 --rm redis:3.0.7 redis-cli -h redis-node1 -p 6379

4. 获取各个redis实例的ip

貌似redis建立集群必须要使用ip,所以先使用以下命令:

1
2
3
docker inspect --format='{{.NetworkSettings.IPAddress}}' redis-node1
......
docker inspect --format='{{.NetworkSettings.IPAddress}}' redis-node6

分别获取到6个redis实例的ip,下面假设拿到的是172.17.0.3-8

5. 构建一个用于创建redis集群命令的镜像

dockerfile如下,镜像名为louz/ruby22-redis307

1
2
3
4
5
6
FROM ruby:2.2.5
MAINTAINER Louz
RUN gem install redis
RUN curl -s http://download.redis.io/releases/redis-3.0.7.tar.gz | tar -xz -C /usr/local
RUN cd /usr/local && ln -s redis-3.0.7 redis

6. 创建集群

步骤5的镜像构建成功后,执行以下命令进入容器的交互式界面

1
docker run -it louz/ruby22-redis307 /bin/bash

然后在容器内部,执行以下命令:

1
2
3
$> /usr/local/redis/src/redis-trib.rb create --replicas 1 \
172.17.0.3:6379 172.17.0.4:6379 172.17.0.5:6379 \
172.17.0.6:6379 172.17.0.7:6379 172.17.0.8:6379

上面的--replicas 1表示每个master节点有1个slave

命令运行后出现类似的对话框:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$ docker run -it louz/ruby22-redis307 /bin/bash
root@0f1df01b4965:/# /usr/local/redis/src/redis-trib.rb create --replicas 1 \
> 172.17.0.3:6379 172.17.0.4:6379 172.17.0.5:6379 \
> 172.17.0.6:6379 172.17.0.7:6379 172.17.0.8:6379
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
172.17.0.3:6379
172.17.0.4:6379
172.17.0.5:6379
Adding replica 172.17.0.6:6379 to 172.17.0.3:6379
Adding replica 172.17.0.7:6379 to 172.17.0.4:6379
Adding replica 172.17.0.8:6379 to 172.17.0.5:6379
M: 716c75b9df60ff6270271a62d2349fa2e6a84a48 172.17.0.3:6379
slots:0-5460 (5461 slots) master
M: 2795b8bb1e62ceeda936499e13c90010c4c9b5c7 172.17.0.4:6379
slots:5461-10922 (5462 slots) master
M: 0160d543fefc9a633c77d7bc7de7eb868a7706b8 172.17.0.5:6379
slots:10923-16383 (5461 slots) master
S: 78e6dafb4c4e08f41a4ef740047728b23ca730b3 172.17.0.6:6379
replicates 716c75b9df60ff6270271a62d2349fa2e6a84a48
S: 78e6dafb4c4e08f41a4ef740047728b23ca730b3 172.17.0.7:6379
replicates 0160d543fefc9a633c77d7bc7de7eb868a7706b8
S: 283474770750c161e2f22f56d7c3cac0d92c9bc1 172.17.0.8:6379
replicates 2795b8bb1e62ceeda936499e13c90010c4c9b5c7
Can I set the above configuration? (type 'yes' to accept):

回答yes后,出现类似信息即表示集群创建成功

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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.17.0.3:6379)
M: 716c75b9df60ff6270271a62d2349fa2e6a84a48 172.17.0.3:6379
slots:0-5460 (5461 slots) master
M: 2795b8bb1e62ceeda936499e13c90010c4c9b5c7 172.17.0.4:6379
slots:5461-10922 (5462 slots) master
M: 0160d543fefc9a633c77d7bc7de7eb868a7706b8 172.17.0.5:6379
slots:10923-16383 (5461 slots) master
M: 78e6dafb4c4e08f41a4ef740047728b23ca730b3 172.17.0.6:6379
slots: (0 slots) master
replicates 716c75b9df60ff6270271a62d2349fa2e6a84a48
M: 78e6dafb4c4e08f41a4ef740047728b23ca730b3 172.17.0.7:6379
slots: (0 slots) master
replicates 0160d543fefc9a633c77d7bc7de7eb868a7706b8
M: 283474770750c161e2f22f56d7c3cac0d92c9bc1 172.17.0.8:6379
slots: (0 slots) master
replicates 2795b8bb1e62ceeda936499e13c90010c4c9b5c7
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

7. 验证

启动一个redis-cli连接其中一个节点

1
$ docker run -it --link redis-node1:redis-node1 --rm redis:3.0.7 redis-cli -h redis-node1 -p 6379 -c

输入cluster info显示类似信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ docker run -it --link redis-node1:redis-node1 --rm redis:3.0.7 redis-cli -h redis-node1 -p 6379 -c
redis-node1:6379> 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:162
cluster_stats_messages_received:162
redis-node1:6379>

测试一下:

1
2
3
4
5
6
7
8
9
redis-node1:6379> get key
-> Redirected to slot [12539] located at 172.17.0.5:6379
(nil)
172.17.0.5:6379> set key1 hello
-> Redirected to slot [9189] located at 172.17.0.4:6379
OK
172.17.0.4:6379> get key1
"hello"
172.17.0.4:6379>