redis SDS 惰性删除

redis SDS 惰性删除
最新回答
糖↘甜到傷痛

2020-11-24 21:29:02

Redis SDS 的惰性删除主要通过 sdsRemoveFreeSpace 函数实现,其核心是在特定场景下移除 SDS 字符串末尾的未使用空间(free space),以优化内存和磁盘使用效率。 以下是具体分析:

1. SDS 惰性删除的触发场景

Redis 不会在每次字符串缩短后立即释放未使用空间,而是通过以下场景触发惰性删除:

  • RDB 持久化在生成 RDB 快照时,Redis 会遍历数据库并写入磁盘。为减少磁盘占用和提高 I/O 效率,写入前会调用 sdsRemoveFreeSpace 清除 SDS 的未使用空间,使数据更紧凑。
  • AOF 重写AOF 重写生成新文件时,Redis 会优化 SDS 字符串,移除未使用空间以缩小文件体积。
  • 内存压力回收当内存接近上限或触发 freeMemoryIfNeeded 时,Redis 会检查 SDS 的未使用空间并调用 sdsRemoveFreeSpace 释放内存。
  • 键值对删除或过期删除键值对时,Redis 可能在释放 SDS 前调用 sdsRemoveFreeSpace,确保仅释放实际使用的内存。
  • 特定命令或模块自定义命令或模块可能主动调用 sdsRemoveFreeSpace 以即时优化内存。
2. SDS 设计特性与惰性删除的关系

SDS 的惰性删除机制依赖于其设计特性:

  • 空间预分配SDS 在字符串增长时预分配额外空间(如 len 的一倍),减少频繁内存分配的开销。但缩短字符串时,未使用空间(free)会保留,需通过惰性删除释放。
  • 未使用空间跟踪SDS 通过 free 字段记录未使用空间大小。惰性删除时,sdsRemoveFreeSpace 会根据 len 重新分配内存,仅保留必要空间。
  • 高效修改操作追加内容时,若 free 不足则扩容;删除内容时,len 减小而 free 增加。惰性删除在后续场景中处理这些未使用空间。
3. sdsRemoveFreeSpace 的执行流程

该函数通过以下步骤移除未使用空间:

  • 调整容量根据当前 len 重新分配内存,确保仅存储有效字符。
  • 更新结构修改 SDS 的 alloc(总容量)和 buf(字符数组指针)字段,匹配新内存布局。
  • 释放内存归还原 SDS 中未使用的内存块,避免浪费。
4. 惰性删除的优势
  • 性能优化避免频繁内存分配/释放,降低操作开销。例如,字符串缩短后不立即缩容,减少后续追加时的扩容次数。
  • 资源高效利用在内存紧张或持久化时集中释放未使用空间,平衡实时性能与资源利用率。
  • 数据紧凑性持久化前清理未使用空间,减少磁盘占用和 I/O 负载。
5. 与空间预分配的协同

SDS 的空间预分配策略(如增长时分配额外空间)与惰性删除形成互补:

  • 预分配提升增长效率通过预留空间减少频繁扩容,适合高频追加场景。
  • 惰性删除优化缩短操作缩短字符串后暂不释放空间,待触发条件(如持久化)时统一处理,避免性能波动。
6. 实际应用示例
  • 场景:用户执行 SET key "hello" 后修改为 SET key "hi"。

    SDS 缩短字符串,len 从 5 变为 2,free 增加。

    若未触发惰性删除条件(如内存压力),未使用空间保留;若后续执行 SAVE 生成 RDB,则调用 sdsRemoveFreeSpace 释放多余内存。

总结:Redis SDS 的惰性删除通过 sdsRemoveFreeSpace 在关键场景(如持久化、内存回收)下移除未使用空间,结合空间预分配策略,实现了内存使用的高效性与操作性能的平衡。