嗯,“缓存”和“数据访问”模式(CRUD + 查询等)实际上是两个不同的问题。
正如Spring docs 解释的那样,缓存本质上是一种在给定相同输入、返回相同输出或结果时降低调用应用程序服务操作(Spring 中的Java 类“方法”)成本的方法。
可以通过多种不同方式衡量成本,但基本上归结为 CPU 利用率、IO 活动(例如磁盘/存储访问)、网络(例如,对远程服务进行 REST API 调用,例如使用 Google 的 Maps API 对地址进行地理编码, for instance) 等。
通过将经常或最近使用的结果缓存在内存中,应用程序的响应速度会更快。当然,开发人员必须小心,因为他/她是以使用更多内存(即资源利用率)为代价来换取性能(即延迟),因此开发人员必须对保存在内存中的内容更具选择性,这就是为什么缓存通常使用 LRU 或 LFU 算法根据使用情况维护缓存中最相关的条目。结合其他策略(过期(TTL 或 TTI)、驱逐、压缩、使用本机内存等)可以提供帮助。此外,开发人员必须牢记其他因素,例如处理陈旧数据或更新时使条目无效等。
Spring Data GemFire 可以position(另见this;首选)Pivotal GemFire 作为Spring's Cache Abstraction 中的“缓存提供程序”,它使用 Spring 的 OOTB AOP 实现后备模式框架。比如……
@Service
class CustomerService {
Autowired
CustomerRepository customerRepository;
@Cacheable("Customers")
Customer findBy(Long id) {
...
return customerRepository.findBy(id);
}
}
在此示例中,CustomerRepository 可能由 RDBMS 支持,而 GemFire 可能是缓存提供程序。
当然,CustomerService 类可能正在对远程服务进行 REST API 调用,考虑到它涉及网络和 HTTP 协议,这可能是一项代价高昂的操作。
我在Contacts Application 中的caching-example 参考实施 (RI) 的 SDG 就是这样做的。它将geocodes a physical address 转换为地理坐标(经度/纬度),并将reverse geocodes coordinates 转换回物理地址。 GeocodingRepository(used by GeocodingService)是用于地理编码的wrapper around Google's Maps API,它使 REST API 调用 Google 的 Maps API。
显然,地址的地理坐标不会经常更改,并且是缓存的主要候选者。
相反,对于一般数据访问(CRUD + 查询等),您使用 SDG 提供的o.s.d.g.GemfireTemplate,或者更好的是 SDG 提供的SD Repository 抽象和extension 来访问数据存储底层的“记录系统”(SOR),而不是作为缓存。因此,在这种情况下,GemFire 将是您的数据库的合适替代品,并且数据访问模式与缓存的关系比与有关数据的目标问题的关系要小。例如:
interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findAllByContactEventsTimestampGreaterThanAndAddressCityIn(LocalDateTime timestamp, Collection<String> cities);
}
很酷的是,使用 SD 的 Repository 抽象,我可以通过遵循某些 conventions 来表达非常简单或复杂的查询,对于 example。
无论如何,缓存与存储库是两个独立的东西,甚至可以组合在一起。
希望这会有所帮助!
-约翰