Spring Boot如何每小时更新缓存随机数 附代码正确性校验
原代码问题说明
原实现无法满足需求,存在4个核心问题:
- 定时任务间隔配置错误:
fixedDelay = 36000对应的间隔是36秒,1小时对应的毫秒值应为3600000;且默认@Scheduled不会在服务启动时执行,首次请求会直接穿透到随机数生成逻辑,服务启动后的第一个小时内缓存不会自动更新。 - 缓存key未显式指定:
@Cacheable和@CachePut默认基于方法参数生成key,虽然当前两个方法都无参不会出错,但后续如果给方法加参数,会直接导致缓存读写不匹配,出现读不到值、更新错缓存的问题。 - 随机数生成器性能差:每次生成随机数都新建
Random实例,既没必要,多线程场景下还可能出现随机数序列重复的问题。 - 缺少定时任务开关:如果项目没有在启动类/配置类上加
@EnableScheduling注解,定时更新逻辑完全不会生效,缓存只会在第一次请求时生成后永久不更新(除非缓存自身配置了过期时间)。
更高效的修正实现
核心优化思路是提前预热缓存、统一缓存规则、复用基础组件,完全满足“请求直接读缓存、每小时自动更新”的要求:
- 首先在项目启动类或任意配置类上添加
@EnableScheduling注解,开启定时任务能力。 - 修正Service层代码如下:
@Service public class TestService { // 线程安全的全局随机数生成器,单例复用,避免重复创建对象的开销 private static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current(); private static final String CACHE_NAME = "randomvalue"; // 显式指定缓存key,避免隐式生成规则带来的不确定性 private static final String CACHE_KEY = "'active_random'"; private int createRandomValue() { return RANDOM.nextInt(100); } @Cacheable(value = CACHE_NAME, key = CACHE_KEY) public int getRandomValue() { // 兜底逻辑:仅在缓存意外失效、定时任务异常时触发,正常请求不会执行到这里 return createRandomValue(); } // 服务启动后立即执行一次初始化缓存,之后每1小时固定触发一次更新 @CachePut(value = CACHE_NAME, key = CACHE_KEY) @Scheduled(initialDelay = 0, fixedRate = 3600000) public int updateRandomValue() { return createRandomValue(); } }
实现优势
- 无请求穿透:服务启动时就会生成第一个随机值写入缓存,所有GET请求都直接读缓存,不会触发随机数生成逻辑。
- 更新逻辑稳定:用
fixedRate替代fixedDelay,严格按1小时间隔触发更新,不会受方法执行耗时影响间隔。 - 性能更高:复用
ThreadLocalRandom实例,多线程场景下无锁竞争,也减少了对象创建和GC开销。 - 容错性强:就算缓存服务故障、定时任务执行异常,
getRandomValue的兜底逻辑也能正常返回值,不会直接报错。
不建议用缓存TTL过期自动更新的方案:这种方案下缓存过期后的第一个用户请求会触发随机数生成,不符合“请求不执行生成逻辑”的要求,主动定时更新是更贴合需求的方案。
内容的提问来源于stack exchange,提问作者mattsmith5
相关产品推荐
相关产品推荐

