跳转至

持久化与内存管理

Redis 主要在内存中处理数据,进程退出后内存内容会消失。持久化负责把可恢复的数据写到磁盘;复制负责在别的实例保存副本;高可用负责故障后恢复服务。这三者互相配合,不能互相替代。

RDB:给数据拍一张快照

RDB 保存一个时间点的数据集,适合备份、迁移和启动加载。两次快照之间的数据没有包含在旧快照里,因此只靠旧 RDB 恢复时会丢失后面的修改。

BGSAVE 用后台子进程生成快照,父进程继续处理请求;但 fork 以及写时复制仍会带来暂停或内存压力。SAVE 会同步执行快照并阻塞服务,不应作为繁忙生产环境的随手检查命令。

配置例子:save 900 1 表示满足“900 秒内至少 1 次修改”等条件时触发快照,不是每写一条就落盘。

AOF:保存能够重建数据的写操作记录

AOF 通过记录写入操作来恢复数据。它会增长,因此需要重写,将历史操作整理成能表达当前数据的更紧凑形式。重写是存储整理,不是清除业务数据。

appendfsync 行为 取舍
always 每次写入按策略同步到磁盘 更强调持久性,磁盘成本和延迟更高
everysec 通常每秒执行同步 常见折中;异常时通常存在约 1 秒写入丢失窗口,不是所有故障的硬保证
no 由操作系统决定刷盘时机 延迟可能较低,但丢失窗口更不可控

Redis 7+ 使用多文件 AOF,包含 manifest、基础文件和增量文件等。备份与恢复应保存一致的完整集合,不能以为永远只有一个 appendonly.aof。同时启用 RDB 与 AOF 时,正常启动会优先使用 AOF 恢复。官方持久化说明

选哪一种

普通可重建缓存可以按回源能力决定是否持久化;关闭持久化后,重启时冷缓存可能压垮数据库。会话、队列或其他难以重建的数据,需要更明确的恢复目标、持久化和备份安排。

我会先确认允许丢多少数据(RPO),再确认能停多久(RTO),最后决定策略。AOF、RDB 和副本都可能同步保存误删除结果;恢复历史数据依赖独立备份及恢复演练。

TTL 到期与内存淘汰是两回事

TTL 到期: 到了应用约定的时间,key 应该失效。Redis 会在访问时检查,也会主动抽样清理,不是每个 key 都创建一个独立定时器。

内存淘汰: 到达 maxmemory 后,为了继续处理需要内存的请求,按策略选择 key 移除。它可能在 TTL 尚未到期时发生。

key 还有 5 分钟有效期
  → 内存达到上限
  → allkeys-lru 认为它很久没访问
  → 提前淘汰

所以 TTL 不是“这条数据至少能保存这么久”的保证。用 Redis 保存重要状态时,不能让它随意被缓存淘汰策略删除。

maxmemory-policy 决定内存满了怎么做

策略 含义 适合的考虑方向
noeviction 不自动淘汰;需要额外内存的写命令可能报错 不允许自动丢 key 的状态数据,需要容量告警
allkeys-lru 从所有 key 中近似挑选最近较少使用的 通用缓存的常见起点
allkeys-lfu 从所有 key 中近似挑选使用频率较低的 有稳定冷热分布的缓存
volatile-lru / volatile-lfu 只在有过期时间的 key 中选择 需要区分可淘汰 key;没有合适候选仍可能写失败
volatile-ttl 优先淘汰剩余寿命较短的 key 能接受这种优先级的缓存
allkeys-random / volatile-random 在全部或可过期 key 中随机选择 不依赖热度排序的特定负载

LRU 看“最近用没用”,LFU 看“常不常用”;Redis 的实现是近似策略。内存上限与淘汰策略见官方说明

缓存与重要会话混在一个实例中,通常很难选一个都合适的策略。不同逻辑数据库只是命名隔离,仍共享实例资源和淘汰机制,不提供独立内存上限;Cluster 也不支持这种多逻辑数据库切换。

配了 512 MiB,为什么容器仍然可能超过它

maxmemory 512mb 不是操作系统对进程 RSS 的硬上限。数据结构开销、分配器碎片、客户端缓冲区、复制/AOF 缓冲及后台任务都影响实际内存;部分缓冲不纳入用于淘汰判断的内存统计。

RDB/AOF 重写的子进程通过写时复制共享内存,父进程持续修改页面时,物理内存额外增长。写入越活跃,峰值可能越明显。容器限制必须留有余量,再通过压测和重写过程验证;不能将 maxmemory 与容器限制设成同一个值。

INFO memory
INFO persistence
MEMORY STATS
MEMORY USAGE learn:product:1001

重点比较 used_memoryused_memory_rssmaxmemory,以及重写时的峰值。mem_fragmentation_ratio 在数据很少时可能很高,不能只凭一个比值就判定严重泄漏。

大 key 和热 key

大 key 是单个值很大、或一个集合成员很多;热 key 是访问特别频繁。它们可以同时存在,也可以完全不同。

问题 影响 常见处理
巨大 String 序列化、网络传输、内存都重 缩小缓存结果,拆分内容,按需读取
巨大 Hash/List/Set 全量读取、遍历或删除耗时 分批访问,拆结构,限制成员增长
热 key 某个实例或分片负载集中 应用本地缓存、请求合并、限流,按业务拆热点

UNLINK 可以将适合异步的内存释放移到后台,但不会让大数据的读取与传输成本消失。分片也不会自动把一个热 key 拆开。

恢复要实际做一次

先在隔离环境准备相同兼容版本和配置,用已验证一致的备份恢复,检查 key 数量、关键样本、TTL、启动时长和日志。如果在恢复演练里直接使用过期很久的快照,部分 key 在加载后消失可能正是 TTL 到期,应结合时间点判断。

记录备份生成时间、文件集合、校验值、版本和恢复耗时。发现损坏时先保留原件再考虑检查/修复工具;修复可能截掉不能恢复的尾部记录。具体部署与检查见下一页