1

理解缓存抽象

缓存与缓冲区

术语“缓冲区”和“缓存”往往可以互换使用,但是请注意,它们代表不同的东西。传统上,缓冲区用作数据在快实体和慢实体之间的中间临时存储,由于一方必须等待另一方(这会影响性能),缓冲区允许整个数据块(而不是小块)同时移动,从而缓解了这种情况。数据只从缓冲区写入和读取一次,此外,至少有一方知道缓冲区是可见的。

另一方面,缓存根据定义是隐藏的,并且任何一方都不知道缓存的发生,它还提高了性能,但是通过让相同的数据以快速方式多次读取来提高性能。

你可以在这里找到关于缓冲区和缓存之间差异的进一步解释。

缓存抽象的核心是将缓存应用于Java方法,从而根据缓存中可用的信息减少执行的次数,也就是说,每次调用目标方法时,抽象都会应用缓存行为,检查给定参数的方法是否已经执行。如果已执行,则返回缓存的结果,而不必执行实际的方法,如果方法尚未执行,则执行该方法,并缓存结果并返回给用户,以便在下次调用该方法时返回缓存的结果。这样,对于给定的一组参数,昂贵的方法(无论是CPU绑定的还是IO绑定的)只能执行一次,并且结果可以重用,而不必实际再次执行该方法,缓存逻辑被透明地应用,没有任何对调用程序的干扰。

这种方法只适用于保证为给定输入(或参数)返回相同输出(结果)的方法,无论执行了多少次。

缓存抽象提供了其他与缓存相关的操作,比如更新缓存内容或删除一个或所有条目的能力,如果缓存处理的数据在应用程序运行过程中可能发生更改,那么这些方法非常有用。

与其他在Spring Framework中的服务,缓存服务是一个抽象(不是缓存实现),需要使用实际的存储来存储缓存数据 — 也就是说,抽象使你不必写缓存逻辑但不提供实际的数据存储。这个抽象是由org.springframework.cache.Cacheorg.springframework.cache.CacheManager接口实现。

Spring提供了该抽象的一些实现:JDK 基于缓存的java.util.concurrent.ConcurrentMapEhcache 2.x、Gemfire缓存、Caffeine和JSR-107兼容缓存(例如Ehcache 3.x)。

缓存抽象对多线程和多进程环境没有特殊的处理,因为这些特性是由缓存实现来处理的。

如果你有一个多进程环境(即部署在多个节点上的应用程序),则需要相应地配置缓存提供程序,根据你的用例,在多个节点上复制相同的数据就足够了,但是,如果在应用程序过程中更改数据,则可能需要启用其他传播机制。

缓存特定的项与通过编程缓存交互找到的典型get-if-not-found-then- proceed-and-put-eventually代码块是直接等价的,没有应用锁,几个线程可能试图同时加载相同的项,这同样适用于驱逐。如果多个线程试图同时更新或驱逐数据,则可以使用陈旧数据,某些缓存提供程序在该领域提供高级特性,有关详细信息,请参阅缓存提供程序的文档。

要使用缓存抽象,你需要考虑两个方面:

  • 缓存声明:标识需要缓存的方法及其策略。
  • 缓存配置:存储数据并从中读取数据的后备缓存。


博弈
2.5k 声望1.5k 粉丝

态度决定一切