
簡介一份面向 CentOS 7.x 環(huán)境搭建 Redis 集群的自動化部署腳本包服務于需要快速驗證集群方案的運維與后端開發(fā)者把主從復制、16384 個槽位分配、故障轉移等集群要點固化為可一鍵執(zhí)行的流程免去逐臺手工編譯與配置的重復勞動。壓縮包共 5 個文件、約 1.86MB以 3 個 sh 腳本為主體分別承擔主流程調度、Redis 安裝配置與集群卸載清理另含 redis-5.0.0.tar.gz 源碼包和一份 txt 使用說明覆蓋從解壓編譯到集群成型的完整環(huán)節(jié)已有 777 人學習。按說明修改 IP 與端口變量后依次執(zhí)行即可完成依賴安裝、編譯、節(jié)點配置與集群創(chuàng)建卸載腳本便于回收實例與殘留配置腳本中的變量定義、條件判斷與循環(huán)結構也可作為編寫同類自動化部署腳本的參考。對初次接觸集群部署的讀者還可借此理解節(jié)點角色劃分與槽位分配在真實環(huán)境中的含義并沿著腳本順序梳理常見故障的排查方向。1. 手工搭三主三從熬到凌晨這份 Redis 集群一鍵部署腳本省掉的四件事三臺 CentOS 機器、六個 Redis 實例我第一次手工搭集群從下午兩點折騰到凌晨配置文件手改六遍meet 完節(jié)點卡在 handshake最后發(fā)現是 17000 端口沒放行。后來拿到這份 redis 集群一鍵自動部署腳本.rar真正省事的不是redis-cli --cluster create那一行而是它前面那堆重復勞動——批量生成 conf、按順序拉起實例、把客戶端端口和集群總線端口一起放通、創(chuàng)建完再跑一遍 check 把狀態(tài)確認下來。這套東西是 shell 寫的貼著 CentOS 的 systemctl、firewalld、sysctl 走沒有額外運行時依賴幾百行讀一遍就能按自己的機器改。它適合三類人手上只有兩三臺測試機、需要反復重建集群做課程設計或壓測的線上出過槽位故障、想在預發(fā)環(huán)境原樣復現的以及剛接觸 Redis Cluster、想先跑通再回頭補原理的。下面從機制講到執(zhí)行鏈路再講翻車點。2. 槽位、總線與選舉一鍵腳本必須替你做對的四個集群機制腳本只做「生成配置、拉進程、建集群」三件事但每一件背后都壓著 Redis Cluster 的運行時規(guī)則。不理解這四條腳本跑掛了連日志該往哪看都不知道。反過來理解了這四條腳本里那些看起來多余的 sleep、循環(huán)和判斷你就知道它在防什么。2.1 16384 個槽位怎么分腳本為什么默認給三主Redis Cluster 把整個鍵空間切成 16384 個槽key 落到哪個槽由CRC16(key) mod 16384決定槽再歸某個主節(jié)點管??蛻舳四玫?MOVED 重定向后自己緩存槽位表所以集群的核心不是「數據分片存儲」這件事本身而是「槽位歸屬必須全集群一致」。任何一個槽沒有主人集群在cluster-require-full-coverage yes默認值下會直接拒絕所有寫請求。一鍵腳本之所以默認三主三從不是審美選擇是硬約束--cluster-replicas 1要求主節(jié)點數至少 3因為故障轉移要靠主節(jié)點多數派投票兩個主節(jié)點掛一個就湊不出多數。三主是最小可用拓撲腳本里如果寫成「節(jié)點數 / 2」來算主節(jié)點數節(jié)點少于 6 個時就會算出 2 主create 階段直接報*** ERROR: Invalid configuration for cluster creation。槽位分配默認是均分再取余16384 / 3 5461、5461、5462第三個主節(jié)點多拿 2 個槽。這個數字在很多巡檢腳本里被寫死成5461做斷言一旦集群做過 reshard 就會誤報。我的做法是只看cluster info里的cluster_slots_assigned:16384不校驗單節(jié)點槽數。另外要記住集群模式只支持 db 0配置里寫databases 16不會報錯但SELECT命令會被拒絕返回ERR SELECT is not allowed in cluster mode。涉及多 key 的操作必須落在同一個槽用 hash tag 把 key 的一部分用{}包起來比如user:{1001}:name和user:{1001}:age會被強制分到同一槽這是設計鍵名時就要定下來的事不是部署階段能補救的。2.2 cluster bus 與握手meet 之后到底發(fā)生了什么每個集群節(jié)點會額外監(jiān)聽一個「客戶端端口 10000」的總線端口7000 對應 17000。節(jié)點之間交換 gossip 消息、投票、傳播槽位表都走這個端口用的是二進制協議和客戶端協議不是一回事。手工搭集群最常見的卡點就在這里6379 能 telnet 通17000 不通cluster nodes里對方節(jié)點永遠是handshake狀態(tài)日志里反復刷Unable to connect to MASTER。握手的完整鏈路是腳本對 A 節(jié)點執(zhí)行CLUSTER MEET B_IP B_PORTA 通過總線端口連 B交換節(jié)點信息B 再把 A 的信息 gossip 給已知節(jié)點。所以只要有一個節(jié)點的總線端口不通整個集群就可能分裂成兩個互不可見的孤島而cluster_state在每個孤島內部都顯示 ok。這就是為什么腳本里的防火墻規(guī)則必須成對出現客戶端端口段和總線端口段一起放少寫一行就是幾小時的排查。還有個容易被忽略的點節(jié)點的 node id 存在cluster-config-file指定的文件里默認叫nodes.conf。這個文件是 Redis 自己維護的腳本絕對不能刪、不能提前創(chuàng)建、不能手改。刪掉它的后果是節(jié)點重啟后生成新 id其他節(jié)點還拿著舊 id 做 gossip集群視圖徹底錯亂。我在腳本里見過用rm -rf $DATA_DIR/*做「清理重來」的寫法看著干凈實際上把 nodes.conf 一起干掉了第二次執(zhí)行必翻車。2.3 主從復制與自動故障轉移的判定鏈路從節(jié)點默認每秒向主節(jié)點發(fā)REPLCONF ACK主節(jié)點把復制偏移量記在內存里。某個主節(jié)點失聯后其余主節(jié)點在cluster-node-timeout默認 15000 毫秒之后把它標記為fail然后由持有該主節(jié)點槽位的從節(jié)點發(fā)起選舉拿到多數主節(jié)點投票后提升為主接管槽位。整個過程腳本管不了但腳本里的兩個參數直接決定它能不能成。一個參數是cluster-node-timeout。設太小網絡抖一下就觸發(fā)主從切換切完數據還沒同步完又切回來設太大真掛了要等半分鐘以上才恢復。生產上給 15000 到 30000 之間比較穩(wěn)測試機可以給 5000 加快演練節(jié)奏。另一個是cluster-replica-validity-factor默認 10從節(jié)點斷線時間超過node-timeout × factor就失去競選資格這是防止用一份過期數據頂上去的保護。把它設成 0 表示不管斷多久都能選只在「寧可丟數據也要??捎谩沟膱鼍跋虏胚@么干。從節(jié)點能不能被選中還要看它的復制偏移量和主節(jié)點差多少。如果腳本為了讓啟動快把repl-diskless-sync之類的東西亂調或者從節(jié)點剛起來還沒完成全量同步就被拉進集群選舉時它的 offset 落后太多同樣會被其他主節(jié)點拒絕。所以腳本里「拉起實例」和「cluster create」之間應該留幾秒讓復制鏈路建立這個 sleep 不是玄學是在等master_link_status:up。2.4 節(jié)點順序與副本錯位腳本里最容易寫錯的一段邏輯redis-cli --cluster create的節(jié)點列表順序是有語義的前 N 個被當作主節(jié)點后面按順序分配給它們做從節(jié)點。如果參數寫成--cluster-replicas 1列表是A B C D E F那 A B C 是主D E F 依次是 A B C 的從。但這個「依次」是按主機和端口的排列算的腳本如果用兩層 for 循環(huán)先生成所有 7000 端口再生成所有 7001 端口最終可能出現三個主節(jié)點全在同一臺物理機上另一臺機器上的三個從節(jié)點全在等它掛——機器一斷電集群直接沒了一半。正確的做法是按機器交錯排列每臺機器出兩個實例列表寫成A:7000 A:7001 B:7000 B:7001 C:7000 C:7001這樣主節(jié)點天然分散在三臺機器上從節(jié)點也落在不同的物理機。腳本里如果做了「按 IP 分組再拼接」的處理讀的時候要確認它是交錯而不是分段。這一點在驗收時可以用redis-cli --cluster check輸出的主從對應關系直接看出來從節(jié)點和它的主節(jié)點在同一臺機器上就是錯位了。還有一種錯位是端口和目錄沒對上。同一個 IP 上跑 7000 和 7001 兩個實例配置里的dir必須是兩個不同目錄logfile、pidfile、dbfilename也都得帶端口后綴。腳本如果只替換了port而沒替換dir兩個實例會往同一個 dump 文件里寫AOF 也會互相覆蓋癥狀是集群能建起來但一重啟數據就亂。3. 解包看結構CentOS 上的目錄、系統(tǒng)參數與端口三件套拿到 rar 之后第一件事不是急著bash deploy.sh而是先看清包里有什么、它假設你的機器處于什么狀態(tài)。這類腳本的失敗八成不是腳本邏輯錯而是它默認的前置條件在你的機器上不成立。3.1 壓縮包里的文件各管什么rar 在 CentOS 上默認解不開需要先裝unrar很多最小化安裝的鏡像里沒有這個包得先配好軟件源再裝。解出來的目錄結構各家寫法不同但職責基本是固定的幾類讀之前先按下面這張表對一遍缺哪個文件就知道腳本會缺哪一步文件/目錄典型職責缺了會怎樣deploy.sh主入口串起檢查、生成、啟動、建集群無法一鍵執(zhí)行redis.conf.tpl配置模板用變量占位端口、目錄、密碼生成的配置全是默認值nodes.list/hosts.conf節(jié)點 IP 與端口清單腳本不知道往哪幾臺機器鋪start_all.sh/stop_all.sh批量拉起與停止實例只能手工 ps 后 killcheck_cluster.sh建完集群后的狀態(tài)校驗出問題沒有統(tǒng)一出口redis-*.tar.gz源碼包或二進制包需要自己準備同版本安裝包README端口、密碼、目錄約定參數只能靠讀腳本猜讀腳本時優(yōu)先確認三件事REDIS_HOME裝在哪、DATA_DIR數據落在哪、密碼是寫死在腳本里還是從外部傳入。寫死密碼的腳本在多人共用的測試環(huán)境里很常見改的時候記得同步改requirepass和masterauth兩處只改一處集群建不起來。3.2 CentOS 7/8 必須先改的四個內核與資源項Redis 在集群模式下對系統(tǒng)資源更敏感因為多了總線連接和節(jié)點間心跳。以下四項如果腳本里沒做建議在執(zhí)行前手工補上用sysctl落成配置文件比sysctl -w臨時改可靠重啟不丟# /etc/sysctl.d/99-redis-cluster.conf # 允許內存過量提交否則 fork 做 RDB 落盤時可能直接失敗 vm.overcommit_memory 1 # 監(jiān)聽隊列長度低于 511 時高并發(fā)下會出現連接被丟棄 net.core.somaxconn 1024 # 盡量不使用 swap避免節(jié)點間心跳因換頁抖動而超時 vm.swappiness 1 # 關閉透明大頁THP 會造成 Redis 的 fork 延遲 spikes echo never /sys/kernel/mm/transparent_hugepage/enabled echo never /sys/kernel/mm/transparent_hugepage/defrag sysctl --systemvm.overcommit_memory這一項是最容易被忽略的日志里表現為Background save is starting之后跟一條fork: Cannot allocate memory進程直接沒了而這臺機器內存看起來還很空閑。原因不是內存不夠是內核在 fork 時按 overcommit 策略拒絕了地址空間申請。somaxconn則對應TCP: request_sock_TCP: Possible SYN flooding這類告警連接數一上來就丟包。文件描述符也得提。Redis 默認建議ulimit -n不低于 10032systemd 拉起的服務要在 unit 文件里寫LimitNOFILE10032光改/etc/security/limits.conf對 systemd 服務不生效這是 CentOS 7 之后非常常見的坑。腳本如果用redis-server xxx.conf 的方式啟動繼承的是當前 shell 的限制換個終端執(zhí)行結果就不一樣我一般讓腳本顯式ulimit -n 10032再拉進程。3.3 端口放行7000-7005 只是其中一半六個實例用 7000 到 7005客戶端連這些端口沒問題但節(jié)點之間要走 17000 到 17005只放前半段的表現是cluster nodes里其他節(jié)點一直是handshake或者已經connected但cluster_state:fail日志刷Cluster bus: connection refused。firewalld 的寫法是一次把兩段都加上# 客戶端端口段 firewall-cmd --permanent --add-port7000-7005/tcp # 集群總線端口段 客戶端端口 10000 firewall-cmd --permanent --add-port17000-17005/tcp firewall-cmd --reload firewall-cmd --list-ports如果機器在云上安全組是另一道門firewall-cmd --list-ports有輸出不代表外部能進來。驗證方式是換一臺機器用telnet 目標IP 17000或者nc -zv 目標IP 17000試本地ss -lntp | grep 1700看到監(jiān)聽只說明本機進程起來了跟網絡可達是兩件事。還有個細節(jié)如果同一臺機器上跑多個實例bind建議寫內網 IP 而不是0.0.0.0同時把protected-mode關掉集群模式和多節(jié)點訪問下通常要關并且顯式設置cluster-announce-ip為內網地址。多網卡機器上不設這一項節(jié)點會把自己廣播成 127.0.0.1 或者某塊業(yè)務網卡的地址其他節(jié)點按這個地址連總線端口永遠連不上。4. 從零跑一遍配置生成、實例拉起、cluster create 的完整鏈路這一章按執(zhí)行順序走一遍每一步給出關鍵命令和需要核對的輸出。腳本再自動這四步的中間產物你都應該知道長什么樣否則出問題只能干等。4.1 生成六份 redis.conf用循環(huán)替掉手改配置模板的核心是集群相關的那幾行端口、目錄、密碼用變量替換。手寫六份的失敗率遠高于想象一份漏了cluster-enabled yescreate 階段就報Node xxx is not configured as a cluster node。用循環(huán)生成模板只維護一份#!/usr/bin/env bash set -euo pipefail BASE_PORT7000 DATA_ROOT/data/redis-cluster NODES(10.0.0.11 10.0.0.12 10.0.0.13) PASSWORDChangeMe_2024 for ip in ${NODES[]}; do for idx in 0 1; do port$((BASE_PORT idx)) dir${DATA_ROOT}/${port} mkdir -p ${dir} cat ${dir}/redis.conf EOF port ${port} bind ${ip} protected-mode no daemonize yes pidfile ${dir}/redis.pid logfile ${dir}/redis.log dir ${dir} dbfilename dump-${port}.rdb appendonly yes appendfilename appendonly-${port}.aof # 集群三件套開關、節(jié)點狀態(tài)文件、失聯判定毫秒數 cluster-enabled yes cluster-config-file nodes-${port}.conf cluster-node-timeout 15000 cluster-announce-ip ${ip} cluster-announce-port ${port} cluster-announce-bus-port $((port 10000)) # 密碼必須兩處一致否則從節(jié)點同步和集群創(chuàng)建都會失敗 requirepass ${PASSWORD} masterauth ${PASSWORD} EOF done done幾個參數值得單獨說。cluster-config-file帶上端口后綴避免同機多實例互相覆蓋這個文件由 Redis 維護腳本只負責給路徑。cluster-announce-ip顯式寫成當前機器的內網 IP多網卡環(huán)境下這是唯一可靠的廣播地址來源。appendonly yes在集群里建議打開從節(jié)點提升為主后如果只有 RDB最后一個 RDB 之后的數據就丟了。daemonize yes讓實例后臺跑腳本里要跟一個循環(huán)等待端口就緒不能生成完就立刻建集群。路徑權限也要順手檢查${dir}必須對運行 Redis 的用戶可寫用 root 生成目錄、用 redis 用戶起進程是常見組合權限沒給對的表現是啟動即退出日志里一行Cant open the append-only file: Permission denied。4.2 拉起實例并確認端口真的在監(jiān)聽啟動之后不要相信daemonize的返回值它只表示 fork 成功不表示配置正確。判斷標準是端口在監(jiān)聽且PING有回應這一步放在腳本里就是一個帶超時的輪詢#!/usr/bin/env bash # 逐臺啟動并按端口探活超過 30 秒未就緒就打印日志尾巴退出 for ip in 10.0.0.11 10.0.0.12 10.0.0.13; do for port in 7000 7001; do ssh ${ip} redis-server ${DATA_ROOT}/${port}/redis.conf for i in $(seq 1 30); do if redis-cli -h ${ip} -p ${port} -a ChangeMe_2024 --no-auth-warning ping 2/dev/null | grep -q PONG; then echo OK ${ip}:${port} break fi sleep 1 done redis-cli -h ${ip} -p ${port} -a ChangeMe_2024 --no-auth-warning ping \ | grep -q PONG || { tail -n 30 ${DATA_ROOT}/${port}/redis.log; exit 1; } done done這里用--no-auth-warning只是避免密碼提示刷屏腳本里不要把密碼明文寫進 history正式環(huán)境建議用REDISCLI_AUTH環(huán)境變量傳。探活只看PING還不夠集群模式下要再確認cluster-enabled:yes和cluster_state的初始值剛啟動的節(jié)點應該是cluster_state:fail、cluster_known_nodes:1這屬于正常狀態(tài)說明它以單節(jié)點身份起來了等著被 meet。如果某個端口一直起不來先看日志最后 30 行再看ss -lntp | grep 端口有沒有別的進程占著。測試機上經常出現上一次的實例沒殺干凈pidfile 殘留導致新進程以為自己在跑daemonize yes下這種問題特別隱蔽。4.3 cluster create 的節(jié)點順序與副本分配六個節(jié)點都活了之后才能建集群節(jié)點列表按「主機交錯、主節(jié)點在前」的順序排。Redis 5 之后--cluster子命令是內建的不需要額外裝 ruby 的 redis-tribredis-cli --cluster create \ 10.0.0.11:7000 10.0.0.12:7000 10.0.0.13:7000 \ 10.0.0.11:7001 10.0.0.12:7001 10.0.0.13:7001 \ --cluster-replicas 1 \ -a ChangeMe_2024 --cluster-yes前三個是主節(jié)點后三個按順序做它們的從節(jié)點所以 7001 的三個實例分別跟著三個 7000 主節(jié)點且從節(jié)點都不在同一個 IP 上——這就是 2.4 里說的交錯排列。--cluster-yes跳過多余的交互確認腳本里必須加否則會卡在Can I set the above configuration? (type yes to accept)等人輸入。-a在帶密碼集群里要給且必須和配置里的requirepass一致。執(zhí)行過程中會看到每個主節(jié)點分到5461/5461/5462個槽接著是Waiting for the cluster to join這一步耗時取決于總線端口是否通。如果卡在這里超過一分鐘別等直接去另一臺機器上看telnet 目標IP 17000是否可達九成是端口或cluster-announce-ip的問題。4.4 用 cluster check 把狀態(tài)釘死創(chuàng)建命令返回成功不代表集群健康必須再跑一遍 check它會逐個節(jié)點連過去核對槽位覆蓋和主從關系redis-cli --cluster check 10.0.0.11:7000 -a ChangeMe_2024 # 關鍵看三行 # [OK] All 16384 slots covered. # 每個 master 下列出的 slots 區(qū)間與 replica 數量 # [OK] All nodes agree about slots configuration.All nodes agree about slots configuration這句是核心它表示各節(jié)點的槽位視圖已經收斂一致。如果這里報Different slots configuration說明有節(jié)點的信息還沒 gossip 到等幾秒重跑如果一直不一致檢查是不是有節(jié)點被 meet 過兩次、在集群里留了重復條目。驗收時我會把 check 的輸出存一份到日志目錄后面擴容、遷移、重啟都可以拿來對比。5. 避坑與排查cluster_state:ok 之后仍然會翻車的五個場景集群建起來、狀態(tài) ok只說明拓撲成立不代表業(yè)務能用。下面五個是我和同事在不同機器上真實踩過的癥狀看起來都不像集群問題根因全在配置和端口上。5.1 客戶端一直報 MOVED狀態(tài)卻是 ok現象應用連上 7000 寫一個 key報MOVED 12345 10.0.0.12:7000程序里沒做重定向處理直接拋異常。集群側CLUSTER INFO顯示一切正常。原因客戶端沒開集群模式把 Redis 當成單機在用。MOVED 不是錯誤是告訴客戶端這個槽在別的節(jié)點集群感知客戶端會自動跟隨并緩存槽位表單機客戶端則把重定向當異常拋出來。另一種變體是連的是代理或 VIP請求被固定轉發(fā)到某一臺槽位表永遠變不過來。解決換成客戶端庫的集群模式初始化方式連接時給出全部種子節(jié)點而不是一個 VIP。如果確實只能給單地址必須在中間層做槽位感知轉發(fā)不能做四層負載均衡——四層會把同一個連接的所有請求固定到同一節(jié)點跨槽訪問必然失敗。5.2 節(jié)點卡在 handshake 半天不動現象cluster nodes里某個節(jié)點狀態(tài)是handshakecluster info的cluster_known_nodes比實際節(jié)點數少日志反復刷Unable to connect to node。原因總線端口不通或者節(jié)點廣播的地址是 127.0.0.1、某塊業(yè)務網卡地址。前者是防火墻只放了 7000 段后者是多網卡機器沒設cluster-announce-ip節(jié)點按默認網卡地址互相通告對方連過去自然不通。解決把總線端口段補進防火墻和安全組cluster-announce-ip顯式寫內網 IP 后重啟實例。已經進過集群的錯誤節(jié)點不能直接改配置重啟要先CLUSTER RESET HARD清掉它的節(jié)點狀態(tài)再重新CLUSTER MEET否則舊地址會一直留在其他節(jié)點的視圖里。5.3 重啟之后集群整體 fail現象三臺機器重啟實例都起來了cluster_state:failcluster_slots_assigned遠小于 16384部分主節(jié)點顯示fail?。原因腳本的清理邏輯把nodes-*.conf刪了節(jié)點重新生成 id全集群不認它或者數據目錄權限變了節(jié)點讀不到原狀態(tài)文件只能當新節(jié)點啟動還有一種是從節(jié)點比主節(jié)點先起來且主節(jié)點長時間未就緒從節(jié)點把自己降級成孤立狀態(tài)。解決nodes.conf絕對不刪。重啟順序先主后從腳本里加等待邏輯確認所有主節(jié)點cluster_state恢復到 ok 再拉起從節(jié)點。真出現了 id 變更只能在剩下節(jié)點里用CLUSTER FORGET把舊條目錄掉再把故障節(jié)點以干凈狀態(tài)重新加回并遷移槽位這個操作要停機窗口。5.4 帶密碼的集群創(chuàng)建直接失敗現象redis-cli --cluster create輸出Node xxx replied with error: NOAUTH Authentication required或者從節(jié)點一直master_link_status:down。原因requirepass配了masterauth沒配或者值不一樣。requirepass管客戶端連它masterauth管它連主節(jié)點時用什么密碼集群里兩個方向都要通只配一處就是半通狀態(tài)。解決兩處寫成同一個值redis-cli --cluster相關命令帶-a或用REDISCLI_AUTH。改配置要六個節(jié)點全改一遍再重啟改完先用redis-cli -a 密碼 info replication確認從節(jié)點master_link_status:up再跑--cluster check。5.5 擴容加節(jié)點后槽位覆蓋不全現象新加兩個節(jié)點、遷移了部分槽過去--cluster check報Not all 16384 slots are covered但每個節(jié)點單獨看都正常。原因遷移過程中斷或者用了手工CLUSTER SETSLOT但漏了IMPORTING/MIGRATING兩步的收尾源節(jié)點把槽標成遷移中目標節(jié)點沒接管這個槽就懸空了。cluster-require-full-coverage yes下整個集群拒寫。解決用redis-cli --cluster reshard走完整流程不要手工拼SETSLOT。已經懸空的槽用CLUSTER SETSLOT slot NODE node-id在相關節(jié)點上逐一修正修完跑 check 確認All 16384 slots covered。注意以上所有涉及CLUSTER RESET、FORGET、SETSLOT的操作都有數據丟失風險先在測試環(huán)境完整走一遍再上預發(fā)。6. 把一鍵腳本用成可維護工具故障演練與巡檢的固定動作腳本能建集群只是起點。真正決定這套東西能不能長期用的是你能不能在一次執(zhí)行之后回答兩個問題故障切換要多久、下次重建要改哪幾行。我給自己的固定動作是每次部署完做一次小型故障演練把切換時間記進部署記錄后面遇到「集群是不是變慢了」這類問題時至少有基線可比。演練很簡單找到某個主節(jié)點kill -9掉它的進程然后每兩秒查一次cluster info里的cluster_state和cluster_slots_assigned同時用redis-cli -c往這個主節(jié)點負責的槽寫 key看多久恢復寫入。默認cluster-node-timeout 15000下30 秒內完成切換屬于正常超過 45 秒就要檢查是不是只有兩個主節(jié)點、投票湊不齊多數。演練完把殺掉的實例重新拉起它會以從節(jié)點身份回歸用redis-cli --cluster check確認主從關系復原。巡檢我習慣寫成一個小循環(huán)把每個節(jié)點的關鍵指標拉成一行肉眼掃一遍就知道有沒有異常#!/usr/bin/env bash # 逐節(jié)點采集關鍵狀態(tài)輸出一行一個實例便于 diff 和歸檔 PASSChangeMe_2024 for ip in 10.0.0.11 10.0.0.12 10.0.0.13; do for port in 7000 7001; do info$(redis-cli -h ${ip} -p ${port} -a ${PASS} --no-auth-warning cluster info 2/dev/null) role$(redis-cli -h ${ip} -p ${port} -a ${PASS} --no-auth-warning info replication 2/dev/null | awk -F: /^role/{print $2} | tr -d \r) state$(echo ${info} | awk -F: /^cluster_state/{print $2} | tr -d \r) assigned$(echo ${info} | awk -F: /^cluster_slots_assigned/{print $2} | tr -d \r) printf %-12s %-5s role%-6s state%-5s slots%s\n ${ip} ${port} ${role} ${state} ${assigned} done done這個腳本的價值在于輸出穩(wěn)定、可以直接 diff部署前存一份、演練后存一份cluster_slots_assigned從 16384 掉了就說明有槽懸空role變了就說明發(fā)生過切換。比翻日志快得多也不用記復雜命令。最后是一個參數化的習慣。拿到這類腳本我第一件事是把BASE_PORT、NODES、PASSWORD、DATA_ROOT四個變量抽到單獨的cluster.env里腳本開頭source進來第二件事是把生成的配置、check 輸出、演練記錄按時間戳落到logs/不做覆蓋。那次重啟后集群 fail 的經歷之后我每次改腳本都會先在一臺干凈的虛擬機上從零跑兩遍確認第二遍執(zhí)行不會因為殘留目錄報錯再看一遍nodes.conf有沒有被動過——集群這東西一次省事的rm -rf能換來一整晚的恢復工作后悔藥是沒有的。希望幫到你。本文還有配套的精品資源點擊獲取