外观
Memcached 过期策略
Memcached的过期策略是其内存管理的重要组成部分,通过合理的过期策略,可以确保缓存数据的时效性,同时高效利用内存资源。
过期时间设置
1. 过期时间格式
Memcached支持两种过期时间格式:
- 相对时间:从当前时间开始计算的秒数,例如3600表示1小时后过期
- 绝对时间:Unix时间戳,例如1609459200表示2021-01-01 00:00:00
- 永不过期:设置过期时间为0,表示数据永不过期
2. 过期时间限制
- 相对时间最大值:如果相对时间超过30天(2592000秒),Memcached会将其视为绝对时间
- 过期时间精度:秒级精度,不支持毫秒级过期时间
3. 设置过期时间的命令
# 使用SET命令设置过期时间
SET key flags exptime bytes [noreply]
value
# 使用ADD命令设置过期时间
ADD key flags exptime bytes [noreply]
value
# 使用REPLACE命令设置过期时间
REPLACE key flags exptime bytes [noreply]
value
# 使用EXPIRE命令设置过期时间
EXPIRE key seconds过期数据处理机制
1. 惰性删除(Lazy Expiration)
工作原理
- 触发时机:当客户端访问数据时,才会检查该数据是否过期
- 处理流程:
- 客户端发送GET命令请求数据
- Memcached检查数据的过期时间
- 如果数据已过期,删除该数据并返回NOT_FOUND
- 如果数据未过期,返回数据并更新LRU链表
优缺点
- 优点:
- 不需要额外的过期检查线程,节省CPU资源
- 只在访问数据时进行过期检查,避免了对所有数据的遍历
- 缺点:
- 过期数据可能会占用内存一段时间,直到被访问
- 如果过期数据长时间不被访问,会导致内存浪费
2. 主动清理(Active Expiration)
工作原理
- 触发时机:定期运行过期清理线程
- 处理流程:
- 每60秒运行一次过期清理线程
- 随机选择100个数据项
- 检查这些数据项是否过期
- 删除已过期的数据项
- 如果删除的数据项超过10%,继续检查,直到删除的数据项少于10%
配置参数
- 检查频率:固定为每60秒一次,不可配置
- 检查数量:每次检查100个数据项,或5%的总数据项(取较小值)
- 检查深度:如果删除的数据项超过10%,继续检查,最多检查10次
优缺点
- 优点:
- 定期清理过期数据,避免内存浪费
- 控制清理频率和深度,避免影响正常服务
- 缺点:
- 需要额外的CPU资源用于过期检查
- 可能会遗漏一些过期数据
数据淘汰机制
1. LRU淘汰算法
工作原理
当Memcached的内存不足时,会使用LRU(最近最少使用)算法淘汰最近最少使用的数据,为新数据腾出空间。
- LRU链表:每个Slab类维护一个LRU链表,记录数据的访问顺序
- 访问更新:当数据被访问时,会被移到LRU链表的头部
- 淘汰策略:当需要淘汰数据时,从LRU链表的尾部选择数据进行淘汰
淘汰触发条件
- 当需要分配新的Chunk,但对应Slab类没有空闲Chunk
- 当无法分配新的Slab页面(已达到最大内存限制)
- 当特定Slab类的内存使用率过高
淘汰范围
- 只在当前需要分配Chunk的Slab类中进行淘汰
- 不会跨Slab类进行淘汰
2. 淘汰优先级
Memcached的数据淘汰优先级如下:
- 已过期的数据:优先淘汰已过期的数据
- 最近最少使用的数据:在未过期的数据中,淘汰最近最少使用的数据
- 同Slab类的数据:只在当前Slab类中进行淘汰
过期策略最佳实践
1. 合理设置过期时间
- 热点数据:设置较长的过期时间,或永不过期
- 冷数据:设置较短的过期时间
- 临时数据:根据数据的时效性设置合适的过期时间
- 避免固定过期时间:为数据设置随机的过期时间,避免缓存雪崩
2. 避免缓存雪崩
- 随机过期时间:为数据设置随机的过期时间,例如在基础过期时间上增加0-300秒的随机值
- 分层缓存:使用多级缓存,减少单级缓存的压力
- 限流降级:在缓存失效时,对请求进行限流和降级处理
3. 避免缓存穿透
- 布隆过滤器:在缓存前添加布隆过滤器,过滤不存在的键
- 空值缓存:对不存在的键缓存一个空值,设置较短的过期时间
- 请求限流:对异常请求进行限流,防止恶意攻击
4. 避免缓存击穿
- 热点数据永不过期:对热点数据设置较长的过期时间或永不过期
- 分布式锁:使用分布式锁控制缓存重建,防止并发重建
- 提前刷新:在热点数据过期前主动刷新缓存
5. 监控过期数据比例
- 定期监控过期数据的比例
- 如果过期数据比例过高,调整过期策略
- 分析过期数据的分布,优化缓存策略
过期策略监控
1. 监控指标
- curr_items:当前存储的数据项数量
- total_items:存储的总数据项数量
- evictions:因内存不足而淘汰的数据项数量
- reclaimed:通过惰性删除回收的内存字节数
- expired_unfetched:未被访问而过期的数据项数量(1.6.x版本及以上)
2. 监控工具
- memcached-tool:使用
memcached-tool <host>:<port> stats命令查看统计信息 - stats命令:通过客户端发送stats命令获取统计信息
- Prometheus + Grafana:全面监控和可视化Memcached的过期策略指标
- Zabbix:系统级监控和告警
过期策略的影响因素
1. 数据访问模式
- 频繁访问的数据:会被频繁更新LRU链表,不容易被淘汰
- 偶尔访问的数据:LRU链表位置靠后,容易被淘汰
- 永不过期的数据:除非内存不足,否则不会被淘汰
2. 内存大小
- 内存不足:会导致频繁的LRU淘汰,影响缓存命中率
- 内存充足:过期数据有足够的时间被清理,内存使用率稳定
3. 数据大小分布
- 数据大小均匀:Slab分配器的内存利用率高,LRU淘汰效率高
- 数据大小差异大:Slab分配器的内存利用率低,可能导致频繁的LRU淘汰
4. 过期时间分布
- 过期时间集中:可能导致缓存雪崩
- 过期时间分散:缓存压力均匀,避免缓存雪崩
常见问题及解决方案
1. 过期数据占用内存
症状
- 内存使用率高,但实际有效数据少
- 过期数据长时间不被访问
- 频繁出现evictions
解决方案
- 调整主动清理策略:虽然主动清理策略不可配置,但可以通过优化数据结构和过期时间来减少过期数据的积累
- 增加内存大小:减少LRU淘汰的频率
- 优化数据访问模式:确保过期数据能够被及时访问和清理
2. 缓存雪崩
症状
- 大量数据同时过期
- 导致请求直接穿透到后端系统
- 后端系统负载突然增加
解决方案
- 设置随机的过期时间:避免数据同时过期
- 使用分层缓存:减少单级缓存的压力
- 限流降级:在缓存失效时,对请求进行限流和降级处理
3. 缓存穿透
症状
- 大量请求访问不存在的数据
- 导致请求直接穿透到后端系统
- 后端系统负载增加
解决方案
- 使用布隆过滤器:过滤不存在的键
- 空值缓存:对不存在的键缓存一个空值,设置较短的过期时间
- 请求限流:对异常请求进行限流,防止恶意攻击
4. 缓存击穿
症状
- 热点数据过期
- 大量请求同时访问该数据
- 导致请求直接穿透到后端系统
解决方案
- 热点数据永不过期:对热点数据设置较长的过期时间或永不过期
- 分布式锁:使用分布式锁控制缓存重建,防止并发重建
- 提前刷新:在热点数据过期前主动刷新缓存
过期策略的演进
1. 早期版本(1.0-1.2)
- 基本的惰性删除机制
- 简单的主动清理策略
- 有限的统计信息
2. 稳定版本(1.4)
- 改进的主动清理策略
- 增加了更多的统计信息
- 优化了LRU淘汰算法
3. 现代版本(1.5-1.6)
- 优化的过期清理机制
- 增加了expired_unfetched指标
- 改进的LRU实现
常见问题(FAQ)
Q1: Memcached的过期时间精度是多少?
A1: Memcached的过期时间精度是秒级,不支持毫秒级过期时间。
Q2: 如何查看Memcached的过期数据数量?
A2: 在1.6.x版本及以上,可以使用stats命令查看expired_unfetched指标,该指标表示未被访问而过期的数据项数量。
Q3: 如何避免Memcached的缓存雪崩?
A3: 避免缓存雪崩的方法包括:
- 设置随机的过期时间
- 使用分层缓存
- 限流降级
- 热点数据永不过期
Q4: 如何处理Memcached中的过期数据?
A4: Memcached通过惰性删除和主动清理两种机制处理过期数据:
- 惰性删除:当访问数据时检查是否过期
- 主动清理:每60秒运行一次过期清理线程
Q5: 如何优化Memcached的过期策略?
A5: 优化Memcached过期策略的方法包括:
- 合理设置过期时间
- 避免固定过期时间
- 监控过期数据比例
- 优化数据访问模式
- 调整内存大小
Q6: Memcached的主动清理策略可以配置吗?
A6: Memcached的主动清理策略不可配置,固定为每60秒运行一次,每次检查100个数据项。
Q7: 如何处理Memcached中的热点数据?
A7: 处理热点数据的方法包括:
- 设置较长的过期时间或永不过期
- 使用分布式锁控制缓存重建
- 提前刷新缓存
- 将热点数据分布到多个节点
Q8: 如何监控Memcached的过期策略效果?
A8: 监控Memcached过期策略效果的方法包括:
- 监控evictions指标:反映LRU淘汰的频率
- 监控reclaimed指标:反映惰性删除回收的内存
- 监控expired_unfetched指标:反映未被访问而过期的数据数量
- 监控缓存命中率:反映缓存的有效性
Q9: Memcached的过期时间最大值是多少?
A9: Memcached的相对过期时间最大值是30天(2592000秒),超过该值会被视为绝对时间。
Q10: 如何设置Memcached的数据永不过期?
A10: 将过期时间设置为0,表示数据永不过期。但需要注意的是,当内存不足时,永不过期的数据也可能会被LRU淘汰。
