You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot如何每小时更新缓存随机数 附代码正确性校验

原代码问题说明

原实现无法满足需求,存在4个核心问题:

  • 定时任务间隔配置错误:fixedDelay = 36000对应的间隔是36秒,1小时对应的毫秒值应为3600000;且默认@Scheduled不会在服务启动时执行,首次请求会直接穿透到随机数生成逻辑,服务启动后的第一个小时内缓存不会自动更新。
  • 缓存key未显式指定:@Cacheable和@CachePut默认基于方法参数生成key,虽然当前两个方法都无参不会出错,但后续如果给方法加参数,会直接导致缓存读写不匹配,出现读不到值、更新错缓存的问题。
  • 随机数生成器性能差:每次生成随机数都新建Random实例,既没必要,多线程场景下还可能出现随机数序列重复的问题。
  • 缺少定时任务开关:如果项目没有在启动类/配置类上加@EnableScheduling注解,定时更新逻辑完全不会生效,缓存只会在第一次请求时生成后永久不更新(除非缓存自身配置了过期时间)。
更高效的修正实现

核心优化思路是提前预热缓存、统一缓存规则、复用基础组件,完全满足“请求直接读缓存、每小时自动更新”的要求:

  1. 首先在项目启动类或任意配置类上添加@EnableScheduling注解,开启定时任务能力。
  2. 修正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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 22:27:19