Redis 淘汰策略、持久化与高可用

Redis 淘汰策略、持久化与高可用

一、淘汰策略

Redis 作为内存数据库,所有数据存储在内存中。当内存使用达到上限(maxmemory)时,Redis 需要根据配置的策略淘汰部分数据,以容纳新写入的数据。

1. 淘汰策略触发时机

  • 内存使用达到 maxmemory 限制,且客户端发起新写入操作(如 SETLPUSH 等)。
  • 淘汰只在写操作时触发,读操作不会淘汰数据。

2. RedisObject 与 LRU/LFU 字段

每个键值对由 redisObject 结构管理,其中包含一个 24 位的 lru 字段:

  • LRU 模式:存储最后一次访问的时间戳(秒级),精度约为 194 天。
  • LFU 模式:分为 16 位“最后一次访问时间”和 8 位“访问频次计数器”。

通过 OBJECT IDLETIME key 可以查看键的空闲时间(秒),该命令会更新 lru 字段(为了准确返回空闲时间,会临时更新)。

3. 淘汰策略类型

Redis 提供八种淘汰策略(通过 maxmemory-policy 配置):

策略 说明 适用场景
noeviction 默认策略,内存满时写入报错 不允许任何数据丢失的场景
allkeys-lru 从所有键中淘汰最近最少使用的 通用缓存,适合大部分场景
volatile-lru 从设置了过期时间的键中淘汰最近最少使用的 要求缓存数据有明确过期时间
allkeys-lfu 从所有键中淘汰最不经常使用的 访问频率差异明显的场景
volatile-lfu 从设置了过期时间的键中淘汰最不经常使用的 同上,且要求数据带过期时间
allkeys-random 随机淘汰所有键 对访问模式无要求,可快速释放内存
volatile-random 随机淘汰设置了过期时间的键 同上
volatile-ttl 淘汰剩余生存时间(TTL)最短的键 优先淘汰即将过期的数据

注意

  • volatile-* 策略仅作用于带过期时间的键,如果没有任何带过期时间的键,则退化为 noeviction
  • 采样机制:每次淘汰时,从 maxmemory-samples(默认 5)个候选键中选出最符合策略的键淘汰,避免全量扫描,平衡性能与准确性。

4. LRU vs LFU

  • LRU(Least Recently Used):基于“最近使用时间”,使用 24 位时间戳记录最后一次访问。
  • LFU(Least Frequently Used):基于“访问频率”,使用 8 位计数器动态增长,但会随时间衰减,避免冷数据长期占据内存。

通过 redis.conf 配置:

maxmemory 4gb
maxmemory-policy allkeys-lru
maxmemory-samples 10

5. 过期键的删除策略

淘汰策略解决的是内存满的问题,而过期键删除解决的是键到期后自动删除的问题。Redis 采用两种方式:

  • 惰性删除:当客户端访问一个已过期的键时,发现过期立即删除并返回空。
  • 定期删除:后台任务每秒执行多次,从设置了过期时间的键中随机抽样检查,删除其中过期的键。

这两种方式结合,既保证 CPU 友好,又避免大量过期键长期占用内存。


二、持久化

Redis 提供 RDB 和 AOF 两种持久化机制,用于在服务器重启时恢复数据。

1. RDB(Redis Database)

RDB 是内存快照,将某个时间点的数据以二进制形式保存到磁盘。

工作原理

  1. 主进程 fork 出一个子进程。
  2. 子进程将当前内存数据写入临时 RDB 文件。
  3. 写入完成后,用临时文件替换旧文件。

由于 fork 采用写时复制(COW),子进程与父进程共享物理内存,仅在父进程修改数据时才会复制被修改的页,因此 RDB 对内存的影响较小。

触发方式

  • 手动SAVE(阻塞)或 BGSAVE(后台)。
  • 自动:根据 save 配置(如 save 900 1 表示 900 秒内至少有 1 次修改则自动执行 BGSAVE)。

优缺点

优点 缺点
文件紧凑,恢复速度快 可能丢失最后一次快照后的数据
适合备份,可异地存储 频繁 fork 可能影响性能

2. AOF(Append Only File)

AOF 记录所有写操作的 Redis 协议文本,重启时重放这些命令来恢复数据。

刷盘策略

通过 appendfsync 配置:

  • always:每次写入都同步到磁盘,最安全,但性能最差。
  • everysec:每秒异步同步一次,折中方案(默认)。
  • no:由操作系统决定,性能最好,但可能丢失更多数据。

AOF 重写(Rewrite)

