理解缓存抽象
其核心在于,缓存抽象将缓存应用于 Java 方法,从而根据缓存中可用的信息减少执行次数。也就是说,每次调用目标方法时,抽象都会应用缓存行为,检查该方法是否已针对给定参数被调用。如果已调用,则直接返回缓存结果,无需调用实际方法。如果方法尚未调用,则调用该方法,并将结果缓存并返回给用户,以便下次调用该方法时,返回缓存结果。通过这种方式,开销大的方法(无论是 CPU 密集型还是 IO 密集型)对于给定的一组参数只需调用一次,结果即可重复使用,而无需再次实际调用该方法。缓存逻辑透明地应用,不会对调用者造成任何干扰。
| 这种方法仅适用于那些无论调用多少次,都保证针对给定输入(或参数)返回相同输出(结果)的方法。 |
缓存抽象提供了其他与缓存相关的操作,例如更新缓存内容或删除一个或所有条目的能力。如果缓存处理的数据在应用程序运行过程中可能发生变化,这些操作会很有用。
与 Spring 框架中的其他服务一样,缓存服务是一种抽象(而不是缓存实现),需要使用实际存储来存储缓存数据——也就是说,该抽象使你无需编写缓存逻辑,但它不提供实际的数据存储。这种抽象由 org.springframework.cache.Cache 和 org.springframework.cache.CacheManager 接口实现。
Spring 提供了该抽象的一些实现:基于 JDK java.util.concurrent.ConcurrentMap 的缓存、Gemfire 缓存、Caffeine 以及符合 JSR-107 标准的缓存(例如 Ehcache 3.x)。有关插入其他缓存存储和提供程序的信息,请参阅插入不同的后端缓存。
| 缓存抽象对多线程和多进程环境没有特殊处理,因为此类功能由缓存实现负责处理。 |
如果您处于多进程环境(即,应用程序部署在多个节点上),您需要相应地配置您的缓存提供程序。根据您的用例,在多个节点上复制相同的数据可能就足够了。但是,如果您在应用程序运行过程中更改数据,您可能需要启用其他传播机制。
缓存特定项直接等同于通过编程缓存交互找到的典型“get-if-not-found-then-proceed-and-put-eventually”代码块。不应用锁,并且多个线程可能尝试并发加载同一项。驱逐也适用相同的情况。如果多个线程尝试并发更新或驱逐数据,您可能会使用过时的数据。某些缓存提供程序在该领域提供高级功能。有关更多详细信息,请参阅您的缓存提供程序的文档。
要使用缓存抽象,您需要注意两个方面
-
缓存声明:识别需要缓存的方法及其策略。
-
缓存配置:存储数据并从中读取数据的后端缓存。