对于最新稳定版本,请使用 Spring Framework 7.0.6spring-doc.cadn.net.cn

理解缓存抽象

缓存与缓冲区

术语“缓冲区”(buffer)和“缓存”(cache)往往被互换使用。然而请注意,它们实际上代表不同的概念。传统上,缓冲区被用作快速实体与慢速实体之间数据传输的中间临时存储。由于其中一方必须等待另一方(这会影响性能),缓冲区通过允许一次性传输整个数据块而非小块数据来缓解这一问题。数据仅从缓冲区写入和读取一次。此外,缓冲区至少对知晓其存在的某一方是可见的。spring-doc.cadn.net.cn

另一方面,缓存根据定义是透明的,通信双方均 unaware(不知道)缓存的存在。它同样能提升性能,但其方式是允许多次以快速的方式读取相同的数据。spring-doc.cadn.net.cn

你可以在此处找到关于缓冲区(buffer)和缓存(cache)之间差异的进一步解释。spring-doc.cadn.net.cn

其核心在于,缓存抽象将缓存应用于 Java 方法,从而根据缓存中已有的信息减少方法的执行次数。也就是说,每次调用目标方法时,该抽象会应用一种缓存行为,检查对于给定的参数,该方法是否已经被调用过。如果已经调用过,则直接返回缓存的结果,而无需再次执行实际的方法;如果尚未调用过,则执行该方法,将其结果缓存并返回给用户,以便下次使用相同参数调用该方法时,可以直接返回缓存的结果。通过这种方式,对于给定的一组参数,那些开销较大的方法(无论是 CPU 密集型还是 I/O 密集型)只需执行一次,之后便可重复使用缓存结果,而无需再次实际调用该方法。整个缓存逻辑是透明应用的,对调用方没有任何干扰。spring-doc.cadn.net.cn

这种方法仅适用于那些对于给定输入(或参数)无论调用多少次都能保证返回相同输出(结果)的方法。

缓存抽象提供了其他与缓存相关的操作,例如更新缓存内容或移除一个或所有条目。如果缓存处理的数据在应用程序运行过程中可能发生更改,这些操作将非常有用。spring-doc.cadn.net.cn

与 Spring 框架中的其他服务一样,缓存服务是一种抽象(而非缓存实现),需要使用实际的存储来保存缓存数据——也就是说,该抽象使你无需编写缓存逻辑,但并不提供实际的数据存储。这种抽象通过 org.springframework.cache.Cacheorg.springframework.cache.CacheManager 接口得以具体化。spring-doc.cadn.net.cn

Spring 提供了该抽象的几种实现: 基于 JDK java.util.concurrent.ConcurrentMap 的缓存、Gemfire 缓存、 Caffeine,以及符合 JSR-107 规范的缓存(例如 Ehcache 3.x)。 有关如何集成其他缓存存储和提供者的更多信息,请参见接入不同的后端缓存spring-doc.cadn.net.cn

缓存抽象层对多线程和多进程环境没有特殊处理,因为此类功能由缓存实现本身负责处理。

如果你处于多进程环境(即应用程序部署在多个节点上), 你需要相应地配置你的缓存提供程序。根据你的使用场景,在多个节点上保存同一数据的副本可能就足够了。 然而,如果在应用程序运行过程中需要修改数据,则可能需要启用其他传播机制。spring-doc.cadn.net.cn

缓存特定项直接等同于在编程式缓存交互中常见的“先获取,若未找到则执行操作并最终放入缓存”的代码块。 不会应用任何锁机制,多个线程可能会并发地尝试加载同一项。 驱逐(eviction)操作也是如此。如果多个线程并发地尝试更新或驱逐数据,你可能会使用到过期的数据。某些缓存提供者在此方面提供了高级特性。更多详细信息,请参阅你所使用的缓存提供者的文档。spring-doc.cadn.net.cn

要使用缓存抽象,您需要注意两个方面:spring-doc.cadn.net.cn