集群
1.Redis 集群的優(yōu)勢
自動分割數(shù)據(jù)到不同的節(jié)點上抛丽。
整個集群的部分節(jié)點失敗或者不可達的情況下能夠繼續(xù)處理命令失暂。
特點
主從復制
實現(xiàn)了高可用
數(shù)據(jù)分片存儲
集群節(jié)點的 meet
過程
指派槽
客戶端和槽
3. Redis 集群的安裝
原生命令安裝
步驟
配置開啟集群節(jié)點
配置
meet
指派槽
配置主從
實例操作
準備兩臺虛擬機:
一臺啟動三個 Redis 實例作為 主節(jié)點
另一臺啟動三個 Redis 實例作為 從節(jié)點
架構圖
一、在一臺服務器上手動部署 redis 集群
在一臺服務器上啟動六個 Redis 實例淋袖,三臺作為主節(jié)點凭迹,三臺作為從節(jié)點
實驗步驟
- 先編輯一個集群的配置文件
編譯配置文件 /etc/redis/7001.conf
, 添加如下內(nèi)容:
bind 0.0.0.0
port 7001
daemonize yes
# 允許任何地址不使用密碼訪問我
protected-mode yes
dir "/redis/data/"
logfile "cluster-7001.log"
dbfilename "cluster-dump-7001.log"
cluster-enabled yes
cluster-config-file cluster-redis-7001.conf
# 不需要集群的全部節(jié)點完好才提供服務
cluster-require-full-coverage no
-
再創(chuàng)建其他集群的配置文件
sed 's/7001/7002/g' 7001.conf > 7002.conf
sed 's/7001/7003/g' 7001.conf > 7003.conf
sed 's/7001/7004/g' 7001.conf > 7011.conf
sed 's/7001/7005/g' 7001.conf > 7012.conf
sed 's/7001/7006/g' 7001.conf > 7013.conf
3.啟動 redis 進程
mkdir -p /redis/data
redis-server /etc/redis/7001.conf
redis-server /etc/redis/7002.conf
redis-server /etc/redis/7003.conf
redis-server /etc/redis/7011.conf
redis-server /etc/redis/7012.conf
redis-server /etc/redis/7013.conf
4.檢查進程
ps aux| grep redis-server
假設你現(xiàn)在去連接到任意一個節(jié)點上執(zhí)行操作會返回集群目前是沒有啟動的信息。
原因是目前集群各節(jié)點之間沒有進行 meet
操作鸡捐,都是各自孤立的狀態(tài)。
可以使用如下命令查看集群的相關信息
還可以查看某一個集群節(jié)點信息麻裁,第一列是集群節(jié)點 ID
- 集群節(jié)點之間的
meet
我們下面使用主節(jié)點127.0.0.1:7001
去依次的meet
其他 5 個節(jié)點箍镜。
redis-cli -p 7001 cluster meet 127.0.0.1 7002
redis-cli -p 7001 cluster meet 127.0.0.1 7003
redis-cli -p 7001 cluster meet 127.0.0.1 7004
redis-cli -p 7001 cluster meet 127.0.0.1 7005
redis-cli -p 7001 cluster meet 127.0.0.1 7006
查看集群信息和節(jié)點 信息
- 給集群節(jié)點分配
數(shù)據(jù)槽
集群的槽號是 從0
開始,到16383
結束煎源,共16384
個色迂。
槽的分配是拿 16384
除以集群中主節(jié)點的個數(shù),得到每個主節(jié)點應該被分配給槽的數(shù)量薪夕。
所以現(xiàn)在的計劃是:
命令
redis-cli -h 被添加的主機 IP -p 端口 cluster addslots 槽號
假如給
7001
分配 0 號槽脚草。命令應該是:redis-cli -h 172.16.153.178 -p 7001 cluster addslots 0
每次只能分配一個 槽號赫悄,所以我們可以寫個腳本原献,當然這種方式是不會在生產(chǎn)環(huán)境中使用的馏慨,這里只是為了理解集群的架構關系。
腳本
#!/bin/sh
target_host_ip=$1
target_host_port=$2
star=$3
end=$4
for slot in $(seq ${star} ${end})
do
echo "正在給 ${target_host_ip} ${target_host_port} 添加${slot}"
redis-cli -h ${target_host_ip} -p ${target_host_port} cluster addslots ${slot}
done
使用腳本
sh mutil-addslots.sh 172.16.153.178 7002 5462 10922
sh mutil-addslots.sh 172.16.153.178 7003 10923 16383
多線程版
target_host_ip=$1
target_host_port=$2
star=$3
end=$4
num=$5
mkfifo t # 創(chuàng)建命名管道文件
exec 7<>t # 給命名管道起個文件描述符
rm -rf t # 刪除這個命名管道文件姑隅,但是管道依然存在写隶,可以使用文件描述符 7 進行使用。
for i in $(seq 1 ${num}) # 向這個管道中輸入相應數(shù)據(jù)的空行
do
echo >&7 # 每一行就是一次并發(fā)
done
for slot in $(seq ${star} ${end})
do
read -u7 # 這個不能變
{
echo " 主機 ${target_host_ip} 端口 ${target_host_port} 數(shù)據(jù)槽 ${slot}"
redis-cli -h ${target_host_ip} -p ${target_host_port} \
cluster addslots ${slot}
echo >&7
}&
done
wait # 這個不能變讲仰, 就是等待上面的所有后臺進程結束
exec 7>&- # 這個不能變慕趴,
echo "任務執(zhí)行完畢"
最后查看集群信息
可以發(fā)現(xiàn)此時集群的狀態(tài)是
OK
的。
查看節(jié)點信息
- 給集群節(jié)點配置主從關系
命令語法
redis-cli -p 從節(jié)點端口 cluster replicate 主節(jié)點的 ID
實操
切換到從節(jié)點所在的主機鄙陡,這樣有便于操作
先獲取到集群各個節(jié)點的 ID
再按照計劃好的進行復制關系的設置
[root@s2 ~]# redis-cli -p 7011 cluster replicate 587b37f1bbe86dcce2b21e3890a61e9b5cdabade
OK
[root@s2 ~]# redis-cli -p 7012 cluster replicate 9d2617ed1892ad08d0bc66b50dada6d53901cce3
OK
[root@s2 ~]# redis-cli -p 7013 cluster replicate e3f9b763619c0f94ce943e57766001f0283f6c51
OK
查看集群節(jié)點信息冕房,驗證主從關系
redis-cli -p 7011 cluster nodes
完全配置好后,可以觀察集群的數(shù)據(jù)槽的分配情況
redis-cli -p 7011 cluster slots
最后用客戶端登錄集群的方式登錄到集群中的任意一個節(jié)點趁矾,設置鍵值對進行測試耙册。
二、使用官方工具 redis-trib.rb 進行部署
官方工具依賴于 Ruby
1. 下載毫捣、編譯详拙、安裝 Ruby
wget https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.1.tar.gz
安裝依賴包
yum install zlib-devel readline openssl-devel gcc gcc-c++
tar xf ruby-2.6.1.tar.gz
cd ruby-2.6.1
./configure
make && make install
2. 安裝 rubygem redis
一個 ruby 語言實現(xiàn)的訪問 Redis 集群的客戶端
cd ..
wget https://rubygems.org/rubygems/rubygems-3.0.2.tgz
tar -xf rubygems-3.0.2.tgz
cd rubygems-3.0.2/
ruby setup.rb
gem install redis
3. 安裝 redis-trib.rb
redis-trib
位于 Redis 源碼的 src
文件夾中, 它是一個 Ruby 程序蔓同, 這個程序通過向實例發(fā)送特殊命令來完成創(chuàng)建新集群饶辙, 檢查集群, 或者對集群進行重新分片(reshared
)等工作斑粱。
cp ~/redis-4.0.10/src/redis-trib.rb /usr/local/bin/
chmod +x redis-trib.rb
沒有源碼安裝的可以從以下網(wǎng)址獲取
Redis 源碼 src 中的 redis-trib.rb 文件內(nèi)容
create:創(chuàng)建集群
check:檢查集群
info:查看集群信息
fix:修復集群
reshard:在線遷移slot
rebalance:平衡集群節(jié)點slot數(shù)量
add-node:添加新節(jié)點
del-node:刪除節(jié)點
set-timeout:設置節(jié)點的超時時間
call:在集群所有節(jié)點上執(zhí)行命令
import:將外部redis數(shù)據(jù)導入集群
配置集群
假如你完全安裝這個文檔做的實驗的換弃揽,此時配置集群之前,需要把之前的集群進程都停掉则北。
先在從節(jié)點上執(zhí)行蹋宦,再到主節(jié)點上執(zhí)行
ps -ef | grep redis-server | grep -v 'grep' | awk '{print $2}' |xargs kill
接著分別在兩臺主機上,把之前集群產(chǎn)生的數(shù)據(jù)清除
rm -rf /redis/data/*
再重新啟動這些節(jié)點的服務進程
redis-server 7001.conf
redis-server 7002.conf
redis-server 7003.conf
redis-server 7011.conf
redis-server 7012.conf
redis-server 7013.conf
之后使用如下命令創(chuàng)建集群
redis-trib.rb create --replicas 1 主節(jié)點1的IP:端口 主節(jié)點2的IP:端口 主節(jié)點3的IP:端口 從節(jié)點1的IP:端口 從節(jié)點2的IP:端口 從節(jié)點3的IP:端口
選項–replicas 1 表示我們希望為集群中的每個主節(jié)點創(chuàng)建一個從節(jié)點咒锻。
redis-trib.rb create --replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006
創(chuàng)建流程如下:
1冷冗、首先為每個節(jié)點創(chuàng)建ClusterNode對象,包括連接每個節(jié)點惑艇。檢查每個節(jié)點是否為獨立且db為空的節(jié)點蒿辙。執(zhí)行l(wèi)oad_info方法導入節(jié)點信息。
2滨巴、檢查傳入的master節(jié)點數(shù)量是否大于等于3個思灌。只有大于3個節(jié)點才能組成集群。
3恭取、計算每個master需要分配的slot數(shù)量泰偿,以及給master分配slave。分配的算法大致如下:
先把節(jié)點按照host分類蜈垮,這樣保證master節(jié)點能分配到更多的主機中耗跛。
不停遍歷遍歷host列表裕照,從每個host列表中彈出一個節(jié)點,放入interleaved數(shù)組调塌。直到所有的節(jié)點都彈出為止晋南。
master節(jié)點列表就是interleaved前面的master數(shù)量的節(jié)點列表。保存在masters數(shù)組羔砾。
計算每個master節(jié)點負責的slot數(shù)量负间,保存在slots_per_node對象,用slot總數(shù)除以master數(shù)量取整即可姜凄。
遍歷masters數(shù)組政溃,每個master分配slots_per_node個slot,最后一個master态秧,分配到16384個slot為止玩祟。
接下來為master分配slave,分配算法會盡量保證master和slave節(jié)點不在同一臺主機上屿聋。對于分配完指定slave數(shù)量的節(jié)點空扎,還有多余的節(jié)點,也會為這些節(jié)點尋找master润讥。分配算法會遍歷兩次masters數(shù)組转锈。
第一次遍歷masters數(shù)組,在余下的節(jié)點列表找到replicas數(shù)量個slave楚殿。每個slave為第一個和master節(jié)點host不一樣的節(jié)點撮慨,如果沒有不一樣的節(jié)點,則直接取出余下列表的第一個節(jié)點脆粥。
第二次遍歷是在對于節(jié)點數(shù)除以replicas不為整數(shù)砌溺,則會多余一部分節(jié)點。遍歷的方式跟第一次一樣变隔,只是第一次會一次性給master分配replicas數(shù)量個slave规伐,而第二次遍歷只分配一個,直到余下的節(jié)點被全部分配出去匣缘。
4猖闪、打印出分配信息,并提示用戶輸入“yes”確認是否按照打印出來的分配方式創(chuàng)建集群肌厨。
5培慌、輸入“yes”后,會執(zhí)行flush_nodes_config操作柑爸,該操作執(zhí)行前面的分配結果吵护,給master分配slot,讓slave復制master,對于還沒有握手(cluster meet)的節(jié)點馅而,slave復制操作無法完成祥诽,不過沒關系,flush_nodes_config操作出現(xiàn)異常會很快返回用爪,后續(xù)握手后會再次執(zhí)行flush_nodes_config原押。
6胁镐、給每個節(jié)點分配epoch偎血,遍歷節(jié)點,每個節(jié)點分配的epoch比之前節(jié)點大1盯漂。
7颇玷、節(jié)點間開始相互握手,握手的方式為節(jié)點列表的其他節(jié)點跟第一個節(jié)點握手就缆。
8帖渠、然后每隔1秒檢查一次各個節(jié)點是否已經(jīng)消息同步完成,使用ClusterNode的get_config_signature方法竭宰,檢查的算法為獲取每個節(jié)點cluster nodes信息空郊,排序每個節(jié)點,組裝成node_id1:slots|node_id2:slot2|...的字符串切揭。如果每個節(jié)點獲得字符串都相同狞甚,即認為握手成功。
9廓旬、此后會再執(zhí)行一次flush_nodes_config哼审,這次主要是為了完成slave復制操作。
10孕豹、最后再執(zhí)行check_cluster涩盾,全面檢查一次集群狀態(tài)。包括和前面握手時檢查一樣的方式再檢查一遍励背。確認沒有遷移的節(jié)點春霍。確認所有的slot都被分配出去了。
11叶眉、至此完成了整個創(chuàng)建流程终畅,返回[OK] All 16384 slots covered.。
4. 深入集群
集群的伸縮
添加節(jié)點(擴容)
-
準備節(jié)點
啟動兩個新的 redis 實例, 分別監(jiān)聽不同端口 比如 7008
和 7009
我這里是在一臺主機上啟動 redis 實例
cp 7001.conf 7008.conf
sed -i 's/7001/7008/g' 7008.conf
cp 7001.conf 7014.conf
sed -i 's/7001/7009/g' 7014.conf
redis-server 7008.conf
redis-server 7014.conf
2.加入集群中
添加一個新的節(jié)點為主節(jié)點
redis-trib.rb add-node new_host:new_port existing_host:existing_port
// new_host:new_port 為新添加的節(jié)點信息
// existing_host:existing_port 集群中任意節(jié)點的信息
添加一個新節(jié)點為從節(jié)點
redis-trib.rb add-node --slave --master-id 主節(jié)點的 ID new_host:new_port existing_host:existing_port
主節(jié)點 ID 可以使用如下命令查看竟闪,此命令還同時輸出了各個節(jié)點的角色
redis-trib.rb check host:port
// host:port 為集群中任意節(jié)點的信息
例如:
加入一個主節(jié)點到集群中
redis-trib.rb add-node 127.0.0.1:7008 127.0.0.1:7002
- 獲取剛才新加入的主節(jié)點信息
redis-trib.rb check 127.0.0.1:7002
檢查前會先執(zhí)行l(wèi)oad_cluster_info_from_node方法离福,把所有節(jié)點數(shù)據(jù)load進來。load的方式為通過自己的cluster nodes發(fā)現(xiàn)其他節(jié)點炼蛤,然后連接每個節(jié)點妖爷,并加入nodes數(shù)組。接著生成節(jié)點間的復制關系。
load完數(shù)據(jù)后絮识,開始檢查數(shù)據(jù)绿聘,檢查的方式也是調(diào)用創(chuàng)建時候使用的check_cluster。
- 添加從節(jié)點到集群中次舌,并指定他的主節(jié)點
redis-trib.rb add-node --slave --master-id 78e32beeb696819eb5718b0273723506761e645a 127.0.0.1:7009 127.0.0.1:7001
add-node命令可以將新節(jié)點加入集群熄攘,節(jié)點可以為master,也可以為某個master節(jié)點的slave彼念。
add-node new_host:new_port existing_host:existing_port
--slave
--master-id <arg>
add-node有兩個可選參數(shù):
--slave:設置該參數(shù)挪圾,則新節(jié)點以slave的角色加入集群
--master-id:這個參數(shù)需要設置了--slave才能生效,--master-id用來指定新節(jié)點的master節(jié)點逐沙。如果不設置該參數(shù)哲思,則會隨機為節(jié)點選擇master節(jié)點。
add-node流程如下:
1吩案、通過load_cluster_info_from_node方法轉載集群信息棚赔,check_cluster方法檢查集群是否健康。
2徘郭、如果設置了--slave靠益,則需要為該節(jié)點尋找master節(jié)點。設置了--master-id残揉,則以該節(jié)點作為新節(jié)點的master胧后,如果沒有設置--master-id,則調(diào)用get_master_with_least_replicas方法冲甘,尋找slave數(shù)量最少的master節(jié)點绩卤。如果slave數(shù)量一致,則選取load_cluster_info_from_node順序發(fā)現(xiàn)的第一個節(jié)點江醇。load_cluster_info_from_node順序的第一個節(jié)點是add-node設置的existing_host:existing_port節(jié)點濒憋,后面的順序根據(jù)在該節(jié)點執(zhí)行cluster nodes返回的結果返回的節(jié)點順序村象。
3郊尝、連接新的節(jié)點并與集群第一個節(jié)點握手。
4蜡饵、如果沒設置–slave就直接返回ok条辟,設置了–slave黔夭,則需要等待確認新節(jié)點加入集群,然后執(zhí)行cluster replicate命令復制master節(jié)點羽嫡。
5本姥、至此,完成了全部的增加節(jié)點的流程杭棵。
- 向新加入的主節(jié)點中分配槽
redis-trib.rb reshard 127.0.0.1:7001
reshard host:port
--from <arg>
--to <arg>
--slots <arg>
--yes
--timeout <arg>
--pipeline <arg>
host:port:這個是必傳參數(shù)婚惫,用來從一個節(jié)點獲取整個集群信息,相當于獲取集群信息的入口。
--from <arg>:需要從哪些源節(jié)點上遷移slot先舷,可從多個源節(jié)點完成遷移艰管,以逗號隔開,傳遞的是節(jié)點的node id蒋川,還可以直接傳遞--from all牲芋,這樣源節(jié)點就是集群的所有節(jié)點,不傳遞該參數(shù)的話捺球,則會在遷移過程中提示用戶輸入缸浦。
--to <arg>:slot需要遷移的目的節(jié)點的node id,目的節(jié)點只能填寫一個懒构,不傳遞該參數(shù)的話餐济,則會在遷移過程中提示用戶輸入耘擂。
--slots <arg>:需要遷移的slot數(shù)量胆剧,不傳遞該參數(shù)的話,則會在遷移過程中提示用戶輸入醉冤。
--yes:設置該參數(shù)秩霍,可以在打印執(zhí)行reshard計劃的時候,提示用戶輸入yes確認后再執(zhí)行reshard蚁阳。
--timeout <arg>:設置migrate命令的超時時間铃绒。
--pipeline <arg>:定義cluster getkeysinslot命令一次取出的key數(shù)量,不傳的話使用默認值為10螺捐。
遷移的流程如下:
1颠悬、通過load_cluster_info_from_node方法裝載集群信息。
2定血、執(zhí)行check_cluster方法檢查集群是否健康赔癌。只有健康的集群才能進行遷移。
3澜沟、獲取需要遷移的slot數(shù)量灾票,用戶沒傳遞--slots參數(shù),則提示用戶手動輸入茫虽。
4刊苍、獲取遷移的目的節(jié)點,用戶沒傳遞--to參數(shù)濒析,則提示用戶手動輸入正什。此處會檢查目的節(jié)點必須為master節(jié)點。
5号杏、獲取遷移的源節(jié)點婴氮,用戶沒傳遞--from參數(shù),則提示用戶手動輸入。此處會檢查源節(jié)點必須為master節(jié)點莹妒。--from all的話名船,源節(jié)點就是除了目的節(jié)點外的全部master節(jié)點。這里為了保證集群slot分配的平均旨怠,建議傳遞--from all渠驼。
6、執(zhí)行compute_reshard_table方法鉴腻,計算需要遷移的slot數(shù)量如何分配到源節(jié)點列表迷扇,采用的算法是按照節(jié)點負責slot數(shù)量由多到少排序,計算每個節(jié)點需要遷移的slot的方法為:遷移slot數(shù)量 * (該源節(jié)點負責的slot數(shù)量 / 源節(jié)點列表負責的slot總數(shù))爽哎。這樣算出的數(shù)量可能不為整數(shù)蜓席,這里代碼用了下面的方式處理:
n = (numslots/source_tot_slots*s.slots.length)
if i == 0
n = n.ceil
else
n = n.floor
這樣的處理方式會帶來最終分配的slot與請求遷移的slot數(shù)量不一致,這個BUG已經(jīng)在github上提給作者课锌,https://github.com/antirez/redis/issues/2990厨内。
7、打印出reshard計劃渺贤,如果用戶沒傳--yes雏胃,就提示用戶確認計劃。
8志鞍、根據(jù)reshard計劃瞭亮,一個個slot的遷移到新節(jié)點上,遷移使用move_slot方法固棚,該方法被很多命令使用统翩,具體可以參見下面的遷移流程。move_slot方法傳遞dots為true和pipeline數(shù)量此洲。
9厂汗、至此,就完成了全部的遷移任務黍翎。
補充
move_slot方法可以在線將一個slot的全部數(shù)據(jù)從源節(jié)點遷移到目的節(jié)點面徽,fix、reshard匣掸、rebalance都需要調(diào)用該方法遷移slot趟紊。
move_slot接受下面幾個參數(shù),
1碰酝、pipeline:設置一次從slot上獲取多少個key霎匈。
2、quiet:遷移會打印相關信息送爸,設置quiet參數(shù)铛嘱,可以不用打印這些信息暖释。
3、cold:設置cold墨吓,會忽略執(zhí)行importing和migrating球匕。
4、dots:設置dots帖烘,則會在遷移過程打印遷移key數(shù)量的進度亮曹。
5、update:設置update秘症,則會更新內(nèi)存信息照卦,方便以后的操作。
move_slot流程如下:
1乡摹、如果沒有設置cold役耕,則對源節(jié)點執(zhí)行cluster importing命令,對目的節(jié)點執(zhí)行migrating命令聪廉。fix的時候有可能importing和migrating已經(jīng)執(zhí)行過來瞬痘,所以此種場景會設置cold。
2锄列、通過cluster getkeysinslot命令图云,一次性獲取遠節(jié)點遷移slot的pipeline個key的數(shù)量.
3惯悠、對這些key執(zhí)行migrate命令邻邮,將數(shù)據(jù)從源節(jié)點遷移到目的節(jié)點。
4克婶、如果migrate出現(xiàn)異常筒严,在fix模式下,BUSYKEY的異常情萤,會使用migrate的replace模式再執(zhí)行一次鸭蛙,BUSYKEY表示目的節(jié)點已經(jīng)有該key了,replace模式可以強制替換目的節(jié)點的key筋岛。不是fix模式就直接返回錯誤了娶视。
5、循環(huán)執(zhí)行cluster getkeysinslot命令睁宰,直到返回的key數(shù)量為0肪获,就退出循環(huán)。
6柒傻、如果沒有設置cold孝赫,對每個節(jié)點執(zhí)行cluster setslot命令,把slot賦給目的節(jié)點红符。
7青柄、如果設置update伐债,則修改源節(jié)點和目的節(jié)點的slot信息。
8致开、至此完成了遷移slot的流程峰锁。
- 完成后觀察各主節(jié)點的數(shù)據(jù)槽的分配情況
減少節(jié)點(縮容)
縮容時的遷移槽
忘記節(jié)點操作
實驗
命令:
./redis-trib.rb reshard --from 下線節(jié)點 ID --to 集群中的任意主節(jié)點 ID --slots 遷移到槽數(shù) 目前集群中任意節(jié)點 IP:端口
redis-trib.rb reshard --from 78e32beeb696819eb5718b0273723506761e645a --to e00fedd6658c5cfedb2a27346a8e0e137b403536 --slots 4096 127.0.0.1:7001
注意:
需要把下線節(jié)點的槽數(shù)平均遷移到剩余的所有節(jié)點,所以需要分批分次執(zhí)行上面的命令双戳。
并且祖今,每次都集群中的主節(jié)點應該不同。
刪除節(jié)點
當我們使用 redis-trib.rb
工具時拣技,只需要在目前集群中的任意一個節(jié)點中執(zhí)行如下命令即可千诬。
redis-trib.rb del-node 集群中的任意host:port 刪除的節(jié)點的id
注意:
你應該始終先刪除從節(jié)點,再刪除主節(jié)點
del-node流程如下:
1膏斤、通過load_cluster_info_from_node方法轉載集群信息徐绑。
2、根據(jù)傳入的node id獲取節(jié)點莫辨,如果節(jié)點沒找到傲茄,則直接提示錯誤并退出。
3沮榜、如果節(jié)點分配的slot不為空盘榨,則直接提示錯誤并退出。
4蟆融、遍歷集群內(nèi)的其他節(jié)點草巡,執(zhí)行cluster forget命令,從每個節(jié)點中去除該節(jié)點型酥。如果刪除的節(jié)點是master山憨,而且它有slave的話,這些slave會去復制其他master弥喉,調(diào)用的方法是get_master_with_least_replicas郁竟,與add-node沒設置--master-id尋找master的方法一樣。
5由境、然后關閉該節(jié)點
刪除節(jié)點的小問題
在cluster不小心刪除某個節(jié)點后再加入節(jié)點是個很麻煩的事(刪除之前先把cluster分配的hashslot給重新分配一下(很重要))
通過 redis-trib.rb del-node 你的節(jié)點地址 bd5a40a6ddccbd46a0f4a2208eb25d2453c2a8db(你的node ID(可以通過 redis-trib.rb check 查看))刪除你的節(jié)點棚亩。
刪除完后要是想重新添加回去時發(fā)現(xiàn)用 redis-trib.rb add-node 你的節(jié)點地址 需要掛載的集群的節(jié)點 添加時會報錯,
[ERR] Node 192.168.XX.XX:XXXX is not empty. Either the nodealready knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
出現(xiàn)這個的原因是這個節(jié)點之前已經(jīng)加入過這個集群了虏杰,再次加入就會爆出這樣的錯誤讥蟆,你可以區(qū)配置節(jié)點的xxxx.conf文件里找到你保存的cluster-config-fil節(jié)點信息,找到然后刪除掉嘹屯,然后刪除掉該節(jié)點的數(shù)據(jù)保存RDB文件(要是開啟的AOF)也需一并刪除掉
然后運行 redis-trib.rb add-node 命令攻询,看是否可以加入集群。成功的話就不用往下看了
要是還是不行就得去連接到你的Redis redis-cli -h 192.168.XXX.XXX -p xxxx (你節(jié)點的地址個端口號)去flushdb一下州弟,清空數(shù)據(jù)庫钧栖,再次add-node應該就可以了低零。添加節(jié)點后記得給他分配hashslot(記得)
補充知識點
rebalance平衡集群節(jié)點slot數(shù)量
rebalance命令可以根據(jù)用戶傳入的參數(shù)平衡集群節(jié)點的slot數(shù)量,rebalance功能非常強大拯杠,可以傳入的參數(shù)很多掏婶,以下是rebalance的參數(shù)列表和命令示例。
rebalance host:port
--weight <arg>
--auto-weights
--threshold <arg>
--use-empty-masters
--timeout <arg>
--simulate
--pipeline <arg>
$ruby redis-trib.rb rebalance --threshold 1 --weight b31e3a2e=5 --weight 60b8e3a1=5 --use-empty-masters --simulate 10.180.157.199:6379
host:port:這個是必傳參數(shù)潭陪,用來從一個節(jié)點獲取整個集群信息雄妥,相當于獲取集群信息的入口。
--weight <arg>:節(jié)點的權重依溯,格式為node_id=weight老厌,如果需要為多個節(jié)點分配權重的話,需要添加多個--weight <arg>參數(shù)黎炉,即--weight b31e3a2e=5 --weight 60b8e3a1=5枝秤,node_id可為節(jié)點名稱的前綴,只要保證前綴位數(shù)能唯一區(qū)分該節(jié)點即可慷嗜。沒有傳遞–weight的節(jié)點的權重默認為1淀弹。
--auto-weights:這個參數(shù)在rebalance流程中并未用到。
--threshold <arg>:只有節(jié)點需要遷移的slot閾值超過threshold庆械,才會執(zhí)行rebalance操作薇溃。具體計算方法可以參考下面的rebalance命令流程的第四步。
--use-empty-masters:rebalance是否考慮沒有節(jié)點的master缭乘,默認沒有分配slot節(jié)點的master是不參與rebalance的沐序,設置--use-empty-masters可以讓沒有分配slot的節(jié)點參與rebalance。
--timeout <arg>:設置migrate命令的超時時間忿峻。
--simulate:設置該參數(shù)薄啥,可以模擬rebalance操作,提示用戶會遷移哪些slots逛尚,而不會真正執(zhí)行遷移操作。
--pipeline <arg>:與reshar的pipeline參數(shù)一樣刁愿,定義cluster getkeysinslot命令一次取出的key數(shù)量绰寞,不傳的話使用默認值為10。
rebalance命令流程如下:
1铣口、load_cluster_info_from_node方法先加載集群信息滤钱。
2、計算每個master的權重脑题,根據(jù)參數(shù)--weight <arg>件缸,為每個設置的節(jié)點分配權重,沒有設置的節(jié)點叔遂,則權重默認為1他炊。
3争剿、根據(jù)每個master的權重,以及總的權重痊末,計算自己期望被分配多少個slot蚕苇。計算的方式為:總slot數(shù)量 * (自己的權重 / 總權重)。
4凿叠、計算每個master期望分配的slot是否超過設置的閾值涩笤,即--threshold <arg>設置的閾值或者默認的閾值。計算的方式為:先計算期望移動節(jié)點的閾值盒件,算法為:(100-(100.0*expected/n.slots.length)).abs蹬碧,如果計算出的閾值沒有超出設置閾值,則不需要為該節(jié)點移動slot炒刁。只要有一個master的移動節(jié)點超過閾值锰茉,就會觸發(fā)rebalance操作。
5切心、如果觸發(fā)了rebalance操作飒筑。那么就開始執(zhí)行rebalance操作,先將每個節(jié)點當前分配的slots數(shù)量減去期望分配的slot數(shù)量獲得balance值绽昏。將每個節(jié)點的balance從小到大進行排序獲得sn數(shù)組协屡。
6、用dst_idx和src_idx游標分別從sn數(shù)組的頭部和尾部開始遍歷全谤。目的是為了把尾部節(jié)點的slot分配給頭部節(jié)點肤晓。
sn數(shù)組保存的balance列表排序后,負數(shù)在前面认然,正數(shù)在后面补憾。負數(shù)表示需要有slot遷入,所以使用dst_idx游標卷员,正數(shù)表示需要有slot遷出盈匾,所以使用src_idx游標。理論上sn數(shù)組各節(jié)點的balance值加起來應該為0毕骡,不過由于在計算期望分配的slot的時候只是使用直接取整的方式削饵,所以可能出現(xiàn)balance值之和不為0的情況,balance值之和不為0即為節(jié)點不平衡的slot數(shù)量未巫,由于slot總數(shù)有16384個窿撬,不平衡數(shù)量相對于總數(shù),基數(shù)很小叙凡,所以對rebalance流程影響不大劈伴。
7、獲取sn[dst_idx]和sn[src_idx]的balance值較小的那個值握爷,該值即為需要從sn[src_idx]節(jié)點遷移到sn[dst_idx]節(jié)點的slot數(shù)量跛璧。
8严里、接著通過compute_reshard_table方法計算源節(jié)點的slot如何分配到源節(jié)點列表。這個方法在reshard流程中也有調(diào)用赡模,具體步驟可以參考reshard流程的第六步田炭。
9、如果是simulate模式漓柑,則只是打印出遷移列表教硫。
10、如果沒有設置simulate辆布,則執(zhí)行move_slot操作瞬矩,遷移slot,傳入的參數(shù)為:quiet=>true,:dots=>false,:update=>true锋玲。
11景用、遷移完成后更新sn[dst_idx]和sn[src_idx]的balance值。如果balance值為0后惭蹂,游標向前進1伞插。
12、直到dst_idx到達src_idx游標盾碗,完成整個rebalance操作媚污。