声明:本人对shell脚本不熟,这些都是边查边写的,如果各位有更好的方案,欢迎赐教。
一、Redis5.0.3原生添加节点的命令
1、将启动的redis节点添加到集群中:
./src/redis-cli --cluster add-node 127.0.0.1:6385 127.0.0.1:6379
//add-node [新增的节点] [集群中的节点]
2、将这个节点设置为某个集群中的主节点:
命令如下:
./src/redis-cli --cluster reshard 127.0.0.1:6385
出现的日志即要填写的内容如下:
2.1 How many slots do you want to move (from 1 to 16384)?//想要分配多少个槽点到这个节点上
2.2 What is the receiving node ID? //输入要分配槽点的id,例如:eaa6680bb8edfe239518109b387baf06a5e34677
2.3 Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1://输入all将随机分配槽点
2.4 Do you want to proceed with the proposed reshard plan (yes/no)? //是否要继续执行建议的reshard计划?
3、将这个节点作为某个主节点的从节点
./src/redis-trib.rb add-node --slave 127.0.0.1:6386 127.0.0.1:6385//6386为从节点,6385为主节点
二、自动化脚本
1、创建工具脚本util.sh,内容如下:
#验证地址是否有效
function isValidAddr(){
outputLog="Invalid address of $1."
#验证地址
addr=$1
hasColon=`echo $addr | grep :`
if [[ $hasColon == "" ]]; then
echo "Invalid address of $addr."
exit 1
fi
ip=${1%:*}
port=${1#*:}
#验证ip
ret=1
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
ip=(${ip//\./ }) # 按.分割,转成数组,方便下面的判断
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
ret=$?
fi
if [ $ret -ne 0 ]; then
echo "Invalid ip of $addr."
exit 1
fi
#验证port
if [[ $port -gt 65534 || $port -lt 1025 ]]; then
echo "Invalid port of $addr."
exit 1
fi
}
#检测命令是否执行完成
function shellComplete(){
file_name=$1
cycle_times=$2
interval_time=$3
last_modify_time=""
for ((i=1;i<=$cycle_times;i++))
do
time=`ls -lt | grep $file_name | awk {'print $6$7$8'}`
if [[ $i -eq 1 ]]; then
last_modify_time=$time
else
if [[ $last_modify_time==$time ]]; then
break
fi
fi
sleep $interval_time
done
}
2、创建脚本add-node-master-add.sh,内容如下:
../src/redis-cli --cluster add-node $1 $2
3、创建脚本add-node-master.expect,内容如下:
#!/usr/bin/expect -f
#设置超时时间
set timeout -1
#执行命令
set newAddr [lindex $argv 0]
set slots [lindex $argv 1]
set newAddr_id [lindex $argv 2]
spawn ../src/redis-cli --cluster reshard $newAddr
expect "16384)?"
send "$slots\n"
expect "ID?"
send "$newAddr_id\n"
expect "#1:"
send "all\n"
expect "plan (yes/no)?"
send "yes\n"
expect "]$"
4、创建脚本add-node-master.sh,内容如下:
#!/bin/sh
. ./util.sh
newAddr=$1
oldAddr=$2
slots=$3
#检测所给节点是否可连接
function checkAddrIsConnected(){
result=`./isClusterNode.sh $1`
if [[ "$result" == "no" ]]; then
echo "the node of $1 can not connection."
exit 1
fi
}
#判断槽点是否符合条件
function checkSlots(){
if [ $slots -lt 1 ] || [ $slots -gt 16384 ]; then
echo "invalid arguments : The range of slots is 1~16384."
exit 1
fi
}
#校验地址格式是否有效
isValidAddr $oldAddr
isValidAddr $newAddr
checkSlots
checkAddrIsConnected $oldAddr
checkAddrIsConnected $newAddr
#1、在sh中运行命令将此节点添加到集群中。
./add-node-master-add.sh $newAddr $oldAddr -> redisTribAddNodes1.txt
shellComplete redisTribAddNodes1.txt 10 0.5
rm redisTribAddNodes1.txt
#2、获取集群信息中所需的数据:新节点的ID
oldAddr_host=${oldAddr%:*}
oldAddr_port=${oldAddr#*:}
cluster_nodes=`../src/redis-cli -c -h $oldAddr_host -p $oldAddr_port cluster nodes | grep $newAddr | awk {'print $1,$2'}`
cluster_id=""
i=0
newAddr_id=""
for info in $cluster_nodes
do
i=$((i+1))
case "$i" in
1)
cluster_id=$info
;;
2)
newAddr_id=$cluster_id
i=0
;;
esac
done
#3、将数据作为expect参数传输进去。
./add-node-master.expect $newAddr $slots $newAddr_id -> redisTribAddNodes2.txt
shellComplete redisTribAddNodes2.txt 20 3
rm redisTribAddNodes2.txt
echo "Success!"
5、使用方式
./add-node-master.sh newAddr oldAddr slots
参数解释:
newAddr:要作为主节点添加到集群中的新节点的地址,格式为ip:port。
oldAddr:集群中任意一个节点的地址,格式为ip:port。
slots:要移动到新的主节点上的槽点数,范围为0~16383。