结论与计划:Redis的过期key删除机制主要有惰性删除和定时删除两种方式结合使用。惰性删除是访问key时检查过期时间,过期则删除;定时删除是每隔一段时间扫描数据库删除过期key。为避免数据丢失和性能瓶颈,建议配置hz值在10-20之间,结合主动删除脚本,每60秒运行一次删除过期key的lua脚本,同时监控内存使用率,当达到80%时触发主动清理。代码示例:redis-cli --eval delete_expired.lua , --arg key_pattern
痛点解析
Redis过期删除的痛点在于,定时删除任务会占用大量CPU,如果key过多会导致阻塞主线程。惰性删除又可能造成内存泄漏,因为不访问的过期key不会被清理。实际场景中,用户设置了TTL但key一直存在,导致内存持续增长,最终OOM。
避免数据丢失
数据丢失常见于AOF重写时,过期key被提前删除但日志未同步。解决方案是使用lazyfree-lazy-expire yes,让过期删除异步进行,避免阻塞。配置maxmemory-policy allkeys-lru,确保内存满时优先淘汰不活跃key。
性能瓶颈优化
性能瓶颈往往出现在高并发场景,定时删除扫描过多数据库。优化计划:降低hz值到10,启用active-rehashing no,减少哈希表rehash压力。同时编写自定义脚本:local keys = redis.call('keys', ARGV[1]) for i=1,#keys do local ttl = redis.call('ttl', keys[i]) if ttl < 0 then redis.call('del', keys[i]) end end
实际案例
在电商缓存中,商品库存key过期未及时释放,导致新数据覆盖旧数据丢失。解决后,使用pipeline批量删除过期key,每分钟执行一次,内存占用下降30%。
监控与告警
部署Prometheus监控evicted_keys和expired_keys指标,当evicted_keys激增时告警。计划中加入定期scan 0 COUNT 1000 MATCH prefix:*,逐步清理。
高级配置
lazyfree-lazy-eviction yes,结合activedefrag yes at 70,自动碎片整理,避免性能下降。
FAQ:
Q: Redis为什么会出现过期key未删除?
A: 因为惰性+定时删除策略,只有访问或定时扫描时才删。
Q: 如何快速清理大量过期key?
A: 用SCAN命令迭代+DEL批量删除,避免KEYS阻塞。
Q: 内存满时怎么处理?
A: 设置maxmemory并选allkeys-lru策略。
Q: AOF日志会记录过期删除吗?
A: 默认会,开启lazyfree可异步处理减少日志。