网站首页 > java教程 正文
Redis 过期键删除策略全景实战
一、为什么需要过期键?
Redis 是内存数据库,数据无限增长会导致内存耗尽。因此 Redis 提供了键过期与删除机制,确保内存可控。
常见应用场景有:
- 验证码、临时缓存(短生命周期数据)
- Session / Token 管理(自动过期失效)
- 缓存雪崩防护(TTL 加随机)
- 数据热点控制(避免缓存击穿)
二、过期键删除的三种策略
策略
| 触发方式 | 优点 | 缺点 | Redis 是否采用 |
定时删除 | 定时器到期立即删 | 内存释放及时 | 占用 CPU 过大 | |
惰性删除 | 客户端访问时检查 | CPU 友好 | 内存可能浪费 | |
定期删除 | 后台定期随机抽查 | 折中 CPU+内存 | 参数调优复杂 | |
内存淘汰 | 内存不足时触发 | 保证可写入 | 删除未过期键 | (补充机制) |
Redis 实际采用 惰性删除 + 定期删除,并在内存不足时触发 淘汰策略。
三、Java 中设置过期时间
Jedis jedis = new Jedis("localhost", 6379);
// 1. 设置值并指定过期时间(秒)
jedis.setex("user:1001", 60, "Tom");
// 2. 设置毫秒过期
jedis.psetex("user:1002", 3000, "Jerry");
// 3. 给已有键设置过期时间
jedis.set("order:12345", "pending");
jedis.expire("order:12345", 3600); // 1 小时
// 4. 查看剩余 TTL
System.out.println("TTL user:1001 = " + jedis.ttl("user:1001"));
四、惰性删除示例
惰性删除在 访问键时 才会触发。
jedis.setex("temp:data", 5, "123"); // 5 秒过期
try { Thread.sleep(6000); } catch (InterruptedException e) { }
String val = jedis.get("temp:data"); // null,Redis 自动删除
System.out.println("Value after expire: " + val);
五、定期删除示例
Redis 后台线程会定期扫描部分键。
可通过 INFO stats 查看统计数据:
String info = jedis.info("stats");
System.out.println(info); // 含 expired_keys、evicted_keys 等指标
如果想调整清理频率,可在 redis.conf 中修改:
hz 50 # 提高后台任务频率(默认 10)
六、大对象删除:DEL vs UNLINK
- DEL:同步删除,可能阻塞 Redis。
- UNLINK:异步删除,适合大对象。
// 构建一个大 Hash
for (int i = 0; i < 100000; i++) {
jedis.hset("big:hash", "field" + i, String.valueOf(i));
}
// 异步删除(推荐)
jedis.unlink("big:hash");
七、缓存雪崩防护(TTL 随机化)
如果大量缓存同时过期,可能导致雪崩。解决办法是给 TTL 加上随机值:
import java.util.Random;
Random rand = new Random();
int ttl = 300 + rand.nextInt(60); // 300~360 秒
jedis.setex("cache:user:1001", ttl, "cached-data");
八、Session / Token 管理示例
常见的用户认证场景:
// 登录后生成 Token(30 分钟有效)
String token = "abcd1234";
jedis.setex("token:" + token, 1800, "user:1001");
// 校验 Token
String userId = jedis.get("token:" + token);
if (userId != null) {
System.out.println("Token 有效, userId = " + userId);
} else {
System.out.println("Token 已过期");
}
九、监控过期与淘汰情况
// 获取 Redis stats
String stats = jedis.info("stats");
// 打印过期和淘汰指标
for (String line : stats.split("\n")) {
if (line.contains("expired_keys") || line.contains("evicted_keys")) {
System.out.println(line.trim());
}
}
输出示例:
expired_keys:12034
evicted_keys:456
十、应用启示
- 验证码/临时数据 → 使用 setex,惰性删除即可
- 高并发缓存 → TTL 加随机,避免雪崩
- 大对象删除 → UNLINK 而不是 DEL
- Session/Token → Redis 过期机制天然适合
- 生产必配 → maxmemory-policy(如 allkeys-lru)
- 监控必做 → 定期关注 expired_keys、evicted_keys
十一、总结
Redis 的过期机制并不是“立即删除”,而是多策略协同:
惰性删除 + 定期删除 → 保证性能与内存之间的平衡
内存淘汰策略 → 保证系统在高压下仍能运行
在 Java 开发中,通过 Jedis 很容易实现 TTL 控制,同时结合业务特点(如防雪崩、Session 管理、大对象异步删除),能构建更稳定的缓存体系。
猜你喜欢
- 2025-10-23 Linux基础知识_Linux基础知识点
- 2025-10-23 干货:Java 开发高频 Linux 命令(按场景分)
- 2025-10-23 使用Java删除Excel指定行或列_java列表删除指定位置元素
- 2025-10-23 Java:在 Excel 工作表中创建、修改和删除表格
欢迎 你 发表评论:
- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)


本文暂时没有评论,来添加一个吧(●'◡'●)