1. 程式人生 > 資料庫 >redis - cluster 部署說明

redis - cluster 部署說明

1.簡介

redis-cluster是一種分散式儲存的叢集,不同主節點上儲存不同的資料。

原理請參照:

https://www.cnblogs.com/CoreXin/articles/5688019.html

https://blog.csdn.net/truelove12358/article/details/79612954

利用redis-cli來配置叢集,節點啟動和叢集配置獨立分開

redis使用X埠作為服務埠,叢集的通訊埠會有10000的偏移,也就是X+10000埠

2.節點啟動

我們採用docker來啟動redis服務

2.1建立redis配置檔案(redis-cluster.tmpl)

我在路徑/home下建立一個資料夾redis-cluster,在路徑/home/redis-cluster下建立一個檔案redis-cluster.tmpl,並把以下內容複製過去。(注:路徑可自定義,我用的是/home/redis-cluster)

port ${PORT}

protected-mode no

cluster-enabled yes

cluster-config-file nodes.conf

cluster-node-timeout 5000

cluster-announce-ip ${IP_ADDRESS}

cluster-announce-port ${PORT}

cluster-announce-bus-port 1${PORT}

appendonly yes

2.2建立自定義network

docker network create redis-net

2.3 生成配置資訊

在/home/redis-cluster下生成conf和data目標,並生成配置資訊

cd /home/redis-cluster

forportin`seq 6379 6381`; do \

mkdir -p ./${port}/conf \

&& PORT=${port} envsubst < ./redis-cluster.tmpl > ./${port}/conf/redis.conf \

&& mkdir -p ./${port}/data; \

done

我們選在在一臺機子上開三個redis節點,共生成3個資料夾,從6379到6381,每個資料夾下包含data和conf資料夾,同時conf裡面有redis.conf配置檔案

2.4建立3個redis容器

forportin`seq 6379 6381`; do \

docker run -d -ti -p ${port}:${port} -p 1${port}:1${port} \

-v ${DIR}/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \

-v ${DIR}/${port}/data:/data \

--restart always --name redis-${port} --net redis-net \

--sysctl net.core.somaxconn=1024 redis:5.0.7 redis-server /usr/local/etc/redis/redis.conf; \

done

我在10.10.1.160,39,40上各佈置了三個節點,九個節點至此全部啟動完畢。

此時九個節點都是獨立的。

3.叢集配置

首先確保我們的虛擬機器上有redis-cli。執行redis-cli -c -h 10.10.1.160 -p 6379。其中-c代表叢集模式,-h是ip,-p是埠號。

 

使用cluster nodes命令可以檢視當前叢集狀態,不過這裡是已經配置好的叢集。

以下是cluster 的命令。

叢集
cluster info :列印叢集的資訊
cluster nodes :列出叢集當前已知的所有節點(node),以及這些節點的相關資訊。
節點
cluster meet <ip><port> :將ip 和port所指定的節點新增到叢集當中,讓它成為叢集的一份子。
cluster forget <node_id> :從叢集中移除node_id指定的節點。
cluster replicate <node_id> :將當前節點設定為node_id 指定的節點的從節點。
cluster saveconfig :將節點的配置檔案儲存到硬盤裡面。
(slot)
cluster addslots <slot> [slot ...] :將一個或多個槽(slot)指派(assign)給當前節點。
cluster delslots <slot> [slot ...] :移除一個或多個槽對當前節點的指派。
cluster flushslots :移除指派給當前節點的所有槽,讓當前節點變成一個沒有指派任何槽的節點。
cluster setslot <slot> node <node_id> :將槽slot指派給node_id指定的節點,如果槽已經指派給另一個節點,那麼先讓另一個節點刪除該槽>,然後再進行指派。
cluster setslot <slot> migrating <node_id> :將本節點的槽slot遷移到node_id指定的節點中。
cluster setslot <slot> importing <node_id> :從 node_id指定的節點中匯入槽slot到本節點。
cluster setslot <slot> stable :取消對槽slot的匯入(import)或者遷移(migrate)。

