最近要搭集群,看到原文,感觉写的非常不错,受到启发,又根据我的实际情况进行简单的修改,封装了一个脚本用于Docker中快速搭集群与删除集群,在我的机器上可以做到“一键启停”,现简单记录一下,:)。
配置文件以及启动脚本
一些详细的配置以后有机会再完善一下
- redis-cluster.conf.template
#端口
port ${PORT}
#非保护模式
protected-mode no
#装载RedisJson模块
#RedisJson模块直接下载或者clone仓库本地编译即可(需要Rust和LLVM环境)
loadmodule /usr/local/lib/librejson.so
#启用集群模式
cluster-enabled yes
cluster-config-file nodes-${PORT}.conf
#超时时间
cluster-node-timeout 15000
#集群各节点IP地址,记得修改为你的ip地址
cluster-announce-ip ${IP}
# 集群超时时间
cluster-node-timeout 5000
#集群节点映射端口
cluster-announce-port ${PORT}
#集群总线端口
cluster-announce-bus-port 1${PORT}
#开启aof持久化策略
appendonly yes
#后台运行
#daemonize yes
#进程号存储
pidfile /var/run/redis_${PORT}.pid
#外部访问
bind 0.0.0.0
#集群加密
#masterauth itheima
#requirepass itheima
- redis.sh
用于启动集群的脚本
用户只需要根据需求配置下面的几个变量即可
#!/bin/bash
# IP地址
ip="192.168.0.200"
# 此目录用于存放启动脚本以及配置文件模板和所需要装载的动态库
# 为了减小不必要的目录切换以及忘记切换目录带来的问题,统一使用绝对路径
cluster_path="${HOME}/dc-cluster/redis-cluster"
# 此目录将由脚本创建,“/”后的名称可以由用户自定义,存放每个节点于容器内挂载到宿主机的目录
nodes_path="${cluster_path}/nodes"
# 节点名称前缀,因为在这里节点name是由前缀+端口号组成的,所以可以自定义一下前缀
node_presuffix="rc"
# 起始端口
first_port=7001
# 节点数量
cluster_node_num=6
# 最后一个端口号
last_port=`expr $first_port + $cluster_node_num - 1`
# 集群所在的Dokcer网络名称
network_name='redis-net'
# 模板配置文件
template_file="redis-cluster.conf.template"
# 镜像名称
image_name="redis:7.0.2"
launch_cluster(){
# 创建将要映射的目录并处理配置文件
for port in `seq $first_port $last_port`;
do
mkdir -p ${nodes_path}/${port}/conf && \
PORT=${port} IP=${ip} envsubst < ${cluster_path}/${template_file} > \
${nodes_path}/${port}/conf/redis.conf && mkdir -p ${nodes_path}/${port}/data;
done
# 查看是否存在网络,如果不存在则创建一个名为redis-net的网络
res=`docker network ls | grep $network_name`
if [ -n "$res" ];then
echo "find docker network:$res"
else
docker network create ${network_name}
echo "${network_name} has been created"
fi
#启动容器
for port in `seq $first_port $last_port`;
do
docker run -d -it \
-p ${port}:${port} -p 1${port}:1${port} \
-v ${nodes_path}/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \
-v ${nodes_path}/${port}/data:/data \
-v ${cluster_path}/redis-module:/usr/local/lib \
--privileged=true --restart always \
--name ${node_presuffix}${port} \
--net ${network_name} \
--sysctl net.core.somaxconn=1024 \
${image_name} redis-server /usr/local/etc/redis/redis.conf
done
# 显示容器的ip地址
address=""
for port in `seq $first_port $last_port`;
do
tmpstr=`docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ${node_presuffix}${port}`":${port}";
echo " ${node_presuffix}${port}'s IP: ${tmpstr}"
address="$address $tmpstr"
done
# 进入容器初始化集群
docker exec -it ${node_presuffix}${first_port} /bin/bash
redis-cli --cluster create $address --cluster-replicas 1 <<EOF
yes
exit
EOF
}
# 查看集群状态
status_cluster(){
docker exec -i ${node_presuffix}${first_port} /bin/bash <<EOF
redis-cli --version
redis-cli -p 7001 -c
cluster nodes
cluster info
module list
exit
EOF
}
# 停止集群
stop_cluster(){
cmd=`sudo docker ps -a | grep ${image_name} | awk '{print $1}'`
#要将$a分割开,可以这样:
OLD_IFS="$IFS"
# 其中IFS是(内置)内部字段分隔符(internal field separator)。
# IFS环境变量定义了bash shell用户字段分隔符的一系列字符。默认情况下,bash shell会将下面的字符当做字段分隔符:空格、制表符、换行符。
IFS="\n"
arr=($cmd)
IFS="$OLD_IFS"
sudo docker rm -f ${arr[@]}
}
# 停止集群并删除nodes_path
clear_cluster(){
stop_cluster
# curr_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# sudo rm -rf ${curr_dir}/nodes
sudo rm -rf ${nodes_path}
}
p=$1
if [ $p = launch ] ;then
launch_cluster
elif [ $p = status ] ;then
status_cluster
elif [ $p = stop ] ;then
stop_cluster
elif [ $p = clear ] ;then
clear_cluster
elif [ $p = restart ] ;then
clear_cluster
launch_cluster
fi
执行
执行时的位置在主目录下
,把脚本、模板配置文件和存放RedisJson动态库的目录redis-module
放到我的${HOME}/dc-cluster/redis-cluster
目录下
- 为脚本添加执行权限
chmod +x ./dc-cluster/redis-cluster/redis.sh
执行结果
执行时的位置在主目录下
,由截图可以看出,为了更方便查看,把执行命令中的目录信息去掉
执行结果不会受到影响
- 启动集群
./redis.sh launch
启动成功时结果如下
- 查看集群状态
其实这个命令的输出是多个命令输出的组合(详细见脚本),输出形式不太讲究,可以再完善一下,基本都有
./redis.sh status
执行结果
- 停止并清除所有配置信息
./redis.sh clear
执行结果: