Philippe Caseiro
2cb3b1eab0
Redis cluster needs 6 hosts for work ... it's a lot. To trick him each node can be Master and slave for another node. ;)
237 lines
5.1 KiB
Bash
Executable File
237 lines
5.1 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
#
|
|
# Cluster init !
|
|
#
|
|
|
|
#function ProgressBar {
|
|
# # Process data
|
|
# let _progress=(${1}*100/${2}*100)/100
|
|
# let _done=(${_progress}*4)/10
|
|
# let _left=40-$_done
|
|
# # Build progressbar string lengths
|
|
# _fill=$(printf "%${_done}s")
|
|
# _empty=$(printf "%${_left}s")
|
|
#
|
|
# # 1.2 Build progressbar strings and print the ProgressBar line
|
|
# # 1.2.1 Output example:
|
|
# # 1.2.1.1 Progress : [########################################] 100%
|
|
# printf "\rProgress : [${_fill// /#}${_empty// /-}] ${_progress}%%"
|
|
#}
|
|
|
|
function redisRun()
|
|
{
|
|
cmd="redis-cli"
|
|
host=$1
|
|
shift
|
|
port=$1
|
|
shift
|
|
#pass=$1
|
|
#shift
|
|
|
|
#opt="-h ${host} -p ${port} -a ${pass}"
|
|
opt="-h ${host} -p ${port}"
|
|
act=${@}
|
|
${cmd} ${opt} ${act}
|
|
return ${?}
|
|
}
|
|
#
|
|
# Get Node ID with IP Adress and Port Number
|
|
# Params :
|
|
# - $1 => Leader IP
|
|
# - $2 => Leader Port
|
|
# - $3 => Cluster Password
|
|
# - $4 => Node IP Adress
|
|
# - $5 => Node Port
|
|
#
|
|
function getNodeID()
|
|
{
|
|
if [[ ${1} == ${3} ]]
|
|
then
|
|
searchCmd="awk '/myself,master/ { print \$1 }'"
|
|
else
|
|
searchCmd="awk '/${3}:${4}@/ { print \$1 }'"
|
|
fi
|
|
result=$(redisRun $1 $2 cluster nodes | eval ${searchCmd})
|
|
rcode=${?}
|
|
|
|
if [[ -z ${result} ]]
|
|
then
|
|
searchCmd="awk '/${3}:${4}@/ { print \$1 }'"
|
|
result=$(redisRun $1 $2 cluster nodes | eval ${searchCmd})
|
|
rcode=${?}
|
|
fi
|
|
echo ${result}
|
|
return ${rcode}
|
|
}
|
|
|
|
function redisClusterForgetAll()
|
|
{
|
|
local res=0
|
|
for node in $(redisRun ${1} ${2} ${3} cluster nodes | awk '!/myself,master/ {print $1}')
|
|
do
|
|
redisRun ${1} ${2} ${3} "cluster forget ${node}"
|
|
res=$((res+${?}))
|
|
done
|
|
return ${res}
|
|
}
|
|
|
|
#
|
|
# Assing redis slots to master Node
|
|
# Params :
|
|
# - $1 => Node IP
|
|
# - $2 => Node Port
|
|
# - $3 => Cluster Password
|
|
# - $4 => First slot
|
|
# - $5 => Last slot
|
|
#
|
|
function redisSlotAssign()
|
|
{
|
|
res=0
|
|
for slot in $(seq ${3} ${4})
|
|
do
|
|
OUT=$(redisRun ${1} ${2} "cluster ADDSLOTS $slot")
|
|
res=$((res+${?}))
|
|
if [[ ${OUT} =~ ERR ]]
|
|
then
|
|
OUT=$(redisRun ${1} ${2} "cluster ADDSLOTS $slot")
|
|
fi
|
|
done
|
|
return ${res}
|
|
}
|
|
|
|
function redisAddReplica()
|
|
{
|
|
redisRun ${1} ${2} "cluster replicate ${3}"
|
|
return ${?}
|
|
}
|
|
|
|
function redisClusterIsOK()
|
|
{
|
|
out=$(redis-cli -h ${1} -p ${2} cluster info | grep "cluster_state:ok")
|
|
return $?
|
|
}
|
|
|
|
CONF="/etc/redis/cluster.conf"
|
|
|
|
[[ ! -e ${CONF} ]] && exit 0
|
|
|
|
declare -A IPADDRS
|
|
declare -A PORTS
|
|
declare -A ROLES
|
|
declare -A MASTERS
|
|
declare -A NIDS
|
|
declare LeaderIP
|
|
declare LeaderPort
|
|
index=0
|
|
|
|
while read line
|
|
do
|
|
[[ ${line} =~ ^# ]] && continue
|
|
line=${line//::/:none:}
|
|
li=(${line//:/ })
|
|
|
|
name=${li[0]}
|
|
ip=${li[1]}
|
|
port=${li[2]}
|
|
role=${li[3]}
|
|
master=${li[4]}
|
|
ntype=${li[5]}
|
|
|
|
if [[ ${ntype} == "Leader" ]]
|
|
then
|
|
LeaderIP=${ip}
|
|
LeaderPort=${port}
|
|
fi
|
|
NAMES+=(${name})
|
|
IPADDRS+=([${name}]=${ip})
|
|
PORTS+=([${name}]=${port})
|
|
ROLES+=([${name}]=${role})
|
|
MASTERS+=([${name}]=${master})
|
|
done < ${CONF}
|
|
|
|
# If the cluster is "ok" don't do anything
|
|
st=$(redisClusterIsOK ${LeaderIP} ${LeaderPort})
|
|
#[[ ${?} -eq 0 ]] && exit 0
|
|
|
|
if [[ ${1} == "forget" ]]
|
|
then
|
|
redisClusterForgetAll ${LeaderIP} ${LeaderPort}
|
|
exit ${?}
|
|
fi
|
|
|
|
echo " * Organise Cluster Meeting."
|
|
for node in ${NAMES[@]}
|
|
do
|
|
act="cluster meet ${IPADDRS[${node}]} ${PORTS[${node}]}"
|
|
echo " - ${node} - ${IPADDRS[${node}]}:${PORTS[${node}]} meeting with :"
|
|
for oth in ${NAMES[@]}
|
|
do
|
|
[[ ${oth} == ${node} ]] && continue
|
|
echo -en " -> ${oth} - ${IPADDRS[${oth}]} ${PORTS[${oth}]} "
|
|
redisRun ${IPADDRS[${oth}]} ${PORTS[${oth}]} "${act}"
|
|
done
|
|
done
|
|
|
|
echo " * Waiting for all members ."
|
|
for node in ${NAMES[@]}
|
|
do
|
|
try=3
|
|
scmd="awk '/${IPADDRS[$node]}:${PORTS[${node}]}/ {print \$8}'"
|
|
while [[ $(redisRun ${LeaderIP} ${LeaderPort} "cluster nodes" | eval ${scmd}) != "connected" ]]
|
|
do
|
|
sleep 1
|
|
try=$((try-1))
|
|
[[ ${try} -eq 0 ]]
|
|
break
|
|
done
|
|
done
|
|
|
|
nbMaster=$(grep -c ":master" ${CONF})
|
|
totalslots=16384
|
|
perNodeSlots=$((totalslots/nbMaster))
|
|
startSlot=0
|
|
|
|
echo " * Assign Slots to the nodes."
|
|
for node in ${NAMES[@]}
|
|
do
|
|
if [[ ${ROLES[$node]} == "master" ]]
|
|
then
|
|
if [[ ${startSlot} -eq 0 ]]
|
|
then
|
|
lastSlot=$(((perNodeSlots+startSlot)-1))
|
|
else
|
|
lastSlot=$((perNodeSlots+startSlot))
|
|
fi
|
|
[[ ${lastSlot} -ge ${totalslots} ]] && lastSlot=$((totalslots-1))
|
|
echo " - Slots ${startSlot} to ${lastSlot} => ${node} - ${IPADDRS[${node}]} ${PORTS[${node}]}"
|
|
redisSlotAssign ${IPADDRS[${node}]} ${PORTS[${node}]} ${startSlot} ${lastSlot}
|
|
startSlot=$((lastSlot+1))
|
|
fi
|
|
done
|
|
|
|
echo " * Configuring replication."
|
|
NIDS+=()
|
|
for node in ${NAMES[@]}
|
|
do
|
|
NIDS+=([${node}]=$(getNodeID ${LeaderIP} ${LeaderPort} ${IPADDRS[${node}]} ${PORTS[${node}]}))
|
|
done
|
|
|
|
for node in ${NAMES[@]}
|
|
do
|
|
[[ ${ROLES[$node]} == "master" ]] && continue
|
|
echo -ne " - Replicate ${MASTERS[${node}]} to ${node}\t\t"
|
|
redisAddReplica ${IPADDRS[${node}]} ${PORTS[${node}]} ${NIDS[${MASTERS[${node}]}]}
|
|
done
|
|
|
|
sleep 5
|
|
|
|
echo
|
|
echo "Cluster status :"
|
|
echo
|
|
redisRun ${LeaderIP} ${LeaderPort} cluster info
|
|
echo
|
|
|
|
|
|
exit 0
|