cluster keyslot <key> :計算鍵key應該被放置在哪個槽上。
cluster countkeysinslot <slot> :返回槽slot 目前包含的鍵值對數量。
cluster getkeysinslot <slot><count> :返回count個slot槽中的鍵  

 

我們在叢集搭建過程中主要使用的是①cluster meet <ip><port>、②cluster addslots <slot> [slot ...] 、③cluster replicate <node_id>三個命令。

3.1加入加群

我們登入第一個節點(10.10.1.160:6379),使用①命令將其餘8個節點加入叢集。例如cluster meet 10.10.1.160 6380

3.2分配槽

分散式資料儲存為了鑑別什麼key存在什麼節點上面,會利用對映演算法HASH_SLOT=CRC16(key)mod16384分成0-16383共16384個槽。

我們要將這些槽分配到主節點上面去(三主六從,槽儘可能平均地分配給三個主節點)。

要注意的是,②命令只能新增一個槽,效率很慢,所以我們通過指令碼命令執行槽的分配。

#第一個master:10.10.1.160:6379

start=0

end=5461

forslotin`seq ${start}${end}`

do

echo"slot:${slot}"

redis-cli -c -h 10.10.1.160 -p 6379 cluster addslots ${slot}

done

 

#第二個master:10.10.1.170:6379

start=5461

end=10922

forslotin`seq ${start}${end}`

do

echo"slot:${slot}"

redis-cli -c -h 10.10.1.170 -p 6379 cluster addslots ${slot}

done

 

#第三個master:10.10.1.180:6379

start=10923

end=16383

forslotin`seq ${start}${end}`

do

echo"slot:${slot}"

redis-cli -c -h ${CLUSTER_IP_3} -p ${PORT_1} cluster addslots ${slot}

done

start和end代表哪個範圍的槽,選取哪個節點修改ip和埠號即可。

3.3.設定從節點

使用③命令,按命令說明設定節點為剛才分配了槽的主節點的從節點。

#master節點的node_id

node_id=$(redis-cli -c -h 10.10.1.160 -p 6379 cluster nodes | grep 10.10.1.160:6379 | awk '{print $1}')

4.叢集維護

節點在docker維護即可,宕機重新啟動即可,docker設定restart=always。

叢集掛機情況:

① 叢集採取的是投票制度,所以存活的主節點需要保證超過總主節點數的一半。

② 三主是最基本的形式,僅允許短時間內掛掉一個主節點,五主可以允許同時掛掉兩個主節點。

③ 值得一提的是,如果兩個主節點宕機時間有一定間隔,叢集可以及時將從節點提升為主節點,所以三主叢集只要保證不要同時宕掉兩個節點即可。

④ 若docker容器出現無限重啟的情況,根據重啟的redis埠號容器,先停止容器,然後刪除對應的/home/redis-cluster/${port}/data/node.conf檔案,接著重啟容器即可。

 

 

 

附:部署指令碼如下:

指令碼說明:

1.保證指令碼都在同級目錄下
2.每臺機器執行redis-cluster.sh 的指令碼
3.在叢集之外的隨便一臺機器執行redis-config.sh指令碼
4.若叢集都掛掉了,只要保證docker能正常啟動即可,叢集會自動啟動

redis-cluster.sh

#!/usr/bin/env bash
#獲取本機ip地址
IP_ADDRESS=$(ip a | grep inet | grep -v inet6 | grep -v 127 | sed 's/^[ \t]*//g' | awk -F " " '{print $2}' | grep -v 172 | grep -v 32 | awk -F"/" '{print $1}')
DIR="/home/redis-cluster"
echo -e "\033[1;31m 此指令碼需在每個redis節點上執行 \033[0m"
echo "建立目錄${DIR}"
mkdir ${DIR}

echo -e "\033[1;32m 1.開始生成redis-cluster.tmpl檔案 \033[0m"
cat <<EOF >${DIR}/redis-cluster.tmpl
port \${PORT}
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip ${IP_ADDRESS}
cluster-announce-port \${PORT}
cluster-announce-bus-port 1\${PORT}
appendonly yes
EOF
echo "檔案生成完畢"


#echo -e "\033[1;32m 2.建立自定義network \033[0m"
#docker network create redis-net


