【问题标题】:How Spring Caching works?Spring 缓存是如何工作的?
【发布时间】:2018-10-15 23:51:34
【问题描述】:

@Cacheable 注解如何通知数据库的变化。例如:如果我通过 @Cacheable 注释函数调用来缓存 CRUDRepository.findAll() 函数调用的结果,则结果存储在命名缓存中。然而,缓存会继续随着数据库的变化而更新。考虑下面的例子:

@Cacheable(value = "employee", key = "#id")
public Iterable<Employee> getAllEmployees(){                 
    long startTime = System.currentTimeMillis();
    Iterable<Employee>  itr = employeeEntityRepository.findAll();
    long stopTime = System.currentTimeMillis();
    System.out.println("Time-->" + (stopTime - startTime));
    return itr;
}

第一次调用这个方法需要 300 毫秒,第二次调用几乎不需要 5 毫秒,这意味着它缓存了结果集。很公平。但是现在,如果我直接在数据库中更新员工表中的记录并再次调用此方法,则会发生两件事:

  1. 此方法调用返回新记录。
  2. 该方法返回速度非常快。

这意味着缓存每次都从数据库中更新。如果结果集是从 Cache 返回的,这个 Sync 是如何工作的?

谢谢。

【问题讨论】:

  • 您的代码中是否有 CachePut 来更新数据库?
  • 没有。它甚至可以获取您通过 SQL 编辑器放入数据库的记录。
  • 你的缓存什么时候过期或驱逐?
  • 我发现了 Marged。问题出在钥匙上。如果我给出一个常数作为 Key(假设 100),则结果将被缓存,并且不会一次又一次地调用该方法。我想知道这种方法的可能 Key 是什么。
  • @Geek #id 来自哪里。我没有看到该方法的任何输入,它可以放置在哪里?另外,如果您找到解决方案,建议您回答自己的问题。

标签: java spring spring-boot caching


【解决方案1】:

主要问题是:缓存每次都从数据库中更新。如果结果集是从 Cache 返回的,这个 Sync 是如何工作的?

根据 spring doc (5.3.7) @Cacheable 注解在我们需要缓存调用结果时使用。

在上述场景中,将应用缓存行为,检查是否已经为给定参数调用了该方法。

您的示例中使用了以下属性。他们的描述如下:

  1. value : 这个缓存的名字,在上面的例子中是它的“employee”
  2. Key:这是 SpEl,Spring 表达式语言,用于动态计算密钥。

理想情况下,您应该在方法 getAllEmployees() 中将“id”作为方法参数。 但是这个方法好像返回了所有的员工,所以在这个场景中好像是不正确的用法。

SpEl 表达式是 "#id" = 自定义密钥生成器

默认为 "" = 所有方法参数都被视为键。

如果在缓存中没有找到计算键的值,将调用目标方法并将返回值存储在关联的缓存中。

我遇到的场景是@Cacheable注解的方法

    @Cacheable(value= myConstant,key="#accountId")
public Integer getAccountNumber( Integer accountId){. 
// an API call is made here..}

所以,缓存不是从 DB 更新的,它是从调用(API 调用)更新的,当第一次调用方法时,结果存储在缓存中。第二次调用该方法时,返回缓存的结果,不会发生该方法中的API调用。

我已转介:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/cache/annotation/Cacheable.html

【讨论】:

    猜你喜欢
    • 2013-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-15
    • 2017-01-05
    • 2015-12-24
    • 2018-08-01
    相关资源
    最近更新 更多