Linux C/C++ 学习日记(66):Redis(七):redis的高可用性
注:该文用于个人学习记录和知识交流,如有不足,欢迎指点。
一、防止内存溢出
1.过期命令
- expire key (已经存在) timeout(s)
- pexpire key (已经存在) timeout (ms)


2. 内存配置

maxmemory <bytes>
一般设置为主机物理内存中的一半
原因:持久化时会fork一个子进程,有概率触发写时复制(COW)
3. 淘汰策略
内存超过maxmemory时触发


默认(noeviction):不会淘汰任何数据,如果往里面写数据会返回错误
淘汰的范围
volatile:设置了过期的数据
allkeys:所有的数据
淘汰的顺序:
lru:距离上次使用时间最长的淘汰
lfu:使用频次最少的淘汰
ttl:最近要过期的删除
random:随机选一个淘汰
二、持久化策略
-
1. rdb:
-
redis 配置文件 save 指令设置: save 3600 1 # 3600秒内如果超过1个key被修改则生成 RDB save 300 100 # 300秒内如果超过100个key被修改则生成 RDB save 60 10000 # 60秒内如果超过10000个key被修改则生成 RDB -

-
1.1 优缺点
优点:文件小,加载快 缺点:只能记录某个状态的rdb,宕机可能缺少部分数据 -
1.2 fork
- 子进程复制父进程的页表,共用物理内存页(设置为只读状态)。(fork进程,那一刻相当于给父进程的内存打了一个快照)
- 写时复制:父进程想要对数据修改时,触发写保护中断,从而进行物理内存的复制(设置为可读可写状态),页表指向新的物理内存,然后修改里面的数据
- fork的优势:
1. 避免物理内存的复制时间过长导致父进程长时间阻塞
2. 在发生写操作的时候,系统才会去复制物理内存
2. aof

2.1 优缺点
优点:数据可靠,丢失较少
缺点:日志会有冗余,文件大,数据恢复慢
2.2 顺序磁盘io:100ns,近似内存
2.3 落盘:
fprintf(fd,buf,size); // 用户态 (属于内存)
fflush() // 相当于write, 刷到内核高速缓冲区page cache(属于内存)
fsync(fd)// 将page cache 里面的数据刷到磁盘 (属于磁盘)

2.4 刷盘策略
always:刷盘
every_second:另开一个线程每间隔1s就刷盘
no: 不刷盘,就只是调用fflush
2.5 aof-rewrite

fork子进程,根据内存数据生成aof文件,在重写aof期间,对redis的写操作记录到重写缓存区,当重写aof结束后,附加到aof文件末尾
3. 混合持久化: aof-use-rdb-preamble

