0%

memcached过期删除

Memcached 过期与删除机制:Lazy Expiration 与 LRU 策略详解

Memcached 作为内存缓存系统,其过期数据处理和内存回收机制直接影响缓存有效性和资源利用率。与传统数据库的主动过期检查不同,Memcached 采用懒惰删除(Lazy Expiration)LRU(最近最少使用) 策略,以最小的性能开销实现内存管理。本文深入解析这两种机制的原理、优缺点及实际表现。

Lazy Expiration(延迟过期):不主动检查,按需验证

核心原理

Memcached 不会主动监控数据是否过期,而是在用户尝试获取数据时才检查其过期时间:

  1. 当客户端执行 get <key> 时,Memcached 首先判断该键是否存在。
  2. 若存在,检查其时间戳是否过期(当前时间 > 过期时间)。
  3. 若已过期,返回 “键不存在”(END),并将该键标记为无效,从 curr_items 统计中移除。
  4. 若未过期,返回数据,并更新其 “最近使用时间”(用于 LRU 策略)。

优点

  • 节省 CPU 资源:无需维护定时器或线程监控所有键的过期状态,避免频繁检查带来的性能损耗。
  • 简单高效:过期检查与数据访问绑定,仅在必要时执行,适合高并发场景。

缺点

  • 内存占用延迟释放:过期数据可能长时间驻留内存(直到被访问或被 LRU 淘汰),导致短期内存利用率下降。
  • 统计数据延迟更新stats 命令中的 curr_items 会包含已过期但未被访问的键,直至其被主动获取或淘汰。

示例

  1. 存储一个 10 秒后过期的键:

    1
    2
    set test_key 0 10 5
    hello
  2. 5 秒后执行 statscurr_items 仍包含 test_key(未被访问,未触发检查)。

  3. 15 秒后执行 get test_key,返回 END(已过期),此时 curr_items 减 1。

LRU(最近最少使用):内存不足时的回收策略

当 Memcached 内存空间不足(达到 -m 参数限制),且没有过期数据可复用(或过期数据空间不足)时,会通过 LRU 策略 淘汰 “最近最少使用” 的数据,释放内存给新数据。

核心原理

  • 维护访问记录:每个键被访问(get/set 等操作)时,Memcached 会更新其 “最近使用时间戳”。
  • 淘汰规则:当需要分配新内存时,优先淘汰时间戳最早(最久未被使用)的键,无论其是否过期(包括永久有效的键)。

关键特性

  • 不区分过期与永久数据:即使键设置为永久有效(expire=0),若长期未被访问,仍可能被 LRU 淘汰。
  • 按 Slab Class 独立淘汰:LRU 操作仅在当前需要分配的 Slab Class(对应固定大小的 Chunk)内部进行,不会跨类别淘汰数据。

示例

  1. 假设 Memcached 总内存为 1MB,且仅使用 Chunk 大小为 100B 的 Slab Class。
  2. 存储 10000 个 100B 的永久有效键(填满内存)。
  3. 新增第 10001 个键时,Memcached 会淘汰这 10000 个键中最久未被访问的那个,腾出空间。

懒惰删除机制:内存复用的细节

Memcached 在删除数据(delete 命令)或处理过期数据时,采用标记删除而非立即释放内存:

  1. 删除操作:执行 delete <key> 后,键被标记为 “已删除”,但其占用的 Chunk 不会立即归还给操作系统,而是加入该 Slab Class 的空闲列表。
  2. 内存复用:新数据需要分配 Chunk 时,优先使用空闲列表中的标记删除或过期 Chunk,避免频繁向操作系统申请内存。

优点

  • 减少系统调用:内存块复用避免了 freemalloc 的开销,提升分配效率。
  • 维持 Slab 结构稳定:Chunk 大小固定,复用机制保证了 Slab Class 结构不被破坏,便于管理

欢迎关注我的其它发布渠道