我时常需要在云服务器上搭建测试环境,每次入手新的服务器配置集群环境时,跟着笔记敲一遍命令行挺麻烦的。学了 shell 脚本后,我尝试使用脚本在单机服务器上部署 Redis 集群。
参照 Redis 主从集群及自启动配置 实现自动安装,首先判断是否已安装,若存在 Redis 服务程序则跳过,否则安装。
# Check redis commandif [ ! -f "/usr/local/bin/redis-server" ]; then echo "Redis not ready, please install redis firstly!" echo "" echo "===== Install redis as follows =====" wget http://download.redis.io/releases/redis-5.0.7.tar.gz -P /usr/local/src cd /usr/local/src/ tar -zxvf redis-5.0.7.tar.gz cd redis-5.0.7 install GCC if not exists yum install -y gcc-c++ make MALLOC=libc install
echo "" echo "Redis Server Installation Finished!"fi
通过 if[!-f"/usr/local/bin/redis-server"]
判断 server 程序是否存在,若存在则认为 Redis 已安装。
采用源码编译的方式安装 Redis,已指定 5.0.7 版本,防止出现兼容性问题。
# ConstantsBASE_DIR=/usr/local/redis-clusterPORTS=`seq 7000 7005`START_UP=$BASE_DIR/startup.sh
seq70007005
生成 7000-7005 的整数数组;# 创建工作目录,在工作目录下进行后续操作mkdir -p $BASE_DIRcd $BASE_DIR
# 准备集群实例启动脚本,在每次实例配置循环时将启动命令追加到脚本中echo "#!/bin/bash" > $START_UPservers=for port in $PORTS; do # 设置每个实例的工作目录, data为数据存放目录 mkdir -p $BASE_DIR/$port/data # 生成单个实例的配置文件 generate_instance_conf $port # 追加实例启动命令到启动脚本 echo "/usr/local/bin/redis-server $BASE_DIR/$port/redis.conf" >> $START_UP # 记录所有的实例位置,用于之后的集群启动 servers="$servers 127.0.0.1:$port "done
每个实例的配置文件相似,只是端口号和工作目录不同。还有一点需要注意,要想可以从其它外部主机访问此主机上的 Redis 集群,需要将实例的集群地址设置为主机的外网地址,因此需要用户手动输入主机外网地址。
使用 shell 实现外网地址获取的交互模式:
# User custom settingecho -n "Enter your host's public address(default 127.0.0.1):"read cluster_address
将实例配置依次写入 redis.conf 中:
# generate configuration filesfunction generate_instance_conf() { echo "configuring server $1"
# clean conf file echo "" > $1/redis.conf # write conf echo "port $1" >> $1/redis.conf echo "bind 0.0.0.0" >> $1/redis.conf echo "dir $BASE_DIR/$port/data" >> $1/redis.conf echo "cluster-enabled yes" >> $1/redis.conf echo "cluster-config-file nodes-$1.conf" >> $1/redis.conf echo "cluster-node-timeout 5000" >> $1/redis.conf if [ -n "$cluster_address" ]; then echo "cluster-announce-ip $cluster_address" >> $1/redis.conf else echo "cluster-announce-ip 127.0.0.1" >> $1/redis.conf fi echo "appendonly yes" >> $1/redis.conf echo "daemonize yes" >> $1/redis.conf}chmod +x $START_UP
如上步骤完成后,集群工作目录如下:
drwxr-xr-x 3 root root 4096 Apr 19 11:07 7000drwxr-xr-x 3 root root 4096 Apr 19 11:07 7001drwxr-xr-x 3 root root 4096 Apr 19 11:07 7002drwxr-xr-x 3 root root 4096 Apr 19 11:07 7003drwxr-xr-x 3 root root 4096 Apr 19 11:07 7004drwxr-xr-x 3 root root 4096 Apr 19 11:07 7005-rwxr-xr-x 1 root root 426 Apr 19 11:07 startup.sh
# startup instancesecho "starting servers..."$START_UPsleep 5secho "servers ready!"
执行启动脚本,启动 6 个 Redis 实例,并保持休眠 5 秒,等待集群启动完成,执行结果如下:
starting servers...27764:C 19 Apr 2020 11:07:58.874 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo27764:C 19 Apr 2020 11:07:58.874 # Redis version=5.0.7, ..27764:C 19 Apr 2020 11:07:58.874 # Configuration loaded...27777:C 19 Apr 2020 11:07:58.885 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo27777:C 19 Apr 2020 11:07:58.885 # Redis version=5.0.7, ..27777:C 19 Apr 2020 11:07:58.885 # Configuration loadedservers ready!
# create clusterecho "configuring cluster..."/usr/local/bin/redis-cli --cluster create $servers --cluster-replicas 1echo "configured!"
使用 redis-cli 建立集群,指定所要包含实例的 host 和 port,$servers 中就是这些信息。
configuring cluster...>>> Performing hash slots allocation on 6 nodes...Master[0] -> Slots 0 - 5460Master[1] -> Slots 5461 - 10922Master[2] -> Slots 10923 - 16383...Can I set the above configuration? (type 'yes' to accept): yes...[OK] All nodes agree about slots configuration.>>> Check for open slots...>>> Check slots coverage...[OK] All 16384 slots covered.configured!
集群建立时需要用户手动确认槽数划分,输入 yes
即可。
至此集群部署完成,下面配置集群开机自启动。
使用 systemd 配置 Redis 集群启动服务,首先配置 service 文件:
# generate redis-cluster service filecat << EOT > $BASE_DIR/redis-cluster.service[Unit]Description=Redis 5.0 Cluster ServiceAfter=network.target
[Service]Type=forkingExecStart=/usr/local/redis-cluster/startup.sh
[Install]WantedBy=default.targetEOT
cat<<EOT>$BASE_DIR/redis-cluster.service
表示向 redis-cluster.service
文件中覆盖一段内容,内容为下一行至 EOT
之间的内容。
# create serviceecho "Creating redis cluster service..."# 在 systemd 文件夹下创建 service 的软连接并启动 redis 集群服务ln -s $BASE_DIR/$SERVICE /etc/systemd/system/$SERVICEsudo systemctl daemon-reload && sudo systemctl enable $SERVICE && sudo systemctl start $SERVICE
使用 --remove
参数执行集群删除操作:
# Remove redis clusterfunction remove_cluster() { # 终止各 Reids 实例进程 ps -ef | grep redis-server | grep cluster | awk '{print $2}' | xargs kill -9 # 移除 systemd 服务 systemctl disable redis-cluster.service # 移除工作目录(配置文件和数据) if [ -d $BASE_DIR ]; then rm -rf $BASE_DIR fi}
if [ "$1" = "--remove" ]; then remove_cluster exit 0fi
通过过滤器 grep
和流式编辑器 awk
查询到 Redis 实例的 pid,使用 kill
命令结束进程。
其中 awk'{print $2}'
为 awk-F' ''{print $2}'
的缩写, -F
表示分隔符参数,默认为空格, `awk -F ' '
将如下内容分割为数组:
root 27765 1 0 11:07 ? 00:00:03 /usr/local/bin/redis-server 0.0.0.0:7000 [cluster]
{print$2}
表述输出第 2 个元素,$0 表述输出整行。
#!/bin/bash
BASE_DIR=/usr/local/redis-cluster
PORTS=`seq 7000 7005`
START_UP=$BASE_DIR/startup.sh
SERVICE=redis-cluster.service
# Remove redis clusterfunction remove_cluster() { # kill redis servers ps -ef | grep redis-server | grep cluster | awk '{print $2}' | xargs kill -9 # disable systemd systemctl disable redis-cluster.service # rm cluster data if [ -d $BASE_DIR ]; then rm -rf $BASE_DIR fi}
if [ "$1" = "--remove" ]; then remove_cluster exit 0fi
# Check redis commandif [ ! -f "/usr/local/bin/redis-server" ]; then echo "Redis not ready, please install redis firstly!" echo "" echo "===== Install redis as follows =====" wget http://download.redis.io/releases/redis-5.0.7.tar.gz -P /usr/local/src cd /usr/local/src/ tar -zxvf redis-5.0.7.tar.gz cd redis-5.0.7 install GCC if not exists yum install -y gcc-c++ make MALLOC=libc install
echo ""fi
# User custom settingecho -n "Enter your host's public address(default 127.0.0.1):"read cluster_address
# enter work directorymkdir -p $BASE_DIRcd $BASE_DIR
# generate configuration filesfunction generate_instance_conf() { echo "configuring server $1"
# clean conf file echo "" > $1/redis.conf # write conf echo "port $1" >> $1/redis.conf echo "bind 0.0.0.0" >> $1/redis.conf echo "dir $BASE_DIR/$1/data" >> $1/redis.conf echo "cluster-enabled yes" >> $1/redis.conf echo "cluster-config-file nodes-$1.conf" >> $1/redis.conf echo "cluster-node-timeout 5000" >> $1/redis.conf if [ -n "$cluster_address" ]; then echo "cluster-announce-ip $cluster_address" >> $1/redis.conf else echo "cluster-announce-ip 127.0.0.1" >> $1/redis.conf fi echo "appendonly yes" >> $1/redis.conf echo "daemonize yes" >> $1/redis.conf}
# mkdir dirs and setup startup.shecho "#!/bin/bash" > $START_UPservers=for port in $PORTS; do mkdir -p $BASE_DIR/$port/data # generate conf files generate_instance_conf $port # echo "/usr/local/bin/redis-server $BASE_DIR/$port/redis.conf" >> $START_UP # servers servers="$servers 127.0.0.1:$port "done
# startup instanceschmod +x $START_UPecho "starting servers..."$START_UPsleep 5secho "servers ready!"
# create clusterecho "configuring cluster..."/usr/local/bin/redis-cli --cluster create $servers --cluster-replicas 1echo "configured!"
# generate redis-cluster service filecat << EOT > $BASE_DIR/redis-cluster.service[Unit]Description=Redis 5.0 Cluster ServiceAfter=network.target
[Service]Type=forkingExecStart=/usr/local/redis-cluster/startup.sh
[Install]WantedBy=default.targetEOT
# create serviceecho "Creating redis cluster service..."ln -s $BASE_DIR/$SERVICE /etc/systemd/system/$SERVICEsudo systemctl daemon-reload && sudo systemctl enable $SERVICE && sudo systemctl start $SERVICE
# Cluster OKecho ""echo "Completed!"echo ""echo "Test cluster with: /usr/local/bin/redis-cli -h 127.0.0.1 -p 7000"echo ""echo "127.0.0.1:7000>cluster nodes"
脚本下载:http://pic.blackist.top/202004182234_789.sh
https://blackist.org/2020/04/03/redis-cluster-masterandslave/
https://stackoverflow.com/questions/13910087/shell-script-to-capture-process-id-and-kill-it-if-exist