必须在写入缓存时为每个 key 主动计算带偏移的 ttl,禁用全局 entryttl 配置,通过 redistemplate 手动控制并封装 jitter 工具方法,推荐扰动范围为基础 ttl 的 10%~20%,使用 threadlocalrandom 生成偏移并校验 ttl > 0。

不能靠配置“自动”加随机过期时间,必须在写入缓存时主动为每个 key 计算带偏移的 TTL。
别用全局统一 TTL
@Cacheable 默认不设过期时间,一旦通过 RedisCacheConfiguration 统一配了 entryTtl,所有 key 就会严格按同一倒计时失效——哪怕只差几毫秒写入,也可能因系统时钟精度或批量预热导致大量 key 在同一秒过期。这不是理论风险,是线上高频事故源。
- 禁用 RedisCacheConfiguration.setEntryTtl() 这类全局设定
- 停用 @Cacheable 的 cacheManager 自动装配,改用自定义 CacheManager 包装 RedisCache
- 确保每个缓存写入动作都经过可控逻辑,而非框架隐式触发
每个 key 单独算随机 TTL
基础时间(比如 3600 秒)加上一个合理范围内的随机扰动值,才是有效分散失效压力的核心。偏移量不是越大越好,得匹配业务容忍度。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 推荐扰动范围为基础 TTL 的 10%~20%:3600 秒可配 ±360 秒,86400 秒(1 天)可配 ±1800 秒(30 分钟)
- 用 ThreadLocalRandom.current().nextLong(0, jitterRange) 生成偏移,避免 new Random(System.currentTimeMillis()) 在高并发下重复种子
- 务必校验最终 TTL > 0,防止负数导致 key 立即过期
绕过 @Cacheable,用 RedisTemplate 手动控制
Spring Cache 抽象层不支持 per-key 动态 TTL,必须下沉到 RedisTemplate 层做精确控制。
- 封装工具方法,如 setWithJitter(String key, Object value, long baseSeconds, long maxJitter)
- 调用 redisTemplate.opsForValue().set(key, value, Duration.ofSeconds(baseSeconds + jitter), TimeUnit.SECONDS)
- 若用 Jedis,对应使用 jedis.setex(key, (int) actualSeconds, value),注意类型转换和整型溢出
补救存量 key 用 Lua 脚本(慎用)
已有大批固定 TTL 的 key 且无法重启应用?可用 Lua 原子批量补随机过期时间,但仅限应急,不可作为日常方案。
- 脚本内用 math.random()(Redis 7.0+ 支持),避免依赖 time() 构造种子
- SCAN 操作必须加 COUNT 限流(如 COUNT 500),防阻塞主线程
- 先在测试环境验证,再用 redis-cli --eval 执行,严禁直接线上硬跑
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










