Redis 云服务器内存容量评估

Redis 数据集只有 1GB,是不是买 2GB 内存的云服务器就够了?很多线上 OOM、延迟抖动和后台保存失败,正是从这个估算开始的。

Redis 的内存需求不只有键值数据。对象开销、内存碎片、客户端缓冲区、复制积压、AOF 缓冲、操作系统余量,以及 RDB/AOF 重写时 Fork 触发的写时复制,都可能把进程 RSS 推到 used_memory 之上。选 2G、4G 还是 8G,应该以高峰期真实数据和最坏写入窗口为依据。

本文提供一套可以执行的容量评估方法:先量出数据集与额外开销,再估算 Fork 峰值,最后决定优化配置、升级内存还是迁移到更合适的云服务器。

一、哪些 Redis 场景最需要提前算内存

以下场景不适合只按当前数据集大小购买:

  • Redis 同时承担缓存、Session、排行榜或分布式锁;
  • 开启 RDB、AOF,或需要定期执行后台重写;
  • 写流量高,过期键和淘汰量随业务峰值明显变化;
  • 存在大量小 Key、Hash 小字段或长 TTL 数据;
  • 作为主从复制节点,存在复制缓冲与全量同步窗口;
  • 运行在 Docker 中,容器内存上限小于宿主机可用内存;
  • 云服务器同时运行应用、监控代理、日志服务或其他数据库。

纯测试环境可以更激进地使用内存,但生产环境必须给持久化、故障恢复和业务突增留出余量。

二、第一步:区分 used_memory、RSS 和系统可用内存

先获取 Redis 内存指标:

redis-cli INFO memory

重点关注:

指标含义容量判断
used_memoryRedis 分配器统计的已使用内存数据与内部结构的基础占用
used_memory_dataset数据集实际占用部分判断业务数据规模
used_memory_overhead连接、复制、内部结构等开销Key 多、连接多时可能明显增加
used_memory_rss操作系统看到的进程常驻内存更接近进程真实物理占用
mem_fragmentation_ratioRSS 与分配内存的关系指标之一需结合绝对值和负载判断
maxmemoryRedis 配置的内存上限不应直接等于机器总内存

同时检查系统和进程:

free -h
ps -o pid,rss,vsz,cmd -C redis-server
vmstat 1 10

used_memory 不是云服务器需要购买的总内存,used_memory_rss 也不能脱离系统余量单独看。内核、文件缓存、SSH、监控和同机服务都需要空间。

三、第二步:找出数据为什么比预想占内存

查看更细的统计:

redis-cli MEMORY STATS
redis-cli MEMORY DOCTOR
redis-cli INFO clients
redis-cli INFO replication

1. 大量小 Key 的结构开销

1GB 业务内容不等于 1GB Redis 内存。Key 字符串、对象头、过期字典、哈希表桶和分配器对齐都会增加占用。Key 越多、单个 Value 越小,结构开销占比可能越高。

可以在低峰期抽查 Key 分布:

redis-cli --bigkeys
redis-cli --memkeys

这些命令会扫描键空间,生产环境应评估数据量和扫描影响,避免在高峰期直接运行。

2. 客户端输出缓冲区

慢消费者、Pub/Sub、大查询和复制连接可能积累输出缓冲。检查:

redis-cli CLIENT LIST
redis-cli INFO clients

如果少数连接的 omem 持续增长,应先修复消费速度或限制策略,而不是只给机器加内存。

3. 内存碎片与释放滞后

频繁更新不同大小的 Value、批量过期或删除后,RSS 可能不会立刻下降。不要只看 mem_fragmentation_ratio 的单个瞬时值,还要比较:

  • used_memory_rss - used_memory 的绝对差值;
  • 指标是否在业务低峰仍持续增长;
  • 是否刚发生大批量删除、加载或后台保存;
  • 操作系统是否已经出现内存压力。

碎片高并不总等于应该立刻重启。应先确认版本、分配器、业务写入模式和可用的主动碎片整理策略,再在可回滚窗口操作。

四、第三步:估算 Fork 写时复制的峰值

Redis 执行 BGSAVE 或 AOF 重写时会 Fork 子进程。父子进程最初共享内存页,但在后台任务期间,父进程继续写入的页面会触发 Copy-on-Write(COW),形成额外物理内存占用。

查看持久化与 Fork 指标:

redis-cli INFO persistence
redis-cli INFO stats

重点观察:

  • rdb_bgsave_in_progress
  • aof_rewrite_in_progress
  • 最近后台保存或重写是否成功;
  • latest_fork_usec
  • 后台任务期间 Redis RSS 与系统可用内存的变化。

COW 峰值取决于后台任务时长和这段时间被修改的内存页,而不是简单固定为数据集的某个百分比。写入越密集、后台任务越慢,额外占用通常越值得警惕。

建议在一次真实但可控的后台保存窗口中每秒采样:

while true; do
  date '+%F %T'
  redis-cli INFO memory | grep -E 'used_memory:|used_memory_rss:|mem_fragmentation_ratio:'
  free -b | awk '/Mem:/ {print "mem_available=" $7}'
  sleep 1
done

不要为了测峰值在容量已经紧张的生产节点上贸然触发 BGSAVE。应优先使用既有计划任务的观测窗口,或在同规格测试节点复现。

五、用公式估算 2G、4G 或更大配置

可以把容量拆成五部分:

