用容器轻松搭建redis主从和集群环境

Redis是目前使用得非常广泛的开源分布式缓存。它支持诸多数据结构和数据持久化,并且通过Redis SentinelRedis cluster来支持高可用。本文旨在通过docker轻松搭建redis的主从/集群环境。

主从

用容器启动redis实例非常容易:

1
docker run --net=host --name=master -d redis:3.2.0

这就搞定了。进去看一看:

1
2
3
4
5
docker exec -it master redis-cli
set ggg 123
keys *
get ggg
exit

可以通过配置文件、启动参数或者命令来新建一个从实例。接下来我们用启动参数的方式:

1
docker run --net=host --name=slave -d redis:3.2.0 redis-server --port 6380 --slaveof 127.0.0.1 6379

进去看一看,就能看到刚才创建的ggg已经被同步过来了:

1
2
3
4
docker exec -it slave redis-cli
keys *
get ggg
exit

最后把刚刚创建的实例都删除掉:

1
docker rm -f master slave

集群

Redis的集群至少是3个实例。接下来为这3个实例创建3个端口不同的配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
cat << EOF > redis1.conf
port 6381
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
EOF

cp redis1.conf redis2.conf
sed -i 's/6381/6382/' redis2.conf

cp redis1.conf redis3.conf
sed -i 's/6381/6383/' redis3.conf

通过刚刚创建的配置文件来启动3个redis实例:

1
2
3
4
5
docker run --net=host --name=redis1 -v `pwd`/redis1.conf:/usr/local/etc/redis/redis.conf -d redis:3.2.0 redis-server /usr/local/etc/redis/redis.conf

docker run --net=host --name=redis2 -v `pwd`/redis2.conf:/usr/local/etc/redis/redis.conf -d redis:3.2.0 redis-server /usr/local/etc/redis/redis.conf

docker run --net=host --name=redis3 -v `pwd`/redis3.conf:/usr/local/etc/redis/redis.conf -d redis:3.2.0 redis-server /usr/local/etc/redis/redis.conf

创建集群最简单的方式是用源代码库里的redis-trib.rb脚本。我们需要先下载源代码并安装redis的gem使之能够运行这个脚本:

1
2
3
4
5
git clone https://github.com/antirez/redis

sudo gem install redis

ruby redis/src/redis-trib.rb create 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383

运行redis-trib.rb会提示:**Can I set the above configuration? (type ‘yes’ to accept)**,输入yes回车即可。Redis集群就这样搭建好了。我们进去看一看:

1
2
3
4
5
docker exec -it redis1 redis-cli -p 6381
cluster nodes
set ggg 123
set gggg 234
exit

第一个ggg可以顺利设置成功,但是第二个gggg就不行了,我们会看到错误:**(error) MOVED 6392 127.0.0.1:6382**。这是由于redis分片(sharding)的缘故。如果频繁地在控制台里切换实例也怪麻烦的,幸好redis-cli提供了一个-c的参数,允许以集群的方式连接:

1
2
3
4
docker exec -it redis1 redis-cli -c -p 6381
set gggg 234
keys *
exit

再次设置gggg,就会看到:Redirected to slot [6392] located at 127.0.0.1:6382,它表明redis已经把我们连接到6382的实例上去了。最后把前面创建的实例都删除掉:

1
docker rm -f redis1 redis2 redis3

主从集群

主从集群就是给三个主实例各加一个从实例。现在已经有了三个主实例的配置文件了,再来三个从集群的,一共是6个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cp redis1.conf redis4.conf
cp redis1.conf redis5.conf
cp redis1.conf redis6.conf

sed -i 's/6381/6384/' redis4.conf
sed -i 's/6381/6385/' redis5.conf
sed -i 's/6381/6386/' redis6.conf

docker run --net=host --name=redis1 -v `pwd`/redis1.conf:/usr/local/etc/redis/redis.conf -d redis:3.2.0 redis-server /usr/local/etc/redis/redis.conf

docker run --net=host --name=redis2 -v `pwd`/redis2.conf:/usr/local/etc/redis/redis.conf -d redis:3.2.0 redis-server /usr/local/etc/redis/redis.conf

docker run --net=host --name=redis3 -v `pwd`/redis3.conf:/usr/local/etc/redis/redis.conf -d redis:3.2.0 redis-server /usr/local/etc/redis/redis.conf

docker run --net=host --name=redis4 -v `pwd`/redis4.conf:/usr/local/etc/redis/redis.conf -d redis:3.2.0 redis-server /usr/local/etc/redis/redis.conf

docker run --net=host --name=redis5 -v `pwd`/redis5.conf:/usr/local/etc/redis/redis.conf -d redis:3.2.0 redis-server /usr/local/etc/redis/redis.conf

docker run --net=host --name=redis6 -v `pwd`/redis6.conf:/usr/local/etc/redis/redis.conf -d redis:3.2.0 redis-server /usr/local/etc/redis/redis.conf

一条命令即可启动主从集群:

1
ruby redis/src/redis-trib.rb create --replicas 1 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 127.0.0.1:6385 127.0.0.1:6386

然后就可以在里面随意测试啦。最后把创建的实例都删除掉:

1
docker rm -f redis1 redis2 redis3 redis4 redis5 redis6