由于 AOF 文件会不断增长,且包含冗余命令(如对同一键多次 SET),Redis 通过 BGREWRITEAOF 生成一个最小化的 AOF 文件,原理与 RDB 类似:fork 子进程读取内存数据,直接转换为命令写入新 AOF 文件,期间父进程的写操作记录到重写缓冲区,重写完成后追加到新文件。

优缺点

优点 缺点
数据安全性高,可做到秒级丢失 文件体积大,恢复速度慢
可读性好,易于修复 对磁盘 I/O 压力大

3. 混合持久化(Redis 4.0+)

结合 RDB 和 AOF 的优点:AOF 重写时,将 RDB 快照(二进制)作为文件开头,后续增量命令以 AOF 格式追加。这样重启时先加载 RDB 部分(快),再重放增量 AOF 命令,兼顾安全性与恢复速度。

配置:

aof-use-rdb-preamble yes

4. 大键对持久化的影响

  • RDB:大键会使 fork 复制的页表变大,增加 fork 耗时;写时复制时,若大键被修改,会复制整个大键内存页,造成内存短暂翻倍。
  • AOF:大键的写入会产生大量协议文本,增加文件体积;刷盘时可能阻塞主线程(尤其在 always 策略下)。

建议:避免使用大键,可通过拆分或使用合适的数据结构(如 Hash 分段)优化。


三、高可用方案

1. 主从复制

主从复制是 Redis 高可用的基础,实现数据冗余备份。

复制原理

  1. 从节点向主节点发送 REPLICAOF <master_ip> <master_port> 命令(或启动时配置 replicaof)。
  2. 主节点收到命令后,启动后台子进程生成 RDB 快照,并发送给从节点。
  3. 从节点清空自身数据,加载 RDB。
  4. 主节点将复制期间收到的写命令缓存在环形缓冲区中,从节点加载完 RDB 后,主节点将缓冲区的命令增量发送给从节点。
  5. 后续主节点异步将写命令同步给从节点。

复制偏移量与环形缓冲区

  • 主节点维护一个复制偏移量,每次发送数据时偏移量增加。
  • 每个从节点也记录自己的偏移量。
  • 主节点使用一个固定大小的环形缓冲区存储最近发送的命令。如果从节点断线重连后,其偏移量仍在缓冲区内,则进行增量同步;否则触发全量同步。

优缺点

优点 缺点
实现简单,支持读写分离 无自动故障转移
异步复制,主节点性能高 可能丢失少量数据

2. 哨兵模式(Sentinel)

哨兵模式在主从复制基础上增加了自动故障转移能力。

架构

  • 哨兵节点(通常部署奇数个)监控主从节点状态。
  • 当多数哨兵确认主节点不可用时,选举出一个新主节点,并修改配置,通知客户端。

关键概念

  • 主观下线:单个哨兵实例与主节点连接超时。
  • 客观下线:超过 quorum 个哨兵确认主观下线,触发故障转移。

故障转移流程

  1. 哨兵集群选举一个 Leader(基于 Raft 协议)。
  2. Leader 从从节点中选出一个数据最新的(复制偏移量最大)作为新主节点。
  3. 将其他从节点指向新主节点。
  4. 通过发布订阅机制通知客户端更新主节点地址。

缺点

  • 故障转移期间服务不可用(通常 10-30 秒)。
  • 配置复杂,不适合超大规模集群。

3. Redis 集群(Redis Cluster)

Redis Cluster 提供数据分片高可用的一体化方案,支持横向扩展。

核心特性

  • 去中心化:所有节点对等,无中心代理。
  • 数据分片:将 16384 个哈希槽分配给多个主节点。
  • 高可用:每个主节点可配备多个从节点,主节点故障时从节点自动提升为主节点。

数据分布

  • 键通过 CRC16(key) % 16384 确定属于哪个槽。
  • 槽由主节点管理,客户端通过 MOVEDASK 重定向访问正确节点。
  • 支持动态添加/删除节点,通过重新分片迁移槽。

客户端连接

  • 客户端需要支持集群协议(如 hiredis-cluster)。
  • 连接任一节点,获取槽位映射表,之后根据键计算槽位直接访问对应节点。

故障转移

  • 采用故障检测:节点间通过 Gossip 协议交换状态,半数以上节点认为某主节点不可达,则标记为 FAIL,并从其从节点中选举新主节点(基于复制偏移量优先)。

配置示例

创建集群(6 个节点,3 主 3 从):

redis-cli --cluster create 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 --cluster-replicas 1

优缺点

优点 缺点
支持海量数据(可线性扩展) 部署运维复杂
自动故障转移 跨槽操作(如多键事务)受限
无中心节点,性能高 客户端需支持集群协议

posted @ 2026-03-26 22:02  xggx  阅读(17)  评论(0)    收藏  举报