文章目录
- Redis高可用:副本、哨兵和集群
-
- Redis 复制:高可用的基石
-
- 数据同步机制
- 复制 ID 与 偏移量
- 完全重同步 的内部流程
- 关键配置与安全注意事项
-
- 禁用主节点持久化时的风险
- 只读从节点
- 最小写入副本数
- 键的过期处理
- 常用命令
- Redis Sentinel:非集群模式下的高可用守护者
-
- Sentinel 的核心职责
- Sentinel 的分布式架构
-
- 故障检测与转移流程
- 主观下线 vs 客观下线
- 法定人数 vs 多数派
- 配置纪元
- 部署最佳实践
-
- 布局拓扑
- 避免“脑裂”与数据丢失
- 基本配置
- Redis 集群:实现数据的水平扩展与高可用
-
- 核心概念:数据分片与哈希槽
-
- 数据流转示意图
- 多键操作与 Hash Tags
- 网络架构:双端口设计
- 高可用与故障转移机制
-
- 主从模型与自动切换
- 一致性保证
- 关键配置参数
- 集群运维实战指南
-
- 创建集群
- 重分片
- 增加与删除节点
- 集群与复制、哨兵的关系
-
- 集群中的主从节点是指 Redis 副本中的主从节点吗?
- 故障自动恢复是否使用了哨兵?
- 副本、哨兵、集群这三个是否可以同时使用?
- 从其他模式迁移到集群
Redis高可用:副本、哨兵和集群
在构建 Redis 服务时,我们通常面临三个不同层级的需求:数据备份、故障自动恢复、以及海量数据存储。Redis 提供了三种核心模式来应对这些需求:主从复制、哨兵 和 集群。
- 主从复制:这是最基础的数据冗余机制。数据单向流动,从主节点复制到一个或多个从节点。它主要用于数据备份和读写分离。它的特点是简单,但主节点宕机后需要人工介入或脚本处理故障转移,无法自动恢复。
#mermaid-svg-ASXHF7ih0k7SLjSv{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ASXHF7ih0k7SLjSv .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ASXHF7ih0k7SLjSv .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ASXHF7ih0k7SLjSv .error-icon{fill:#552222;}#mermaid-svg-ASXHF7ih0k7SLjSv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ASXHF7ih0k7SLjSv .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ASXHF7ih0k7SLjSv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ASXHF7ih0k7SLjSv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ASXHF7ih0k7SLjSv .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ASXHF7ih0k7SLjSv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ASXHF7ih0k7SLjSv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ASXHF7ih0k7SLjSv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ASXHF7ih0k7SLjSv .marker.cross{stroke:#333333;}#mermaid-svg-ASXHF7ih0k7SLjSv svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ASXHF7ih0k7SLjSv p{margin:0;}#mermaid-svg-ASXHF7ih0k7SLjSv .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-ASXHF7ih0k7SLjSv .cluster-label text{fill:#333;}#mermaid-svg-ASXHF7ih0k7SLjSv .cluster-label span{color:#333;}#mermaid-svg-ASXHF7ih0k7SLjSv .cluster-label span p{background-color:transparent;}#mermaid-svg-ASXHF7ih0k7SLjSv .label text,#mermaid-svg-ASXHF7ih0k7SLjSv span{fill:#333;color:#333;}#mermaid-svg-ASXHF7ih0k7SLjSv .node rect,#mermaid-svg-ASXHF7ih0k7SLjSv .node circle,#mermaid-svg-ASXHF7ih0k7SLjSv .node ellipse,#mermaid-svg-ASXHF7ih0k7SLjSv .node polygon,#mermaid-svg-ASXHF7ih0k7SLjSv .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ASXHF7ih0k7SLjSv .rough-node .label text,#mermaid-svg-ASXHF7ih0k7SLjSv .node .label text,#mermaid-svg-ASXHF7ih0k7SLjSv .image-shape .label,#mermaid-svg-ASXHF7ih0k7SLjSv .icon-shape .label{text-anchor:middle;}#mermaid-svg-ASXHF7ih0k7SLjSv .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ASXHF7ih0k7SLjSv .rough-node .label,#mermaid-svg-ASXHF7ih0k7SLjSv .node .label,#mermaid-svg-ASXHF7ih0k7SLjSv .image-shape .label,#mermaid-svg-ASXHF7ih0k7SLjSv .icon-shape .label{text-align:center;}#mermaid-svg-ASXHF7ih0k7SLjSv .node.clickable{cursor:pointer;}#mermaid-svg-ASXHF7ih0k7SLjSv .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ASXHF7ih0k7SLjSv .arrowheadPath{fill:#333333;}#mermaid-svg-ASXHF7ih0k7SLjSv .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ASXHF7ih0k7SLjSv .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ASXHF7ih0k7SLjSv .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ASXHF7ih0k7SLjSv .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ASXHF7ih0k7SLjSv .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ASXHF7ih0k7SLjSv .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ASXHF7ih0k7SLjSv .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ASXHF7ih0k7SLjSv .cluster text{fill:#333;}#mermaid-svg-ASXHF7ih0k7SLjSv .cluster span{color:#333;}#mermaid-svg-ASXHF7ih0k7SLjSv div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ASXHF7ih0k7SLjSv .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ASXHF7ih0k7SLjSv rect.text{fill:none;stroke-width:0;}#mermaid-svg-ASXHF7ih0k7SLjSv .icon-shape,#mermaid-svg-ASXHF7ih0k7SLjSv .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ASXHF7ih0k7SLjSv .icon-shape p,#mermaid-svg-ASXHF7ih0k7SLjSv .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ASXHF7ih0k7SLjSv .icon-shape rect,#mermaid-svg-ASXHF7ih0k7SLjSv .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ASXHF7ih0k7SLjSv .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ASXHF7ih0k7SLjSv .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ASXHF7ih0k7SLjSv :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
主从复制架构
写请求
读请求
读请求
读请求
异步复制
异步复制
客户端
主节点 Master负责写
从节点 Replica 1
从节点 Replica 2
- 哨兵:哨兵是运行在特殊模式下的 Redis 进程,它监控主从复制架构。当主节点故障时,哨兵会自动投票选举从节点升级为主节点,实现高可用。它的特点是自动故障转移,系统更健壮。但数据仍在单个主节点上,内存容量受限于单机。
#mermaid-svg-MCI0Ak6GLorELYmr{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MCI0Ak6GLorELYmr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MCI0Ak6GLorELYmr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MCI0Ak6GLorELYmr .error-icon{fill:#552222;}#mermaid-svg-MCI0Ak6GLorELYmr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MCI0Ak6GLorELYmr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MCI0Ak6GLorELYmr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MCI0Ak6GLorELYmr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MCI0Ak6GLorELYmr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MCI0Ak6GLorELYmr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MCI0Ak6GLorELYmr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MCI0Ak6GLorELYmr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MCI0Ak6GLorELYmr .marker.cross{stroke:#333333;}#mermaid-svg-MCI0Ak6GLorELYmr svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MCI0Ak6GLorELYmr p{margin:0;}#mermaid-svg-MCI0Ak6GLorELYmr .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-MCI0Ak6GLorELYmr .cluster-label text{fill:#333;}#mermaid-svg-MCI0Ak6GLorELYmr .cluster-label span{color:#333;}#mermaid-svg-MCI0Ak6GLorELYmr .cluster-label span p{background-color:transparent;}#mermaid-svg-MCI0Ak6GLorELYmr .label text,#mermaid-svg-MCI0Ak6GLorELYmr span{fill:#333;color:#333;}#mermaid-svg-MCI0Ak6GLorELYmr .node rect,#mermaid-svg-MCI0Ak6GLorELYmr .node circle,#mermaid-svg-MCI0Ak6GLorELYmr .node ellipse,#mermaid-svg-MCI0Ak6GLorELYmr .node polygon,#mermaid-svg-MCI0Ak6GLorELYmr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-MCI0Ak6GLorELYmr .rough-node .label text,#mermaid-svg-MCI0Ak6GLorELYmr .node .label text,#mermaid-svg-MCI0Ak6GLorELYmr .image-shape .label,#mermaid-svg-MCI0Ak6GLorELYmr .icon-shape .label{text-anchor:middle;}#mermaid-svg-MCI0Ak6GLorELYmr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-MCI0Ak6GLorELYmr .rough-node .label,#mermaid-svg-MCI0Ak6GLorELYmr .node .label,#mermaid-svg-MCI0Ak6GLorELYmr .image-shape .label,#mermaid-svg-MCI0Ak6GLorELYmr .icon-shape .label{text-align:center;}#mermaid-svg-MCI0Ak6GLorELYmr .node.clickable{cursor:pointer;}#mermaid-svg-MCI0Ak6GLorELYmr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-MCI0Ak6GLorELYmr .arrowheadPath{fill:#333333;}#mermaid-svg-MCI0Ak6GLorELYmr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-MCI0Ak6GLorELYmr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-MCI0Ak6GLorELYmr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MCI0Ak6GLorELYmr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-MCI0Ak6GLorELYmr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MCI0Ak6GLorELYmr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-MCI0Ak6GLorELYmr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-MCI0Ak6GLorELYmr .cluster text{fill:#333;}#mermaid-svg-MCI0Ak6GLorELYmr .cluster span{color:#333;}#mermaid-svg-MCI0Ak6GLorELYmr div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-MCI0Ak6GLorELYmr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-MCI0Ak6GLorELYmr rect.text{fill:none;stroke-width:0;}#mermaid-svg-MCI0Ak6GLorELYmr .icon-shape,#mermaid-svg-MCI0Ak6GLorELYmr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MCI0Ak6GLorELYmr .icon-shape p,#mermaid-svg-MCI0Ak6GLorELYmr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-MCI0Ak6GLorELYmr .icon-shape rect,#mermaid-svg-MCI0Ak6GLorELYmr .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MCI0Ak6GLorELYmr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-MCI0Ak6GLorELYmr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-MCI0Ak6GLorELYmr :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
数据层 主从
哨兵监控层
监控
监控
监控
哨兵节点 1
哨兵节点 2
哨兵节点 3
主节点 Master
升为新主
从节点 Replica
故障时: 哨兵协商
- 集群:集群是 Redis 的分布式解决方案。它将数据自动分片存储在多个主节点中,每个主节点都有从节点。它解决了单机内存限制和网络瓶颈问题。它的特点是自动分片、高可用、水平扩展。适用于海量数据和高并发场景,但客户端逻辑较复杂,且不支持跨节点的多键操作(如 Multi-key)。
#mermaid-svg-cym1hXhfY2q0foAS{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cym1hXhfY2q0foAS .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cym1hXhfY2q0foAS .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cym1hXhfY2q0foAS .error-icon{fill:#552222;}#mermaid-svg-cym1hXhfY2q0foAS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cym1hXhfY2q0foAS .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cym1hXhfY2q0foAS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cym1hXhfY2q0foAS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cym1hXhfY2q0foAS .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cym1hXhfY2q0foAS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cym1hXhfY2q0foAS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cym1hXhfY2q0foAS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cym1hXhfY2q0foAS .marker.cross{stroke:#333333;}#mermaid-svg-cym1hXhfY2q0foAS svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cym1hXhfY2q0foAS p{margin:0;}#mermaid-svg-cym1hXhfY2q0foAS .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-cym1hXhfY2q0foAS .cluster-label text{fill:#333;}#mermaid-svg-cym1hXhfY2q0foAS .cluster-label span{color:#333;}#mermaid-svg-cym1hXhfY2q0foAS .cluster-label span p{background-color:transparent;}#mermaid-svg-cym1hXhfY2q0foAS .label text,#mermaid-svg-cym1hXhfY2q0foAS span{fill:#333;color:#333;}#mermaid-svg-cym1hXhfY2q0foAS .node rect,#mermaid-svg-cym1hXhfY2q0foAS .node circle,#mermaid-svg-cym1hXhfY2q0foAS .node ellipse,#mermaid-svg-cym1hXhfY2q0foAS .node polygon,#mermaid-svg-cym1hXhfY2q0foAS .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cym1hXhfY2q0foAS .rough-node .label text,#mermaid-svg-cym1hXhfY2q0foAS .node .label text,#mermaid-svg-cym1hXhfY2q0foAS .image-shape .label,#mermaid-svg-cym1hXhfY2q0foAS .icon-shape .label{text-anchor:middle;}#mermaid-svg-cym1hXhfY2q0foAS .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-cym1hXhfY2q0foAS .rough-node .label,#mermaid-svg-cym1hXhfY2q0foAS .node .label,#mermaid-svg-cym1hXhfY2q0foAS .image-shape .label,#mermaid-svg-cym1hXhfY2q0foAS .icon-shape .label{text-align:center;}#mermaid-svg-cym1hXhfY2q0foAS .node.clickable{cursor:pointer;}#mermaid-svg-cym1hXhfY2q0foAS .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-cym1hXhfY2q0foAS .arrowheadPath{fill:#333333;}#mermaid-svg-cym1hXhfY2q0foAS .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cym1hXhfY2q0foAS .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cym1hXhfY2q0foAS .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cym1hXhfY2q0foAS .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-cym1hXhfY2q0foAS .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cym1hXhfY2q0foAS .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-cym1hXhfY2q0foAS .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cym1hXhfY2q0foAS .cluster text{fill:#333;}#mermaid-svg-cym1hXhfY2q0foAS .cluster span{color:#333;}#mermaid-svg-cym1hXhfY2q0foAS div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cym1hXhfY2q0foAS .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-cym1hXhfY2q0foAS rect.text{fill:none;stroke-width:0;}#mermaid-svg-cym1hXhfY2q0foAS .icon-shape,#mermaid-svg-cym1hXhfY2q0foAS .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cym1hXhfY2q0foAS .icon-shape p,#mermaid-svg-cym1hXhfY2q0foAS .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-cym1hXhfY2q0foAS .icon-shape rect,#mermaid-svg-cym1hXhfY2q0foAS .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cym1hXhfY2q0foAS .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-cym1hXhfY2q0foAS .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-cym1hXhfY2q0foAS :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
集群分片架构
Slot 10001-16383
Slot 5001-10000
Slot 0-5000
路由请求
路由请求
路由请求
主节点 A
从节点 A'
主节点 B
从节点 B'
主节点 C
从节点 C'
客户端
| 核心目标 | 数据冗余、读写分离 | 自动故障转移 (高可用) | 数据分片、水平扩展 (高并发+大容量) |
| 数据分片 | 否,所有数据都在主节点 | 否,所有数据都在主节点 | 是,数据分散在多个主节点 |
| 在线扩容 | 手动添加从节点,不增加容量 | 手动添加节点,不增加容量 | 支持动态添加节点并重新分片 |
| 故障转移 | 需要人工介入或脚本 | 自动化 (Sentinel 选举) | 自动化 (节点间通信投票) |
| 运维复杂度 | 低 | 中 | 较高 |
| 客户端支持 | 所有客户端均支持 | 大多数客户端支持 | 需支持 Cluster 协议的客户端 |
| 网络分区容忍 | 主节点宕机不可写 | 少数 Sentinel 存活即可工作 | 多数 Master 存活即可工作 (需注意脑裂) |
| 多键操作 | 支持 | 支持 | 仅当 key 在同一 slot 时支持 (使用 Hash Tag 解决) |
Redis 复制:高可用的基石
Redis 的复制机制是实现数据备份、读取扩展和高可用性的基础。在最底层,它采用的是主从复制 模式。这种模式简单易用,允许一个或多个从节点成为主节点的精确副本。 无论主节点发生什么情况,从节点都会尝试自动重连并与其保持一致。
数据同步机制
Redis主要依赖以下三种机制来维持数据同步:
#mermaid-svg-WCw9v4wO6lHYTRY3{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-WCw9v4wO6lHYTRY3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WCw9v4wO6lHYTRY3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WCw9v4wO6lHYTRY3 .error-icon{fill:#552222;}#mermaid-svg-WCw9v4wO6lHYTRY3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WCw9v4wO6lHYTRY3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WCw9v4wO6lHYTRY3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WCw9v4wO6lHYTRY3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WCw9v4wO6lHYTRY3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WCw9v4wO6lHYTRY3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WCw9v4wO6lHYTRY3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WCw9v4wO6lHYTRY3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WCw9v4wO6lHYTRY3 .marker.cross{stroke:#333333;}#mermaid-svg-WCw9v4wO6lHYTRY3 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WCw9v4wO6lHYTRY3 p{margin:0;}#mermaid-svg-WCw9v4wO6lHYTRY3 defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-WCw9v4wO6lHYTRY3 g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-WCw9v4wO6lHYTRY3 g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-WCw9v4wO6lHYTRY3 g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-WCw9v4wO6lHYTRY3 g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-WCw9v4wO6lHYTRY3 g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-WCw9v4wO6lHYTRY3 .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-WCw9v4wO6lHYTRY3 .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-WCw9v4wO6lHYTRY3 .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-WCw9v4wO6lHYTRY3 .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-WCw9v4wO6lHYTRY3 .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-WCw9v4wO6lHYTRY3 .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-WCw9v4wO6lHYTRY3 .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-WCw9v4wO6lHYTRY3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WCw9v4wO6lHYTRY3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WCw9v4wO6lHYTRY3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WCw9v4wO6lHYTRY3 .edgeLabel .label text{fill:#333;}#mermaid-svg-WCw9v4wO6lHYTRY3 .label div .edgeLabel{color:#333;}#mermaid-svg-WCw9v4wO6lHYTRY3 .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-WCw9v4wO6lHYTRY3 .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-WCw9v4wO6lHYTRY3 .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-WCw9v4wO6lHYTRY3 .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-WCw9v4wO6lHYTRY3 .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-WCw9v4wO6lHYTRY3 .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WCw9v4wO6lHYTRY3 .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WCw9v4wO6lHYTRY3 #statediagram-barbEnd{fill:#333333;}#mermaid-svg-WCw9v4wO6lHYTRY3 .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WCw9v4wO6lHYTRY3 .cluster-label,#mermaid-svg-WCw9v4wO6lHYTRY3 .nodeLabel{color:#131300;}#mermaid-svg-WCw9v4wO6lHYTRY3 .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-WCw9v4wO6lHYTRY3 .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-WCw9v4wO6lHYTRY3 .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-WCw9v4wO6lHYTRY3 .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-WCw9v4wO6lHYTRY3 .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-WCw9v4wO6lHYTRY3 .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-WCw9v4wO6lHYTRY3 .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-WCw9v4wO6lHYTRY3 .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-WCw9v4wO6lHYTRY3 .note-edge{stroke-dasharray:5;}#mermaid-svg-WCw9v4wO6lHYTRY3 .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-WCw9v4wO6lHYTRY3 .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-WCw9v4wO6lHYTRY3 .statediagram-note text{fill:black;}#mermaid-svg-WCw9v4wO6lHYTRY3 .statediagram-note .nodeLabel{color:black;}#mermaid-svg-WCw9v4wO6lHYTRY3 .statediagram .edgeLabel{color:red;}#mermaid-svg-WCw9v4wO6lHYTRY3 #dependencyStart,#mermaid-svg-WCw9v4wO6lHYTRY3 #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-WCw9v4wO6lHYTRY3 .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WCw9v4wO6lHYTRY3 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
接收命令流
网络故障/超时
重连成功且增量在缓冲区
增量丢失或 ID 不匹配
补齐缺失数据
加载 RDB 及缓冲数据
连接建立
命令传播
链路断开
部分重同步
完全重同步
主节点持续发送写命令给从节点保持数据一致
复制 ID 与 偏移量
为了判断两个实例的数据是否一致,Redis 使用了两个概念:
- 复制 ID:一个标记数据集特定历史的大型伪随机字符串。
- 偏移量:一个随着处理复制流而不断递增的数字。
如果两个实例拥有相同的 复制 ID 和 偏移量,它们的数据就是完全一致的。此外, Redis 实例实际上维护两个 ID:主 ID 和辅助 ID。这是为了处理故障转移 场景:
- 当一个从节点被提升为主节点时,它会生成一个新的主 ID(开启新的历史)。
- 同时,它将旧的主 ID 记为辅助 ID。
- 作用:其他旧的从节点重连时,可以凭借辅助 ID 和偏移量进行“部分重同步”,而不必进行昂贵的“完全重同步”。这避免了网络分区导致旧主节点恢复时的 ID 冲突。
完全重同步 的内部流程
当需要进行完全同步时,Redis 会执行以下步骤。这是一个巧妙的后台处理过程,旨在不阻塞主线程:
从节点
磁盘
主节点 (子进程)
主节点 (父进程)
客户端
从节点
磁盘
主节点 (子进程)
主节点 (父进程)
客户端
#mermaid-svg-LYPW2hXRjCPVgAlf{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LYPW2hXRjCPVgAlf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LYPW2hXRjCPVgAlf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LYPW2hXRjCPVgAlf .error-icon{fill:#552222;}#mermaid-svg-LYPW2hXRjCPVgAlf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LYPW2hXRjCPVgAlf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LYPW2hXRjCPVgAlf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LYPW2hXRjCPVgAlf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LYPW2hXRjCPVgAlf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LYPW2hXRjCPVgAlf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LYPW2hXRjCPVgAlf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LYPW2hXRjCPVgAlf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LYPW2hXRjCPVgAlf .marker.cross{stroke:#333333;}#mermaid-svg-LYPW2hXRjCPVgAlf svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LYPW2hXRjCPVgAlf p{margin:0;}#mermaid-svg-LYPW2hXRjCPVgAlf .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-LYPW2hXRjCPVgAlf text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-LYPW2hXRjCPVgAlf .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-LYPW2hXRjCPVgAlf .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-LYPW2hXRjCPVgAlf .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-LYPW2hXRjCPVgAlf .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-LYPW2hXRjCPVgAlf #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-LYPW2hXRjCPVgAlf .sequenceNumber{fill:white;}#mermaid-svg-LYPW2hXRjCPVgAlf #sequencenumber{fill:#333;}#mermaid-svg-LYPW2hXRjCPVgAlf #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-LYPW2hXRjCPVgAlf .messageText{fill:#333;stroke:none;}#mermaid-svg-LYPW2hXRjCPVgAlf .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-LYPW2hXRjCPVgAlf .labelText,#mermaid-svg-LYPW2hXRjCPVgAlf .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-LYPW2hXRjCPVgAlf .loopText,#mermaid-svg-LYPW2hXRjCPVgAlf .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-LYPW2hXRjCPVgAlf .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-LYPW2hXRjCPVgAlf .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-LYPW2hXRjCPVgAlf .noteText,#mermaid-svg-LYPW2hXRjCPVgAlf .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-LYPW2hXRjCPVgAlf .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-LYPW2hXRjCPVgAlf .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-LYPW2hXRjCPVgAlf .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-LYPW2hXRjCPVgAlf .actorPopupMenu{position:absolute;}#mermaid-svg-LYPW2hXRjCPVgAlf .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-LYPW2hXRjCPVgAlf .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-LYPW2hXRjCPVgAlf .actor-man circle,#mermaid-svg-LYPW2hXRjCPVgAlf line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-LYPW2hXRjCPVgAlf :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
触发 BGSAVE
此时从节点状态与主节点一致
写入新数据
缓存写命令到内存缓冲区
Fork() 创建子进程
生成 RDB 快照文件
继续处理请求
快照完成
通知完成
发送 RDB 文件
保存 RDB 到本地
加载 RDB 到内存
发送缓冲区的增量命令
- 无盘复制:如果磁盘 IO 是瓶颈,可以配置 repl-diskless-sync。子进程直接通过网络将 RDB 发送给从节点,跳过磁盘存储,提高同步速度。
关键配置与安全注意事项
禁用主节点持久化时的风险
这是一个非常重要的安全警告。如果在复制配置中,主节点关闭了持久化(RDB/AOF),并且配置了自动重启,可能会导致数据彻底丢失。为了数据安全,强烈建议在主节点和从节点上都开启持久化。如果必须关闭主节点持久化,则绝不要配置自动重启。
#mermaid-svg-NUjHuyGzgDJXT6mA{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-NUjHuyGzgDJXT6mA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-NUjHuyGzgDJXT6mA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-NUjHuyGzgDJXT6mA .error-icon{fill:#552222;}#mermaid-svg-NUjHuyGzgDJXT6mA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-NUjHuyGzgDJXT6mA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-NUjHuyGzgDJXT6mA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-NUjHuyGzgDJXT6mA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-NUjHuyGzgDJXT6mA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-NUjHuyGzgDJXT6mA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-NUjHuyGzgDJXT6mA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-NUjHuyGzgDJXT6mA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-NUjHuyGzgDJXT6mA .marker.cross{stroke:#333333;}#mermaid-svg-NUjHuyGzgDJXT6mA svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-NUjHuyGzgDJXT6mA p{margin:0;}#mermaid-svg-NUjHuyGzgDJXT6mA .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-NUjHuyGzgDJXT6mA .cluster-label text{fill:#333;}#mermaid-svg-NUjHuyGzgDJXT6mA .cluster-label span{color:#333;}#mermaid-svg-NUjHuyGzgDJXT6mA .cluster-label span p{background-color:transparent;}#mermaid-svg-NUjHuyGzgDJXT6mA .label text,#mermaid-svg-NUjHuyGzgDJXT6mA span{fill:#333;color:#333;}#mermaid-svg-NUjHuyGzgDJXT6mA .node rect,#mermaid-svg-NUjHuyGzgDJXT6mA .node circle,#mermaid-svg-NUjHuyGzgDJXT6mA .node ellipse,#mermaid-svg-NUjHuyGzgDJXT6mA .node polygon,#mermaid-svg-NUjHuyGzgDJXT6mA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-NUjHuyGzgDJXT6mA .rough-node .label text,#mermaid-svg-NUjHuyGzgDJXT6mA .node .label text,#mermaid-svg-NUjHuyGzgDJXT6mA .image-shape .label,#mermaid-svg-NUjHuyGzgDJXT6mA .icon-shape .label{text-anchor:middle;}#mermaid-svg-NUjHuyGzgDJXT6mA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-NUjHuyGzgDJXT6mA .rough-node .label,#mermaid-svg-NUjHuyGzgDJXT6mA .node .label,#mermaid-svg-NUjHuyGzgDJXT6mA .image-shape .label,#mermaid-svg-NUjHuyGzgDJXT6mA .icon-shape .label{text-align:center;}#mermaid-svg-NUjHuyGzgDJXT6mA .node.clickable{cursor:pointer;}#mermaid-svg-NUjHuyGzgDJXT6mA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-NUjHuyGzgDJXT6mA .arrowheadPath{fill:#333333;}#mermaid-svg-NUjHuyGzgDJXT6mA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-NUjHuyGzgDJXT6mA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-NUjHuyGzgDJXT6mA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NUjHuyGzgDJXT6mA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-NUjHuyGzgDJXT6mA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NUjHuyGzgDJXT6mA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-NUjHuyGzgDJXT6mA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-NUjHuyGzgDJXT6mA .cluster text{fill:#333;}#mermaid-svg-NUjHuyGzgDJXT6mA .cluster span{color:#333;}#mermaid-svg-NUjHuyGzgDJXT6mA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-NUjHuyGzgDJXT6mA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-NUjHuyGzgDJXT6mA rect.text{fill:none;stroke-width:0;}#mermaid-svg-NUjHuyGzgDJXT6mA .icon-shape,#mermaid-svg-NUjHuyGzgDJXT6mA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NUjHuyGzgDJXT6mA .icon-shape p,#mermaid-svg-NUjHuyGzgDJXT6mA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-NUjHuyGzgDJXT6mA .icon-shape rect,#mermaid-svg-NUjHuyGzgDJXT6mA .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NUjHuyGzgDJXT6mA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-NUjHuyGzgDJXT6mA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-NUjHuyGzgDJXT6mA :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
灾难发生
初始状态
崩溃
自动重启数据为空
同步
同步
主 A无持久化
从 B – 空
从 C – 空
X
主 A – 空
只读从节点
默认情况下,从节点是只读的(replica-read-only yes)。这是为了防止误操作导致主从不一致。
- 可写从节点:虽然 Redis 允许配置从节点可写,但这是不推荐的。
- 写入的数据是临时的,同步后会被覆盖。
- 写入不会被传播给下级的从节点(级联复制场景)。
- 一旦从节点提升为主节点,这些临时数据可能会引发混乱。
- 建议:如果需要在从节点上计算数据,使用 SORT_RO、EVAL_RO 等只读命令,而不是写入临时键。
最小写入副本数
为了增强数据安全性,您可以配置主节点:只有当至少 N 个从节点连接成功且延迟小于 M 秒时,才接受写操作。
相关配置参数:
- min-replicas-to-write <数量>
- min-replicas-max-lag <秒数>
这是一种“尽力而为”的数据安全机制,虽然不能保证强一致性(因为复制是异步的),但能将数据丢失的时间窗口限制在几秒钟内。
键的过期处理
Redis 复制中,键的过期是由主节点驱动的:
常用命令
| INFO replication | 查看复制状态、连接的从节点、偏移量等。 |
| ROLE | 查看实例角色(master/replica)及其详细复制信息。 |
| replicaof <ip> <port> | 将当前实例配置为指定地址的从节点。 |
| WAIT <replicas> <timeout> | 阻塞当前客户端,直到写操作被指定数量的从节点确认(伪同步)。 |
| masterauth <password> | 设置从节点连接主节点所需的密码。 |
Redis Sentinel:非集群模式下的高可用守护者
在上一节中,我们了解了 Redis 如何通过主从复制 来实现数据备份和读写分离。但是,单纯的主从复制有一个致命的弱点:主节点故障无法自动恢复。如果主节点宕机,从节点虽然拥有数据,但不会自动升级为主节点,除非有人工介入。 这就是 Redis Sentinel 登场的时刻。Sentinel 是 Redis 的高可用解决方案,它运行在特殊的模式下,负责监控、通知和自动故障转移。
Sentinel 的核心职责
Sentinel 不仅仅是一个简单的监控工具,它是一个完整的分布式系统,主要承担以下四个职责:
Sentinel 的分布式架构
Sentinel 本身被设计为一个分布式系统。这意味着您不能只运行一个 Sentinel 进程,否则 Sentinel 本身就成了单点故障。 为了实现高可用,您需要运行多个 Sentinel 进程协同工作。它们之间通过Gossip协议进行通信。
故障检测与转移流程
理解 Sentinel 的关键是区分主观下线 和 客观下线,以及法定人数 与 多数派 的概念。 下图展示了从主节点故障到完成故障转移的完整过程:
客户端
从节点 R
Sentinel 3
Sentinel 2
Sentinel 1
主节点 M
客户端
从节点 R
Sentinel 3
Sentinel 2
Sentinel 1
主节点 M
#mermaid-svg-KWUm6Hho07hVws0V{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KWUm6Hho07hVws0V .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KWUm6Hho07hVws0V .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KWUm6Hho07hVws0V .error-icon{fill:#552222;}#mermaid-svg-KWUm6Hho07hVws0V .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KWUm6Hho07hVws0V .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KWUm6Hho07hVws0V .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KWUm6Hho07hVws0V .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KWUm6Hho07hVws0V .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KWUm6Hho07hVws0V .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KWUm6Hho07hVws0V .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KWUm6Hho07hVws0V .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KWUm6Hho07hVws0V .marker.cross{stroke:#333333;}#mermaid-svg-KWUm6Hho07hVws0V svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KWUm6Hho07hVws0V p{margin:0;}#mermaid-svg-KWUm6Hho07hVws0V .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-KWUm6Hho07hVws0V text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-KWUm6Hho07hVws0V .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-KWUm6Hho07hVws0V .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-KWUm6Hho07hVws0V .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-KWUm6Hho07hVws0V .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-KWUm6Hho07hVws0V #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-KWUm6Hho07hVws0V .sequenceNumber{fill:white;}#mermaid-svg-KWUm6Hho07hVws0V #sequencenumber{fill:#333;}#mermaid-svg-KWUm6Hho07hVws0V #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-KWUm6Hho07hVws0V .messageText{fill:#333;stroke:none;}#mermaid-svg-KWUm6Hho07hVws0V .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-KWUm6Hho07hVws0V .labelText,#mermaid-svg-KWUm6Hho07hVws0V .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-KWUm6Hho07hVws0V .loopText,#mermaid-svg-KWUm6Hho07hVws0V .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-KWUm6Hho07hVws0V .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-KWUm6Hho07hVws0V .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-KWUm6Hho07hVws0V .noteText,#mermaid-svg-KWUm6Hho07hVws0V .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-KWUm6Hho07hVws0V .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-KWUm6Hho07hVws0V .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-KWUm6Hho07hVws0V .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-KWUm6Hho07hVws0V .actorPopupMenu{position:absolute;}#mermaid-svg-KWUm6Hho07hVws0V .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-KWUm6Hho07hVws0V .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-KWUm6Hho07hVws0V .actor-man circle,#mermaid-svg-KWUm6Hho07hVws0V line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-KWUm6Hho07hVws0V :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
主节点宕机
选举阶段
连接断开
1
连接断开
2
超时未响应 (SDOWN)
3
超时未响应 (SDOWN)
4
确认主节点状态?
5
确认下线 (ODOWN
达到法定人数)
6
投票请求 (我负责故障转移)
7
投票同意
8
投票请求
9
投票同意
10
SLAVEOF NO ONE
(升级为主节点)
11
断开旧主连接
12
确认已升级
13
广播新配置 (Epoch +1)
14
广播新配置 (Epoch +1)
15
询问主节点地址?
16
返回新主节点地址
17
主观下线 vs 客观下线
- SDOWN (Subjective Down):这是一个局部状态。单个 Sentinel 发现某个实例在 down-after-milliseconds 毫秒内没有回复 PING,就认为它主观下线了。
- ODOWN (Objective Down):这是一个全局状态。当足够数量的 Sentinel(达到配置的 quorum)都认为主节点是 SDOWN 时,主节点被标记为 ODOWN。
- 注意:只有主节点会被标记为 ODOWN。从节点或 Sentinel 故障通常不需要触发复杂的故障转移逻辑。
法定人数 vs 多数派
这两个参数决定了系统的敏感度和安全性,也是容易混淆的地方:
- Quorum (法定人数):在 sentinel monitor <master-name> <ip> <port> <quorum> 中配置。
- 作用:标记主节点为 ODOWN。
- 例子:如果有 5 个 Sentinel,Quorum 设为 2。只要有 2 个 Sentinel 认为主节点挂了,主节点就会被标记为 ODOWN。
- Majority (多数派):Sentinel 总数的一半 + 1。
- 作用:授权执行故障转移。
- 规则:即使主节点已经被标记为 ODOWN,Sentinel 依然必须获得多数派 的授权才能真正开始执行 slaveof no one 等操作。
安全机制:这防止了“脑裂”。即使网络分区导致少数派 Sentinel 认为主节点挂了,它们无法获得多数派授权,因此不会启动故障转移。
配置纪元
这是 Sentinel 的版本号机制。每次成功进行故障转移,配置纪元 就会 +1。
- 当 Sentinel 广播新的配置(主节点变更)时,会附带这个纪元号。
- 纪元号大的配置被视为“更新”,会覆盖旧的配置。
- 这保证了所有 Sentinel 最终会收敛到同一个配置(最终一致性)。
部署最佳实践
为了构建一个健壮的 Sentinel 部署,请遵循以下原则:
布局拓扑
推荐的拓扑(三节点部署): 将 Sentinel 和 Redis 进程分布在三个独立的物理机或虚拟机上。
#mermaid-svg-HCdwRTxY5vJa8iN5{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-HCdwRTxY5vJa8iN5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-HCdwRTxY5vJa8iN5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-HCdwRTxY5vJa8iN5 .error-icon{fill:#552222;}#mermaid-svg-HCdwRTxY5vJa8iN5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HCdwRTxY5vJa8iN5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-HCdwRTxY5vJa8iN5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HCdwRTxY5vJa8iN5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HCdwRTxY5vJa8iN5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-HCdwRTxY5vJa8iN5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HCdwRTxY5vJa8iN5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HCdwRTxY5vJa8iN5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HCdwRTxY5vJa8iN5 .marker.cross{stroke:#333333;}#mermaid-svg-HCdwRTxY5vJa8iN5 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HCdwRTxY5vJa8iN5 p{margin:0;}#mermaid-svg-HCdwRTxY5vJa8iN5 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-HCdwRTxY5vJa8iN5 .cluster-label text{fill:#333;}#mermaid-svg-HCdwRTxY5vJa8iN5 .cluster-label span{color:#333;}#mermaid-svg-HCdwRTxY5vJa8iN5 .cluster-label span p{background-color:transparent;}#mermaid-svg-HCdwRTxY5vJa8iN5 .label text,#mermaid-svg-HCdwRTxY5vJa8iN5 span{fill:#333;color:#333;}#mermaid-svg-HCdwRTxY5vJa8iN5 .node rect,#mermaid-svg-HCdwRTxY5vJa8iN5 .node circle,#mermaid-svg-HCdwRTxY5vJa8iN5 .node ellipse,#mermaid-svg-HCdwRTxY5vJa8iN5 .node polygon,#mermaid-svg-HCdwRTxY5vJa8iN5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-HCdwRTxY5vJa8iN5 .rough-node .label text,#mermaid-svg-HCdwRTxY5vJa8iN5 .node .label text,#mermaid-svg-HCdwRTxY5vJa8iN5 .image-shape .label,#mermaid-svg-HCdwRTxY5vJa8iN5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-HCdwRTxY5vJa8iN5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-HCdwRTxY5vJa8iN5 .rough-node .label,#mermaid-svg-HCdwRTxY5vJa8iN5 .node .label,#mermaid-svg-HCdwRTxY5vJa8iN5 .image-shape .label,#mermaid-svg-HCdwRTxY5vJa8iN5 .icon-shape .label{text-align:center;}#mermaid-svg-HCdwRTxY5vJa8iN5 .node.clickable{cursor:pointer;}#mermaid-svg-HCdwRTxY5vJa8iN5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-HCdwRTxY5vJa8iN5 .arrowheadPath{fill:#333333;}#mermaid-svg-HCdwRTxY5vJa8iN5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-HCdwRTxY5vJa8iN5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-HCdwRTxY5vJa8iN5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HCdwRTxY5vJa8iN5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-HCdwRTxY5vJa8iN5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HCdwRTxY5vJa8iN5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-HCdwRTxY5vJa8iN5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-HCdwRTxY5vJa8iN5 .cluster text{fill:#333;}#mermaid-svg-HCdwRTxY5vJa8iN5 .cluster span{color:#333;}#mermaid-svg-HCdwRTxY5vJa8iN5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-HCdwRTxY5vJa8iN5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-HCdwRTxY5vJa8iN5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-HCdwRTxY5vJa8iN5 .icon-shape,#mermaid-svg-HCdwRTxY5vJa8iN5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HCdwRTxY5vJa8iN5 .icon-shape p,#mermaid-svg-HCdwRTxY5vJa8iN5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-HCdwRTxY5vJa8iN5 .icon-shape rect,#mermaid-svg-HCdwRTxY5vJa8iN5 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HCdwRTxY5vJa8iN5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-HCdwRTxY5vJa8iN5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-HCdwRTxY5vJa8iN5 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
物理机 3
物理机 2
物理机 1
监控
监控
监控
Redis Master
Sentinel 1
Redis Replica 1
Sentinel 2
Redis Replica 2
Sentinel 3
关键配置:
- Quorum 设置为 2:这意味着需要至少 2 个 Sentinel 同意主节点挂了,才能触发 ODOWN。
- 优势:
- 如果物理机 1 宕机(M1 和 S1 挂了),剩下的 S2 和 S3 依然构成多数派(2/3),可以授权 S2 或 S3 进行故障转移。
- 客户端连接到剩下的 S2/S3 依然可以获取新主节点信息。
避免“脑裂”与数据丢失
由于 Redis 复制是异步的,在网络分区发生时,旧的主节点可能仍然接受写入,而新的主节点已经产生。当分区恢复时,旧主节点会被重新配置为从节点,导致其上的写入数据丢失。
缓解措施: 在 Redis 配置中启用 min-replicas-to-write:
min-replicas-to-write 1
min-replicas-max-lag 10
这意味着:主节点必须至少能写入 1 个从节点,否则拒绝写请求。在网络分区发生时,旧主节点会迅速失去连接,从而停止接受写入,大大减少数据丢失窗口。
基本配置
一个最小的 sentinel.conf 示例:
# 监控名为 mymaster 的主节点,IP 127.0.0.1,端口 6379,法定人数为 2
sentinel monitor mymaster 127.0.0.1 6379 2
# 30秒内无响应视为主观下线
sentinel down-after-milliseconds mymaster 30000
# 故障转移超时时间(3分钟)
sentinel failover-timeout mymaster 180000
# 故障转移时,同时有多少个从节点同步新主节点(数字越小对网络影响越小)
sentinel parallel-syncs mymaster 1
Redis 集群:实现数据的水平扩展与高可用
在之前的章节中,我们探讨了“主从复制”(数据冗余)和“哨兵”(高可用监控)。虽然这两个功能组合在一起可以提供一个非常健壮的单节点 Redis 服务,但它们受限于单机的内存大小和 CPU 性能。当数据量达到几十 TB 或者单机吞吐量成为瓶颈时,我们需要 Redis Cluster。 Redis Cluster 是 Redis 的分布式解决方案,它提供了自动分片 和 高可用 的能力。它将数据自动分割到多个节点上,从而实现水平扩展,同时内置了故障恢复机制。
核心概念:数据分片与哈希槽
Redis Cluster 不使用传统的一致性哈希,而是使用一种称为 哈希槽 的概念。
- 总槽位数:集群共有 16384 个哈希槽。
- 计算方式:每个 Key 根据其名称计算哈希值:CRC16(key) % 16384。
- 分配:这 16384 个槽位被分配给集群中的不同主节点。
数据流转示意图
下图展示了一个 Key 是如何被路由到特定节点的,以及 Key 如何在分片中工作:
#mermaid-svg-oAzYDfWF94nHTWHU{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-oAzYDfWF94nHTWHU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-oAzYDfWF94nHTWHU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-oAzYDfWF94nHTWHU .error-icon{fill:#552222;}#mermaid-svg-oAzYDfWF94nHTWHU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-oAzYDfWF94nHTWHU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-oAzYDfWF94nHTWHU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-oAzYDfWF94nHTWHU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-oAzYDfWF94nHTWHU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-oAzYDfWF94nHTWHU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-oAzYDfWF94nHTWHU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-oAzYDfWF94nHTWHU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-oAzYDfWF94nHTWHU .marker.cross{stroke:#333333;}#mermaid-svg-oAzYDfWF94nHTWHU svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-oAzYDfWF94nHTWHU p{margin:0;}#mermaid-svg-oAzYDfWF94nHTWHU .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-oAzYDfWF94nHTWHU .cluster-label text{fill:#333;}#mermaid-svg-oAzYDfWF94nHTWHU .cluster-label span{color:#333;}#mermaid-svg-oAzYDfWF94nHTWHU .cluster-label span p{background-color:transparent;}#mermaid-svg-oAzYDfWF94nHTWHU .label text,#mermaid-svg-oAzYDfWF94nHTWHU span{fill:#333;color:#333;}#mermaid-svg-oAzYDfWF94nHTWHU .node rect,#mermaid-svg-oAzYDfWF94nHTWHU .node circle,#mermaid-svg-oAzYDfWF94nHTWHU .node ellipse,#mermaid-svg-oAzYDfWF94nHTWHU .node polygon,#mermaid-svg-oAzYDfWF94nHTWHU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-oAzYDfWF94nHTWHU .rough-node .label text,#mermaid-svg-oAzYDfWF94nHTWHU .node .label text,#mermaid-svg-oAzYDfWF94nHTWHU .image-shape .label,#mermaid-svg-oAzYDfWF94nHTWHU .icon-shape .label{text-anchor:middle;}#mermaid-svg-oAzYDfWF94nHTWHU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-oAzYDfWF94nHTWHU .rough-node .label,#mermaid-svg-oAzYDfWF94nHTWHU .node .label,#mermaid-svg-oAzYDfWF94nHTWHU .image-shape .label,#mermaid-svg-oAzYDfWF94nHTWHU .icon-shape .label{text-align:center;}#mermaid-svg-oAzYDfWF94nHTWHU .node.clickable{cursor:pointer;}#mermaid-svg-oAzYDfWF94nHTWHU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-oAzYDfWF94nHTWHU .arrowheadPath{fill:#333333;}#mermaid-svg-oAzYDfWF94nHTWHU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-oAzYDfWF94nHTWHU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-oAzYDfWF94nHTWHU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-oAzYDfWF94nHTWHU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-oAzYDfWF94nHTWHU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-oAzYDfWF94nHTWHU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-oAzYDfWF94nHTWHU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-oAzYDfWF94nHTWHU .cluster text{fill:#333;}#mermaid-svg-oAzYDfWF94nHTWHU .cluster span{color:#333;}#mermaid-svg-oAzYDfWF94nHTWHU div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-oAzYDfWF94nHTWHU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-oAzYDfWF94nHTWHU rect.text{fill:none;stroke-width:0;}#mermaid-svg-oAzYDfWF94nHTWHU .icon-shape,#mermaid-svg-oAzYDfWF94nHTWHU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-oAzYDfWF94nHTWHU .icon-shape p,#mermaid-svg-oAzYDfWF94nHTWHU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-oAzYDfWF94nHTWHU .icon-shape rect,#mermaid-svg-oAzYDfWF94nHTWHU .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-oAzYDfWF94nHTWHU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-oAzYDfWF94nHTWHU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-oAzYDfWF94nHTWHU :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Redis Cluster 架构
节点与槽位映射
取模 16384
槽位 0-5000
Master-Sentinel
Master-Sentinel
Master-Sentinel
请求
重定向
返回数据
客户端
Key: user:1001
计算 CRC16
Hash Slot 1234
Master A
Slot 5001-10000
Master B
Slot 10001-16383
Master C
Replica A1
Replica B1
Replica C1
优势:
- 轻松扩容:添加新节点时,只需将一部分槽位从旧节点迁移到新节点。
- 在线迁移:数据迁移过程不需要停止服务。
多键操作与 Hash Tags
Redis Cluster 限制:涉及多个 Key 的操作(如 MGET, SUNION)必须作用在同一个槽位上。 如果需要跨键操作,可以使用 Hash Tags:
- 如果 Key 包含 {…} 这样的子字符串,只有 {} 内的内容参与哈希计算。
- 例如:user:{123}:profile 和 user:{123}:orders 会被分配到同一个槽位,因此可以一起操作。
网络架构:双端口设计
为了保证集群内部通信的高效,每个 Redis Cluster 节点需要开放两个 TCP 端口:
- 这是一个节点对节点的通信通道,使用二进制协议,带宽和处理开销更低。
- 用于故障检测、配置更新、故障转移授权等。
- 注意:客户端不应连接此端口,但防火墙必须开放此端口给其他集群节点。
高可用与故障转移机制
主从模型与自动切换
为了保持高可用,集群中的每个主节点都可以有多个从节点。故障转移流程(内置机制):
一致性保证
Redis Cluster 不保证强一致性。它是最终一致的系统,这意味着在某些故障场景下,已经确认的写入可能会丢失。原因:
- 集群被分割为两部分。
- 多数派(拥有大多数 Master)侧会继续工作,并选举新的主节点。
- 少数派(被隔离的旧 Master)侧在超过 cluster-node-timeout 时间后,会停止接受写入。
- 如果在超时之前,客户端继续向少数派的旧 Master 写入数据,这些数据在分区愈合后将丢失。
关键配置参数
在 redis.conf 中,Cluster 模式引入了以下关键参数:
- cluster-enabled <yes/no>:是否启用集群模式。
- cluster-config-file <filename>:节点状态自动保存的文件(非人工编辑)。
- cluster-node-timeout <milliseconds>:
- 节点被视为失效的超时时间。
- 也是控制分区场景下少数派何时停止写入的关键参数。
- cluster-slave-validity-factor <factor>:控制从节点在断开连接多久后不再尝试发起故障转移(0 表示总是尝试)。
- cluster-require-full-coverage <yes/no>:
- 默认为 yes:如果有一部分槽位没有被任何节点覆盖,集群停止接受写入。
- 设置为 no:即使部分槽位不可用,集群仍处理其他请求。
- cluster-allow-reads-when-down <yes/no>:是否允许在集群标记为失败(标记为 down)时,节点处理只读请求。
集群运维实战指南
创建集群
最小推荐配置是 3 主 3 从(共 6 个节点)。 使用 redis-cli 工具快速创建:
redis-cli –cluster create 127.0.0.1:7000 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 –cluster-replicas 1
- –cluster-replicas 1 表示每个主节点自动分配一个从节点。
- 命令执行后,系统会自动分配 16384 个槽位。
重分片
用于平衡数据负载。
redis-cli –cluster reshard 127.0.0.1:7000
工具会引导您:
增加与删除节点
- 启动一个配置好的空 Redis 实例(如端口 7006)。
- 执行 redis-cli –cluster add-node 127.0.0.1:7006 127.0.0.1:7000。
- 此时节点已加入,但没有槽位。需要通过 Resharding(重分片)分配槽位给它。
- 启动空实例。
- 执行 redis-cli –cluster add-node … –cluster-slave。它会自动复制给某个副本较少的主节点。
- 如果是从节点,直接用 redis-cli –cluster del-node 删除。
- 如果是主节点,必须先通过 Resharding 将其槽位全部移出,使其变空,然后才能删除。
集群与复制、哨兵的关系
集群中的主从节点是指 Redis 副本中的主从节点吗?
是的,完全一致。
Redis Cluster 中的“主节点”和“从节点”,本质就是我们在前面“主从复制”章节中介绍的同一个东西。
- 集群主节点:就是一个开启了 cluster-enabled yes 的普通 Redis 主节点,只是它还负责管理一部分哈希槽。
- 集群从节点:就是一个开启了 cluster-enabled yes 的普通 Redis 从节点。它通过标准的 PSYNC 命令从主节点同步数据。
唯一的区别在于:
- 普通复制:主节点通常只有 1 个,从节点负责备份或分担读压力。
- 集群复制:主节点有多个,每个主节点负责不同的数据(槽位),从节点跟随它对应的主节点。您可以这样理解:Cluster 就像是一个由多个“主从复制小组”组成的大联盟。
故障自动恢复是否使用了哨兵?
没有,完全独立。
Redis Cluster 不依赖 哨兵 来进行故障转移。它拥有一套完全独立的、内置的高可用机制。
- 哨兵模式:Sentinel 是运行在 Redis 外部 的独立进程,作为“监察员”监控 Redis。它通过投票和决策来发起故障转移。
- 集群模式:故障转移的逻辑集成在 Redis 节点内部。节点之间通过二进制的 Cluster Bus(集群总线)交换信息。当主节点 A 宕机,它的从节点 A1、A2 之间会通过 Gossip 协议感知,并进行内部投票,直接将 A1 提升为主节点。
关键区别:
- 如果您使用 Sentinel,您的架构里必须运行 Sentinel 进程。
- 如果您使用 Cluster,您的架构里不需要 运行 Sentinel 进程,Cluster 自己就能搞定。
副本、哨兵、集群这三个是否可以同时使用?
这是一个关于架构选型的问题。答案是:机制上可以混合,但架构上通常是互斥的。
我们要分清“机制”和“解决方案”两个层面:
- Redis 复制:这是底层机制。Cluster 本身就是建立在复制之上的,所以集群肯定用了复制。
- Sentinel vs Cluster:这是两个并列的高可用/扩展解决方案。不要混用。
为什么不建议混用 Sentinel 和 Cluster?
- 功能重复:Sentinel 管监控和故障转移,Cluster 也能管监控和故障转移。同时用就是画蛇添足。
- 逻辑冲突:Sentinel 不理解“槽位”的概念。如果 Cluster 发生了主节点切换,Sentinel 可能无法正确感知 Cluster 的拓扑状态,反之亦然。
正确的架构选择路径:
| 简单缓存 | 单机 Redis | 无 | 最基础模式。 |
| 数据安全 + 读写分离 | 主从复制 | 副本机制 | 基础模式 + 冗余备份。 |
| 自动故障恢复 (单机数据量) | 哨兵 + 主从复制 | 副本机制 + Sentinel | 哨兵作为外挂的大脑,监控主从。这是最经典的生产配置。 |
| 海量数据 (单机存不下) + 高并发 | Redis Cluster | 副本机制 + 集群逻辑 | 集群自带高可用能力,不需要 Sentinel。 |
从其他模式迁移到集群
如果您目前在使用单机或 Sentinel 模式,想要迁移到 Cluster:
网硕互联帮助中心




评论前必须登录!
注册