Redis設(shè)計與實現(xiàn)——分布式Redis
Redis Sentinel(哨兵)
Sentinel 的工作機(jī)制
-
故障檢測(Failure Detection)
-
主觀下線(Subjective Down):單個 Sentinel 實例檢測到主節(jié)點在30 秒內(nèi)無響應(yīng),標(biāo)記其為
SDOWN
。 -
客觀下線(Objective Down):當(dāng)超過
quorum
的 Sentinel 實例確認(rèn)主節(jié)點不可達(dá),標(biāo)記為ODOWN
,觸發(fā)故障轉(zhuǎn)移。
-
-
領(lǐng)導(dǎo)者選舉(Leader Election)
-
Raft 算法:Sentinel 使用類似 Raft 的算法選舉領(lǐng)頭 Sentinel(Leader),由 Leader 執(zhí)行故障轉(zhuǎn)移。
-
選舉條件:獲得多數(shù) Sentinel 實例的投票(
> N/2 + 1
,N 為 Sentinel 總數(shù));避免多個 Sentinel 同時發(fā)起故障轉(zhuǎn)移。
-
-
故障轉(zhuǎn)移(Failover)流程
-
選擇新主節(jié)點:Leader Sentinel 根據(jù)規(guī)則從從節(jié)點中選出新主節(jié)點:
優(yōu)先級(
slave-priority
配置);復(fù)制偏移量最大(數(shù)據(jù)最新);運行 ID 字典序最?。ㄗ罱K裁決條件)。 -
提升新主節(jié)點:向目標(biāo)從節(jié)點發(fā)送
SLAVEOF NO ONE
,使其成為主節(jié)點;等待新主節(jié)點確認(rèn)角色切換。 -
切換從節(jié)點復(fù)制關(guān)系:向其他從節(jié)點發(fā)送
SLAVEOF
命令,使其復(fù)制新主節(jié)點。 -
更新配置:Sentinel 更新監(jiān)控的主節(jié)點地址,并通知客戶端。
-
-
客戶端服務(wù)發(fā)現(xiàn)
-
連接流程:客戶端向 Sentinel 查詢當(dāng)前主節(jié)點地址;客戶端直接連接主節(jié)點,失敗時重試查詢。
-
SDK 支持:主流 Redis 客戶端庫(如 Jedis、Lettuce)內(nèi)置 Sentinel 集成。
-
Sentinel 的架構(gòu)與部署
-
Sentinel 部署模式
-
推薦配置:至少部署 3 個 Sentinel 實例(奇數(shù)個,避免腦裂),分布在獨立物理節(jié)點。
-
網(wǎng)絡(luò)拓?fù)?/strong>:Sentinel 實例與 Redis 節(jié)點部署在同一網(wǎng)絡(luò),避免分區(qū)誤判;Sentinel 之間通過 Gossip 協(xié)議通信,共享節(jié)點狀態(tài)。
-
-
Sentinel 與 Redis 節(jié)點的關(guān)系
-
監(jiān)控對象:每個 Sentinel 監(jiān)控 一個主節(jié)點及其所有從節(jié)點。
-
自動發(fā)現(xiàn):Sentinel 通過主節(jié)點獲取從節(jié)點列表,并持續(xù)監(jiān)控其狀態(tài)。
-
Sentinel 的優(yōu)缺點
-
優(yōu)點
-
自動化容災(zāi):無需人工干預(yù)即可完成故障轉(zhuǎn)移。
-
高可用:Sentinel 自身多實例部署,避免單點故障。
-
客戶端透明:客戶端通過 Sentinel 自動發(fā)現(xiàn)主節(jié)點,業(yè)務(wù)代碼無需硬編碼地址。
-
-
缺點
-
數(shù)據(jù)一致性:異步復(fù)制可能導(dǎo)致故障轉(zhuǎn)移后數(shù)據(jù)丟失(已提交但未同步到從節(jié)點的數(shù)據(jù))。
-
復(fù)雜度:需部署多個 Sentinel 實例,配置和維護(hù)成本較高。
-
腦裂風(fēng)險:網(wǎng)絡(luò)分區(qū)可能導(dǎo)致多個主節(jié)點并存(需合理配置
quorum
和節(jié)點分布)。
-
生產(chǎn)環(huán)境建議
-
部署最佳實踐
-
Sentinel 數(shù)量:至少 3 個實例,部署在獨立物理節(jié)點或可用區(qū)。
-
網(wǎng)絡(luò)優(yōu)化:確保 Sentinel 與 Redis 節(jié)點間低延遲通信,避免跨地域部署。
-
監(jiān)控告警:監(jiān)控 Sentinel 日志和
INFO Sentinel
輸出,關(guān)注odown
事件和故障轉(zhuǎn)移次數(shù)。
-
-
避免腦裂的配置
-
合理設(shè)置quorum:通常設(shè)為
N/2 + 1
(N 為 Sentinel 總數(shù))。 -
調(diào)整min-slaves-to-write:主節(jié)點需至少同步到指定數(shù)量的從節(jié)點才接受寫操作。
-
-
客戶端容錯
-
重試策略:客戶端應(yīng)實現(xiàn)重試邏輯,處理故障轉(zhuǎn)移期間的短暫不可用。
-
多語言 SDK:選擇支持 Sentinel 的客戶端庫(如 Java 的 Jedis、Python 的 redis-py)。
-
常用命令
- SENTINEL masters:查看主節(jié)點信息。
- SENTINEL slaves {master}:查看從節(jié)點信息。
- SENTINEL failover {master}:強(qiáng)制觸發(fā)故障轉(zhuǎn)移(無需ODOWN)。
- SENTINEL sentinels {master}:查看 Sentinel 節(jié)點列表。
Redis集群
集群的架構(gòu)與數(shù)據(jù)分片
-
哈希槽(Hash Slot)分配
-
分片規(guī)則:對鍵的
CRC16
值取模(CRC16(key) % 16384
)確定所屬槽位。 -
哈希標(biāo)簽(Hash Tag):使用
{}
指定部分鍵名計算哈希值,強(qiáng)制相關(guān)鍵分配到同一槽。 -
槽分配管理:集群啟動時,槽均勻分配到主節(jié)點,可通過
CLUSTER ADDSLOTS
手動分配或自動平衡。
-
-
節(jié)點角色
-
主節(jié)點(Master):負(fù)責(zé)處理槽的讀寫請求,參與故障選舉。
-
從節(jié)點(Replica):復(fù)制主節(jié)點數(shù)據(jù),主節(jié)點故障時接替其槽。
-
集群模式節(jié)點:所有節(jié)點默認(rèn)開啟集群模式(
cluster-enabled yes
)。
-
-
集群拓?fù)?/strong>
-
最小部署:至少 3 個主節(jié)點(每個主節(jié)點至少 1 個從節(jié)點),共 6 個節(jié)點。
-
節(jié)點發(fā)現(xiàn):節(jié)點通過 Gossip 協(xié)議交換狀態(tài)信息(如
MEET
命令將節(jié)點加入集群)。
-
集群的工作機(jī)制
-
客戶端請求路由
-
Smart Client:客戶端緩存槽與節(jié)點的映射關(guān)系,直接向目標(biāo)節(jié)點發(fā)送請求,若節(jié)點返回
MOVED
重定向錯誤,更新緩存并重試。 -
Dumb Client:依賴代理(如 Redis Proxy)轉(zhuǎn)發(fā)請求,客戶端無需感知集群拓?fù)洹?/p>
-
-
數(shù)據(jù)讀寫流程
-
鍵存在目標(biāo)槽:直接由負(fù)責(zé)該槽的節(jié)點處理。
-
鍵不在目標(biāo)槽:返回
MOVED
錯誤,客戶端重定向到正確節(jié)點。 -
槽遷移中:返回
ASK
錯誤,客戶端臨時重定向到遷移目標(biāo)節(jié)點。
-
-
故障轉(zhuǎn)移(Failover)
-
主觀下線(PFAIL):節(jié)點 A 在
cluster-node-timeout
(默認(rèn) 15 秒)內(nèi)未收到節(jié)點 B 的響應(yīng),標(biāo)記 B 為PFAIL
。 -
客觀下線(FAIL):超過半數(shù)主節(jié)點確認(rèn)節(jié)點 B 不可達(dá),標(biāo)記為
FAIL
,觸發(fā)故障轉(zhuǎn)移。 -
從節(jié)點選舉:從節(jié)點發(fā)起選舉,獲得多數(shù)主節(jié)點投票后成為新主節(jié)點;接管原主節(jié)點的槽,并廣播更新集群配置。
-
-
數(shù)據(jù)遷移與平衡
-
手動遷移:使用
CLUSTER SETSLOT <slot> IMPORTING/MIGRATING
命令遷移槽。 -
自動平衡:通過
redis-cli --cluster rebalance
自動調(diào)整槽分布,均衡負(fù)載。
-
集群的優(yōu)缺點
-
優(yōu)點
-
水平擴(kuò)展:支持 TB 級數(shù)據(jù)和高并發(fā)訪問。
-
高可用:自動故障轉(zhuǎn)移,數(shù)據(jù)多副本存儲。
-
去中心化:無單點故障,節(jié)點自治。
-
-
缺點
-
功能限制:不支持跨槽事務(wù)、部分命令受限(如
KEYS *
)。 -
運維復(fù)雜度:需管理分片、遷移、節(jié)點擴(kuò)縮容。
-
客戶端兼容性:需使用集群感知的客戶端或代理。
-
生產(chǎn)環(huán)境建議
-
部署與配置
-
節(jié)點規(guī)劃:主節(jié)點至少 3 個,跨物理機(jī)或可用區(qū)部署,從節(jié)點數(shù) ≥ 主節(jié)點數(shù)。
-
網(wǎng)絡(luò)優(yōu)化:確保節(jié)點間低延遲通信,避免跨地域部署。
-
內(nèi)存管理:監(jiān)控節(jié)點內(nèi)存使用,避免數(shù)據(jù)傾斜導(dǎo)致單個節(jié)點過載。
-
-
數(shù)據(jù)均衡
-
預(yù)分片:設(shè)計鍵時使用哈希標(biāo)簽,確保相關(guān)數(shù)據(jù)集中。
-
定期平衡:使用
redis-cli --cluster rebalance
調(diào)整槽分布。
-
-
監(jiān)控與故障排查
-
關(guān)鍵指標(biāo):
CLUSTER INFO # 查看集群健康狀態(tài) CLUSTER NODES # 查看節(jié)點角色、槽分配、狀態(tài) INFO memory # 監(jiān)控內(nèi)存使用
-
日志分析:關(guān)注
CLUSTERDOWN
告警和節(jié)點超時事件。
-
常用集群命令
- CLUSTER NODES:查看集群節(jié)點信息。
- CLUSTER INFO:檢查集群狀態(tài)。
- CLUSTER FAILOVER:手動故障轉(zhuǎn)移(從節(jié)點執(zhí)行)。
Sentinel 與 Cluster 的對比
數(shù)據(jù)分片 | 不支持,需客戶端或代理分片。 | 內(nèi)置分片(16384 槽)。 |
高可用 | 主從復(fù)制 + 故障轉(zhuǎn)移。 | 每個分片主從復(fù)制,自動故障轉(zhuǎn)移。 |
擴(kuò)展性 | 垂直擴(kuò)展(主節(jié)點性能瓶頸)。 | 水平擴(kuò)展(支持大規(guī)模數(shù)據(jù)集和高吞吐)。 |
適用場景 | 中小規(guī)模,非分片架構(gòu)。 | 大規(guī)模數(shù)據(jù),高并發(fā)場景。 |
Redis復(fù)制
主從復(fù)制的建立流程
-
Redis 復(fù)制的建立分為 全量同步(Full Sync) 和 部分同步(Partial Sync) 兩種模式,優(yōu)先嘗試部分同步以減少資源消耗。
-
從節(jié)點初始化連接
-
命令觸發(fā):從節(jié)點執(zhí)行
SLAVEOF <master-ip> <master-port>
,開啟復(fù)制流程。 -
連接主節(jié)點:從節(jié)點向主節(jié)點發(fā)起連接,發(fā)送
PING
確認(rèn)網(wǎng)絡(luò)可達(dá)性。
-
-
身份驗證(可選):若主節(jié)點配置了
requirepass
,從節(jié)點需發(fā)送AUTH <password>
完成認(rèn)證。 -
同步數(shù)據(jù)集
-
全量同步(SYNC):
主節(jié)點生成當(dāng)前數(shù)據(jù)的 RDB 快照,通過子進(jìn)程寫入磁盤。
將 RDB 文件發(fā)送給從節(jié)點,同時緩存期間的寫命令至 復(fù)制緩沖區(qū)(Replication Buffer)。
從節(jié)點接收 RDB 并加載到內(nèi)存,再執(zhí)行緩沖區(qū)中的寫命令,追上主節(jié)點狀態(tài)。
-
部分同步(PSYNC):
從節(jié)點發(fā)送
PSYNC <replid> <offset>
,攜帶自身記錄的復(fù)制 ID 和偏移量。主節(jié)點檢查復(fù)制 ID 和偏移量是否匹配歷史記錄:
匹配:發(fā)送
+CONTINUE
,傳輸從偏移量之后的寫命令(利用 復(fù)制積壓緩沖區(qū))。不匹配:觸發(fā)全量同步(
+FULLRESYNC
)。
-
-
命令傳播(Command Propagation):同步完成后,主節(jié)點持續(xù)將寫命令發(fā)送給從節(jié)點,保持?jǐn)?shù)據(jù)一致。
復(fù)制的核心機(jī)制
-
復(fù)制ID與偏移量
-
復(fù)制ID(Replication ID):主節(jié)點的唯一標(biāo)識,每次主節(jié)點重啟或角色變更時生成新 ID。
-
偏移量(Offset):主從節(jié)點各自維護(hù)一個偏移量,記錄已復(fù)制的數(shù)據(jù)量。
-
-
復(fù)制積壓緩沖區(qū)(Replication Backlog)
-
作用:主節(jié)點維護(hù)一個固定大小的環(huán)形緩沖區(qū)(默認(rèn) 1MB),緩存最近的寫命令。
-
觸發(fā)部分同步:若從節(jié)點的偏移量在緩沖區(qū)范圍內(nèi),直接發(fā)送增量數(shù)據(jù)。
-
配置參數(shù)
repl-backlog-size 1mb # 緩沖區(qū)大小 repl-backlog-ttl 3600 # 主節(jié)點無連接時緩沖區(qū)保留時間(秒)
-
-
心跳檢測與斷線重連
-
心跳機(jī)制:主從節(jié)點定期確認(rèn)存活狀態(tài)和復(fù)制進(jìn)度;主節(jié)點超時未收到心跳(默認(rèn) 60 秒)則認(rèn)為從節(jié)點下線。
-
斷線處理:從節(jié)點重連后嘗試部分同步,失敗則觸發(fā)全量同步。
復(fù)制拓?fù)渑c高級特性
-
級聯(lián)復(fù)制(主-從-從)
-
場景:主節(jié)點連接過多從節(jié)點時,可通過級聯(lián)復(fù)制分?jǐn)倝毫Α?/p>
-
配置:將從節(jié)點(Slave A)作為另一從節(jié)點(Slave B)的主節(jié)點。
-
-
延遲副本(Lagging Replica)
-
作用:人為設(shè)置從節(jié)點延遲同步,用于誤操作恢復(fù)(需第三方工具支持)。
-
實現(xiàn):通過
slave-repl-delay
配置延遲時間(Redis 自身不原生支持,需外部控制)。
-
復(fù)制的問題與優(yōu)化
-
全量同步的資源消耗
-
問題:大數(shù)據(jù)集時生成和傳輸 RDB 文件會阻塞主節(jié)點并占用帶寬。
-
優(yōu)化:增大
repl-backlog-size
減少全量同步概率;使用無盤同步(repl-diskless-sync yes
),但需主節(jié)點內(nèi)存充足。
-
-
復(fù)制延遲
-
原因:網(wǎng)絡(luò)延遲、從節(jié)點負(fù)載過高或主節(jié)點寫入壓力大。
-
監(jiān)控:通過
INFO replication
的slave_repl_offset
與master_repl_offset
差值判斷延遲。 -
優(yōu)化:提升網(wǎng)絡(luò)帶寬,減少主從節(jié)點跨地域部署;限制主節(jié)點寫入速率(如使用管道批量寫入)。
-
-
數(shù)據(jù)不一致
-
原因:主從網(wǎng)絡(luò)中斷導(dǎo)致部分?jǐn)?shù)據(jù)未同步。
-
檢測:使用
redis-cli --slave
模擬從節(jié)點檢查數(shù)據(jù)差異。 -
修復(fù):手動觸發(fā)全量同步(
SLAVEOF NO ONE
+ 重新配置復(fù)制)。
-