所需物理内存 = Redis 稳态 RSS
             + Fork/COW 峰值增量
             + 同机进程占用
             + 操作系统与文件缓存余量
             + 业务增长和故障恢复余量

例如,某节点高峰期观测到:

  • Redis 稳态 RSS:1.35GB;
  • 后台重写期间 RSS 最大增加:420MB;
  • 系统与监控进程:300MB;
  • 未来一个扩容周期预计新增:350MB。

这些项目相加已经超过 2.4GB,还没有加入充分安全余量。2GB 云服务器显然不适合;4GB 是否够用,则要继续结合复制、重启加载、突发写入和同机服务评估。

示例只用于说明计算方式,不能代替你的真实监控。建议至少采集 7 天,覆盖业务高峰、一次 RDB/AOF 后台任务和一次发布窗口。

六、maxmemory 应该怎么设

查看当前配置:

redis-cli CONFIG GET maxmemory
redis-cli CONFIG GET maxmemory-policy

maxmemory 不应直接设置为云服务器总内存,因为 Redis 进程还有未计入数据上限的开销,操作系统和 Fork COW 也需要余量。

配置思路应按用途区分:

  • 纯缓存:可以设置淘汰策略,但必须验证命中率、淘汰量和回源承载能力;
  • Session 或锁:淘汰可能直接影响业务正确性,应谨慎选择策略;
  • 持久化数据:达到上限后的写入行为必须提前验证,不能把淘汰当作默认兜底;
  • 主从复制:还要为复制积压和同步过程预留内存与网络带宽。

临时修改后要同步到配置管理并验证重启,否则运行值与配置文件可能不一致。

七、Docker 场景还要检查容器上限

宿主机有 8GB,不代表 Redis 容器可以使用 8GB。先检查:

docker stats --no-stream
docker inspect <Redis容器名> --format '{{.HostConfig.Memory}} {{.HostConfig.MemorySwap}}'

cgroup v2 可以查看:

cat /sys/fs/cgroup/memory.max
cat /sys/fs/cgroup/memory.current
cat /sys/fs/cgroup/memory.events

如果 memory.eventsoomoom_kill 增长,说明容器已经触碰限制。应同时检查 Redis maxmemory、容器上限和宿主机余量,避免三者互相矛盾。

八、什么时候优化,什么时候升级云服务器

先优化配置与数据结构

  • 过期策略失效,历史 Key 未按预期清理;
  • 客户端缓冲由慢消费者持续堆积;
  • 大量小 Key 可以合理合并为 Hash;
  • 本地缓存了本应归档或放入数据库的数据;
  • 同一实例混用缓存、队列和关键持久化数据,边界不清。

更适合升级内存

  • 稳态 RSS、COW 峰值和系统余量相加已接近物理上限;
  • 数据增长真实且无法通过过期或结构优化消除;
  • RDB/AOF 重写期间可用内存持续下降;
  • 高峰期已经出现 swap、OOM 或后台保存失败;
  • 未来一个扩容周期内会越过安全线。

更适合拆分或迁移

  • 单实例数据集过大,Fork 和恢复时间不可接受;
  • 不同业务需要不同淘汰、持久化或可用性策略;
  • CPU、网络带宽与内存同时接近瓶颈;
  • 业务需要副本、高可用和故障域隔离。

九、调整后如何验证

升级、迁移或修改 maxmemory 后,至少验证一个完整高峰和一次后台保存周期:

redis-cli INFO memory
redis-cli INFO persistence
redis-cli INFO stats
redis-cli LATENCY LATEST
redis-cli LATENCY DOCTOR

同时检查:

  • used_memory_rss 峰值与系统 MemAvailable
  • 后台保存、AOF 重写是否成功;
  • P95/P99 命令延迟;
  • evicted_keysexpired_keys 的变化;
  • swap 是否被使用;
  • 容器 OOM 事件是否停止增长;
  • 主从延迟与复制状态是否正常。

压力测试只能在隔离环境或授权窗口执行,且数据模型、Value 大小、读写比例和持久化配置要接近生产,否则结果没有容量参考价值。

十、常见误区

  1. 数据集 1GB 就买 2GB 内存:忽略了结构开销、RSS、COW 和系统余量。
  2. 只看 used_memory:OOM 由可用物理内存决定,进程 RSS 和同机服务同样重要。
  3. 碎片率高就立刻重启:可能带来不可接受的中断,且未必解决写入模式问题。
  4. 开启淘汰就不会 OOM:客户端缓冲、复制和 Fork 仍可能增加额外占用。
  5. 宿主机内存够,容器就安全:容器可能先触碰 cgroup 上限。
  6. 快照等于 Redis 一致性备份:仍需验证持久化文件、复制状态和实际恢复流程。

结语:用峰值而不是数据集大小购买内存

Redis 云服务器的内存配置,应以高峰期稳态 RSS 为基础,再加入 Fork/COW 峰值、客户端与复制开销、操作系统余量和未来增长。2G、4G 或 8G 只是结果,真正的依据是 INFO memory、系统监控和一次完整持久化窗口的数据。

如果现有实例已经频繁接近安全线,应先修复过期、缓冲和数据结构问题;无法消除的真实增长,则要及时升级内存或拆分实例。购买或迁移云服务器时,还应同时评估 CPU、磁盘 IO、网络带宽、备份恢复与高可用需求,避免只解决内存后又把瓶颈转移到下一项资源。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