4. 补充:
4.1 假如 Redis 的 RDB 和 AOF 持久化都启用,redis 在载入数据的时候,是载入 AOF 文件?还是 RDB 文件?
我直接说答案:Redis 会优先载入 AOF 文件来恢复数据,而不是 RDB 文件。这是因为 AOF 文件通常包含了更完整的操作记录,从而能够恢复更完整的数据状态。而 RDB 文件是定时生成的数据快照,所以它可能没有记录到最后一次快照之后发生的所有更改。因此,使用 AOF 文件恢复数据可以提供更高的数据完整性。
4.2 混合持久化的 AOF 重写与普通的 AOF 重写的区别:
在不使用混合持久化的情况下,普通的 AOF 重写是通过读取当前的内存数据并记录达到这一状态所需的最少命令来减少 AOF 文件的大小的。
而混合持久化在 AOF 重写时,会首先将当前数据集以 RDB 格式快照的形式写入新 AOF 文件的开始位置,然后再追加新的写命令到文件末尾。
三、主从同步
从节点的作用
- 单点故障:主节点的磁盘损坏
- 高可用性:故障转移(搭配
1. 初次连接

2. 断连后重连及部分同步

3. 异步复制

- 复制偏移量:主 / 从节点都会维护一个
repl_offset(复制偏移量),记录自己已处理的写命令字节数,主节点通过对比从节点的偏移量,判断从节点是否跟上同步进度。- 复制积压缓冲区:主节点会维护一个环形缓冲区(默认 1MB,可通过
repl-backlog-size调整),存储最近的写命令,用于从节点断线重连时的增量同步(避免全量复制)。
优点:极致的主节点性能
- 主节点无阻塞:主节点处理完写请求后立即返回,无需等待从节点,避免了网络延迟对主节点性能的影响,这是 Redis 高性能的核心保障之一。
- 低资源消耗:主节点异步发送命令,不占用处理客户端请求的核心线程,适合读多写少的场景(从节点用于读扩展)。
缺点:存在数据丢失风险
- 主节点宕机丢数据:如果主节点在发送写命令给从节点前宕机,从节点会丢失这部分未同步的数据,因为主节点已经向客户端返回了 “成功”,但数据还没同步到从节点。
- 短暂数据不一致:从节点可能存在短暂的数据滞后(取决于网络延迟和主节点的发送频率),不适合对数据一致性要求极高的场景(如金融交易)。
| 配置项 | 作用 | 默认值 | 场景说明 |
|---|---|---|---|
repl-disable-tcp-nodelay |
是否禁用 TCP_NODELAY 选项 | no(启用 TCP_NODELAY) |
- 启用:主节点会尽快将写命令发送给从节点,减少同步延迟,但会增加网络包数量; - 禁用:主节点会攒一批命令再发送,减少网络开销,但同步延迟会增加。 |
repl-backlog-size |
复制积压缓冲区的大小 | 1mb |
缓冲区越大,从节点断线重连时能进行增量同步的概率越高(避免全量复制消耗资源),适合从节点经常断线的场景。 |
repl-timeout |
复制超时时间 | 60s |
如果从节点在该时间内未向主节点反馈复制进度,主节点会认为复制失败,标记从节点为 “下线”。 |
repl-ping-slave-period |
主节点向从节点发送 ping 包的间隔 | 10s |
主节点定期检测从节点是否存活,避免因网络波动误判从节点下线 |
4. 半同步复制
| 维度 | 异步复制 | 半同步复制 |
|---|---|---|
| 性能 | 最优,主节点无阻塞 | 略差,主节点需要等待至少一个从节点确认收到命令 |
| 数据一致性 | 最终一致,可能丢失数据 | 强一致(至少一个从节点确认收到命令后才返回客户端),丢失数据概率极低 |
| 适用场景 | 读多写少、可容忍短暂不一致的场景(如缓存、排行榜、日志) | 对数据一致性要求极高的场景(如金融交易、订单系统) |
| 开启方式 | 默认开启 |
需要手动配置: 主节点设置 从节点设置 |
四、主从切换
1. 哨兵模式

1.1 哨兵之间的连接
哨兵之间的互相发现和连接主要基于 Redis 的发布与订阅机制:
当哨兵启动并监控主节点时,它会订阅主节点的
__sentinel__:hello频道,并且也会在__sentinel__:hello频道上定期发布自己的信息(如IP和端口)。这样各个哨兵就可以实时获取到对方的 IP 地址和 端口信息。通过观察上面的交互图,我们可以看到哨兵 B 会先订阅主节点频道
__sentinel__:hello,哨兵 A 、C 会定期在该频道上发布自己的 IP 地址和端口信息,因此,哨兵 B 就会实时获取到 A、C 的地址端口信息,从而与它们建立连接并通信。
1.2 主观下线
sentinel 会以每秒一次的频率向所有节点(其他sentinel、主节点、以及从节点)发送 ping 消
息,然后通过接收返回判断该节点是否下线;如果在配置指定 down-after-milliseconds 时间
内则被判断为主观下线;
1.3 客观下线
当一个 sentinel 节点将一个主节点判断为主观下线之后,为了确认这个主节点是否真的下线,它会
向其他 sentinel 节点进行询问,如果收到一定数量(半数以上)的已下线回复,sentinel 会将主节
点判定为客观下线,并通过领头 sentinel 节点对主节点执行故障转移;
1.4 故障转移
主节点被判定为客观下线后,开始领头 sentinel 选举,需要半数以上的 sentinel 支持,选举领头
sentinel 后,开始执行对主节点故障转移;
从从节点中选举一个从节点作为新的主节点
通知其他从节点复制连接新的主节点
若故障主节点重新连接,将作为新的主节点的从节点
1.5 缺点
redis 采用异步复制的方式,意味着当主节点挂掉时,从节点可能没有收到全部的同步消息,这部
分未同步的消息将丢失。如果主从延迟特别大,那么丢失可能会特别多。sentinel 无法保证消息完
全不丢失,但是可以通过配置来尽量保证少丢失。
同时,它的致命缺点是不能进行横向扩展
2. 集群模式(cluster)

核心架构与原理
1. 哈希槽(Hash Slot):数据分片核心
- 集群固定划分 16384 个哈希槽(0–16383),所有键按槽位分布。
- 键 → 槽位映射公式:
plaintext
CRC16(key) % 16384 - 每个主节点负责一段连续槽位(如 3 主集群:0–5460、5461–10922、10923–16383)。
- 优势:增删节点只需迁移槽位,不改变键计算逻辑,支持平滑扩缩容。
2. 节点角色
- 主节点(Master):负责读写、存储数据、管理分配的槽位。
- 从节点(Replica/Slave):异步复制主节点数据;主节点故障时,通过选举晋升为新主,实现故障转移。
- 最小集群:至少 3 个主节点(保证选举多数),建议每个主配 1+ 从节点。
3. 节点通信:Gossip 协议
- 所有节点通过集群总线(TCP 端口 + 10000) 互联,形成全网格。
- 用 PING/PONG 消息交换:节点状态、槽位映射、配置纪元(Config Epoch)等。
- 最终所有节点持有一致的集群视图,客户端可从任意节点获取路由信息。
4. 客户端路由
- 客户端本地缓存槽位 → 节点映射表,直接访问目标节点。
- 若访问错误节点,服务端返回
MOVED/ASK重定向,客户端更新本地映射并重试。 - 无代理层,客户端直连节点,性能更高。
高可用机制
1. 故障检测
- 节点通过 Gossip 互相心跳;若多数主节点判定某主节点下线,标记为 FAIL。
2. 自动故障转移
- 下线主节点的从节点发起选举。
- 集群中多数主节点(> N/2) 投票,得票最多的从节点晋升为新主。
- 新主接管原主的槽位,集群恢复可用。
3. 副本迁移(Replica Migration)
- 集群自动平衡:若某主无副本,会从多副本主节点迁移一个副本过去,提升整体可用性。
关键特性与限制
优点
- 水平扩展:存储与读写能力随节点数线性提升,支持海量数据与高并发。
- 高可用:内置自动故障转移,无需额外 Sentinel 组件。
- 去中心化:无中心节点,避免单点瓶颈与故障。
- 原生支持:官方实现,兼容性好,运维成本低于第三方分片方案。
限制
- 事务与多键操作:不支持跨槽事务、
MSET/MGET等多键命令(可用 Hash Tag 强制多键同槽:{user:100}:name、{user:100}:age)。 - 数据迁移:扩缩容需迁移槽位,过程中可能短暂阻塞或重定向请求。
- 配置复杂度:节点数多、槽位管理、网络要求更高。
- 复制延迟:主从异步复制,故障时可能丢失少量已确认写入。
更多推荐




所有评论(0)