序言
在目前我参与开发的代码仓库中,当需要使用 Redis 时,基本上用的都是 Redis 集群。因此,我在办公电脑上也搭建了一个 Redis 集群,以便让我为这些仓库编写的单元测试能成功运行起来。
尽管 Redis 官方提供了部署集群的指引,但这要求团队内的每位成员都要依次执行如下操作:
用 Homebrew 安装 Redis;
创建 6 个目录;
创建 6 份
redis.conf
配置文件;启动 6 个
redis-server
进程;用
redis-cli
创建集群。
为了可以让更多的人愿意执行单元测试,必须要降低部署 Redis 集群的操作难度。因此,本文旨在提供一种基于 Docker 的、一键部署 Redis 集群的办法。
启动单个 Redis 容器
Redis 集群需要至少 6 个实例,那么首先要解决的问题便是如何启动单个 Redis 容器。从前文提到的部署集群的指引中可以知道,要启动一个集群模式的 Redis 实例,所需要的配置文件redis.conf
的内容如下
port 8000 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
参考官方的 redis 镜像的文档的方式,让redis-server
读取来自于宿主机的配置文件,示例代码如下
# 选项 --rm 使该容器在退出后(例如按下 ctrl-c)可以被删除,毕竟这里只是先做个演示,不需要留下它。 sudo docker run --rm -v "`pwd`:/usr/local/etc/redis" redis redis-server "/usr/local/etc/redis/redis.conf"
效果如下图所示
启动 6 个 Redis 容器
接下来以相似的方式启动全部的 6 个 Redis 容器。首先创建 6 个目录
# 这里我用 Redis 监听的端口号作为目录名,但这并非强制要求。 mkdir 8000 8001 8002 8003 8004 8005
然后在每一个目录中都创建配置文件redis.conf
for port in 8000 8001 8002 8003 8004 8005 ; do cat << EOF > "./${port}/redis.conf" port ${port} cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes EOF done
最后启动它们
# 创建出名为 some-network 的容器间网络。 docker network create some-network for port in 8000 8001 8002 8003 8004 8005 ; do # --name 选项让这 6 个容器拥有确定的且不同的主机名,以便之后可以在 redis-cli 中指定它们。 # --network 选项让这 6 个容器处于同一个网络下,以便集群内的节点可以互相通信。 docker run --name "some-redis-${port}" --network some-network --rm -d -v "`pwd`/${port}:/usr/local/etc/redis" redis redis-server '/usr/local/etc/redis/redis.conf' done
效果如下图所示
创建集群
此时 6 个运行中的 Redis 实例还不构成一个集群,还需要执行redis-cli
的命令--cluster create
才行。
# 给 redis-cli 的选项 --cluster-yes 使其默认接受集群内节点的分配情况。这在脚本执行、无法通过标准输出敲入 yes 的时候很有用。 docker run --network some-network --rm -i -t redis redis-cli --cluster create some-redis-8000:8000 some-redis-8001:8001 some-redis-8002:8002 some-redis-8003:8003 some-redis-8004:8004 some-redis-8005:8005 --cluster-replicas 1 --cluster-yes
但命令--cluster create
并非幂等的,只能在创建集群的时候使用一次。因此,如果希望通过脚本一键搭建、启动集群,则必须在创建前先检查集群是否曾经被创建过。借助redis-cli
的命令--cluster check
可以实现
docker run --network some-network --rm -i -t redis redis-cli --cluster check some-redis-8000:8000 | grep 'All 16384 slots covered.' > /dev/null if [[ "$?" == '0' ]]; then echo "Redis 集群已经创建好了。" else echo "开始创建 Redis 集群。" docker run --network some-network --rm -i -t redis redis-cli --cluster create some-redis-8000:8000 some-redis-8001:8001 some-redis-8002:8002 some-redis-8003:8003 some-redis-8004:8004 some-redis-8005:8005 --cluster-replicas 1 --cluster-yes fi
创建成功后,只要新的容器也使用网络some-network
,就可以读写集群中的数据了
docker run --network some-network --rm -i -t redis redis-cli -c -h some-redis-8000 -p 8000
效果如下图所示
总结
我将上面的内容集成到了redis_cluster
这个 GitHub 仓库中,只需要克隆到本地并执行脚本start.sh
即可,效果如下图所示
全文完。