【问题标题】:Bypassing the @Cacheable annotation in Production for debugging在生产环境中绕过@Cacheable 注解进行调试
【发布时间】:2018-11-13 17:21:45
【问题描述】:

我正在开发一个基于 Spring 的新项目,我想知道,如果我要使用 Spring 3.1 或 ehcache-spring-annotation 项目中的 @Cacheable 注解,你将如何实现绕过“按需”缓存机制,例如用于生产调试。

假设我的应用程序仅服务于 REST 请求,有时我希望通过单个调用(我手动进行)直接从“数据库”(或任何后端)获取数据并避免任何途中缓存(任何缓存)。在调用运行时,我真的不介意它是否用刚刚从数据库中获得的内容重新填充缓存......

我想听听您对如何实施这一点的想法。

提前感谢您的任何指导,

肯。

【问题讨论】:

  • 您想在完全不同的环境中绕过缓存,还是在生产环境中按需使用而无需重启?
  • 实际上都是。我希望这种机制在开发环境和生产环境中都有用。但它在开发环境中不太重要,因为如果我想调试,我可以简单地重新启动缓存......在生产中我不能只是重新启动它们(如你所说)

标签: java spring caching


【解决方案1】:

也许您可以扩展缓存管理器并在现有检查之外提供布尔表达式。

您可以在控制器中的 ThreadLocal 中设置该布尔值,这样每当调用服务时,该布尔值就到位。

【讨论】:

    【解决方案2】:

    您可以创建一个刷新缓存的方法,并仅在您需要来自 DB 的值时使用调试器运行它。

    @Cacheable(modelId = "i18NTextCacheModel")
    public List<I18NText> loadAll() {
    
        logger.debug("loadAll called");
        ...
    }
    
    @CacheFlush(modelId = "i18NTextFlushModel")
    public Long save(I18NText entity) {
    
        logger.debug("save called");
        ...
    }
    

    【讨论】:

    • 我想你误解了我的意思。假设我有一个带有 @Cachealbe 注释的 getItem({...}) 。我希望代码正常运行,但是当带有注释的方法运行时,我想实际上忽略缓存并直接进入数据库..我不想手动运行任何方法,因为我想编写代码以继续运行正常。
    • 如果在带有注释的方法运行之前刷新缓存,这正是将会发生的事情。可以在代码中写——if(debug){//flush the cache}
    • 你的意思是把这个 if(debug){//flush} 写入注解代码本身?否则我看不到如何控制注释是否运行..
    【解决方案3】:

    与@Bozho 建议的结果相似 如果传入请求参数refresh-cache=true,则绕过缓存

    我扩展了 DefaultRedisCacheWriter 并将其用作 CacheWriter

        RedisCacheManager cacheManager = RedisCacheManager
                .builder(new RefreshableRedisCacheWriter(redisConnectionFactory()))
                .cacheDefaults(cacheConfiguration)
                .build();
    

    覆盖此 writer 中的 get() 方法

    @Override
    public byte[] get(String name, byte[] key) {
    
        Assert.notNull(name, "Name must not be null!");
        Assert.notNull(key, "Key must not be null!");
    
        HttpServletRequest request = ApiRequestContext.getRequestContext();
        if (Boolean.valueOf(request.getParameter("refresh-cache"))) {
            logger.info("bypassing cache for key: {}", key);
            return null;
        }
    
        return execute(name, connection -> connection.get(key));
    }
    

    ApiRequestContext 是自定义的请求对象,这里存储在线程本地。 请注意,当该方法返回 null 时,会从 db 中获取值并放回缓存中,从而有效地刷新缓存。

    【讨论】:

      猜你喜欢
      • 2011-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-28
      • 2016-06-14
      • 2017-08-13
      • 1970-01-01
      相关资源
      最近更新 更多