温馨提示×

Linux Redis内存如何管理

小樊
43
2025-12-26 07:29:52
栏目: 云计算

Linux 上 Redis 内存管理的核心要点

一 内存构成与关键指标

  • 内存组成:主要由对象内存(键值对真实数据)、缓冲内存(客户端输入/输出缓冲、复制积压缓冲区AOF 缓冲区)、自身进程开销内存碎片构成。Redis 默认使用 jemalloc 分配器,配合不同大小的内存类减少内部碎片。
  • 关键监控指标(通过 INFO memory 查看):
    • used_memory:Redis 分配器视角已用内存。
    • used_memory_rss:操作系统视角进程占用的物理内存。
    • mem_fragmentation_ratio = used_memory_rss / used_memory:碎片率;>1 常见,≈1.03 通常较健康;<1 可能发生了 Swap,性能会显著下降。
    • mem_allocator:如 jemalloc。
      这些指标用于判断是否存在碎片、是否发生交换、是否需要扩容或做碎片整理。

二 内存上限与淘汰策略

  • 设置上限:通过 maxmemory 限制 Redis 可用内存(单位支持如 100mb、6gb)。在 64 位系统若不设置或为 0,表示不限制;32 位系统最多约 3GB。达到上限后,写入将按 maxmemory-policy 进行淘汰或报错。
  • 淘汰策略(共 8 种):
    • noeviction:不淘汰,写操作返回错误(默认)。
    • allkeys-lru / volatile-lru:从全部键或仅有过期时间的键中按 LRU(最近最少使用)淘汰。
    • allkeys-lfu / volatile-lfu(Redis 4.0+):按 LFU(最不常用)淘汰。
    • allkeys-random / volatile-random:随机淘汰。
    • volatile-ttl:淘汰 TTL 剩余最短的键。
  • 选择建议:
    • 访问呈幂律分布(热点明显)优先 allkeys-lru
    • 键普遍设置 TTL 且希望按剩余时间清理优先 volatile-ttl
    • 访问均匀可考虑 allkeys-random
  • 动态生效:可用 CONFIG SET maxmemory 6GBCONFIG SET maxmemory-policy allkeys-lru 在线调整(持久化到配置文件以防重启丢失)。

三 过期键删除与回收流程

  • 惰性删除:当访问带有 TTL 的键时,若已过期则立即删除并返回空,优点是节省 CPU,缺点是过期键可能长时间不被访问而占用内存。
  • 定期删除:后台任务每秒约运行 10 次(受 hz 影响),以“采样 + 删除”的方式自适应清理过期键,避免堆积。
  • 达到上限的回收:当 used_memory 触及 maxmemory,按 maxmemory-policy 执行淘汰以腾出空间,保证写入可用(除 noeviction 外)。

四 Linux 系统层面的关键配置

  • 透明大页 THP:建议关闭(或设置为 madvise),因为 THP 会让 fork 后的 写时复制(COW) 页从 4KB 放大到 2MB,显著增加重写期间的内存复制与阻塞风险。
  • vm.overcommit_memory:建议设为 1(允许内核过量承诺内存),降低 fork 因内存不足失败的概率。
  • 子进程与持久化:执行 RDB/AOF 重写 时会 fork 子进程;父子进程共享物理页,期间父进程发生写操作会触发 COW,实际额外内存开销取决于重写期间的写入量,需预留余量。
  • 监控要点:关注 used_memory_rssmem_fragmentation_ratio、是否出现 Swap、以及慢查询;碎片率高或 RSS 异常增长时考虑重启做碎片整理(在可控的维护窗口进行)。

五 快速排查与优化清单

  • 设定合理上限:确保 maxmemory > used_memory,并预留 1–2GB 给碎片与运行时开销;在 INFO memory 中观察 mem_fragmentation_ratioused_memory_rss 的趋势。
  • 选择匹配业务的淘汰策略:热点数据用 allkeys-lru,带 TTL 的大量键用 volatile-ttl,均匀访问用 allkeys-random
  • 控制缓冲与连接:合理设置 client-output-buffer-limit(如 slave、pubsub、normal),避免慢客户端或大对象返回导致缓冲暴涨;结合 maxclients 控制连接规模。
  • 优化数据结构与编码:尽量使用更紧凑的编码(如 ziplist/intset 条件满足时)、缩短 key、避免大 value 与频繁 APPEND/Range 导致碎片;必要时进行安全重启以回收碎片。
  • 系统层面:关闭 THP、设置 vm.overcommit_memory=1,并在重写高峰期关注 fork 延迟与 COW 内存开销。

0