echo -e "\033[1;32m 3.在/home/redis-cluster下生成conf和data目標,並生成配置資訊 \033[0m"
cd ${DIR}
for port in `seq 6379 6381`; do \
mkdir -p ./${port}/conf \
&& PORT=${port} envsubst < ./redis-cluster.tmpl > ./${port}/conf/redis.conf \
&& mkdir -p ./${port}/data; \
done


echo -e "\033[1;32m 4.建立3個redis容器 \033[0m"
#echo -e "\033[1;32m 獲取redis映象 \033[0m"
#docker pull redis:latest
echo -e "\033[1;32m 根據埠號生成redis容器並啟動 \033[0m"
for port in `seq 6379 6381`; do \
docker run -d -ti -p ${port}:${port} -p 1${port}:1${port} \
-v ${DIR}/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \
-v ${DIR}/${port}/data:/data \
--restart always --name redis-${port} --net host \
--sysctl net.core.somaxconn=1024 redis redis-server /usr/local/etc/redis/redis.conf; \
done
exit

 

redis-config.sh

#!/usr/bin/env bash
CLUSTER_IP_1="10.10.1.160"
CLUSTER_IP_2="10.10.1.170"
CLUSTER_IP_3="10.10.1.180"
PORT_1="6379"
PORT_2="6380"
PORT_3="6381"
echo -e "\033[1;31m 此指令碼需要在redis叢集之外的Linux上執行 \033[0m"
echo "安裝redis(centos)"
sudo yum -y install redis
#sudo apt-get install redis-tools
echo "啟動redis"
systemctl start redis
echo "檢視redis服務執行狀態"
systemctl status redis
echo "設定開機自啟動"
systemctl enable redis


echo -e "\033[1;32m 1.登入其中一個節點並且將九個節點分別加入叢集 \033[0m"
ip_pre="10.10.1."
ip_start="160"
ip_end="180"
port_start="6379"
port_end="6381"
for ip_address in `seq ${ip_start} 10 ${ip_end}`
do
for port in `seq ${port_start} ${port_end}`
do
redis-cli -c -h ${CLUSTER_IP_1} -p ${PORT_1} cluster meet ${ip_pre}${ip_address} ${port}
done
done
echo "檢視節點情況"
redis-cli -c -h ${CLUSTER_IP_1} -p ${PORT_1} cluster nodes

echo -e "\033[1;32m 2.分配槽 \033[0m"
echo "第一個master:${CLUSTER_IP_1} -p ${PORT_1}"
start=0
end=5461
for slot in `seq ${start} ${end}`
do
echo "slot:${slot}"
redis-cli -c -h ${CLUSTER_IP_1} -p ${PORT_1} cluster addslots ${slot}
done


echo "第二個master:${CLUSTER_IP_2} -p ${PORT_1}"
start=5461
end=10922
for slot in `seq ${start} ${end}`
do
echo "slot:${slot}"
redis-cli -c -h ${CLUSTER_IP_2} -p ${PORT_1} cluster addslots ${slot}
done

echo "第三個master:${CLUSTER_IP_3} -p ${PORT_1}"
start=10923
end=16383
for slot in `seq ${start} ${end}`
do
echo "slot:${slot}"
redis-cli -c -h ${CLUSTER_IP_3} -p ${PORT_1} cluster addslots ${slot}
done

echo -e "\033[1;32m 3.設定從節點 \033[0m"
ip_pre="10.10.1."
ip_start="160"
ip_end="180"
port_start="6380"
port_end="6381"
for ip_address in `seq ${ip_start} 10 ${ip_end} `
do
for port in `seq ${port_start} ${port_end}`
do
#master節點的node_id
node_id=$(redis-cli -c -h ${ip_pre}${ip_address} -p 6379 cluster nodes | grep ${ip_pre}${ip_address}:6379 | awk '{print $1}')
redis-cli -c -h ${ip_pre}${ip_address} -p ${port} cluster replicate ${node_id}
done
done
echo "檢視叢集節點狀態"
redis-cli -c -h ${CLUSTER_IP_1} -p ${PORT_1} cluster nodes
echo "redis叢集部署完畢"
exit