优于使用弹簧缓存而不是Spring数据存储库用于Pivotal GemFire

时间:2017-12-04 06:41:10

标签: caching repository-pattern gemfire spring-cache spring-data-gemfire

SDG( Spring Data GemFire )是Spring Cache(GemfireCacheManager)和Spring Data(GemfireTemplate)用于GemFire的库或框架。

使用其中一种是否存在明显的缺陷/优势?

使用基础数据作为具有OQL功能的回购的基本 需要 可以是差异化因素,GemfireTemplate可以提供{{1} }}也可以作为finder methods,更像是cache lookup

另一方面,search提供了基本缓存操作(get / put)的开箱即用功能。如果我们想使用spring-cache执行此操作,则必须编写自定义代码。

GemfireTemplate technically使用spring-cache是否有理想的用例,反之亦然?

1 个答案:

答案 0 :(得分:0)

嗯,“缓存”和“数据访问”模式(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协议。

SDG的Contacts Application 参考实施(RI)中的caching-example就是这样做的。它geocodes a physical address为地理坐标(经度/纬度)以及reverse geocodes coordinates返回物理地址。 GeocodingRepositoryGeocodingService的{​​{3}})是used用于地理编码,可以对Google的Maps API进行REST API调用。

显然,地址的地理坐标不会经常改变,并且是缓存的主要候选者。

相反,通过一般数据访问(CRUD +查询等),您使用的是SDG提供的wrapper around Google's Maps API,或者更好的是o.s.d.g.GemfireTemplate抽象和SDG提供的SD Repository访问数据存储作为基础“记录系统”(SOR),而不是作为缓存。因此,在这种情况下,GemFire将成为您数据库的合适替代品,数据访问模式与缓存相比,与针对您的数据的目标问题无关。例如:

interface CustomerRepository extends CrudRepository<Customer, Long> {

  List<Customer> findAllByContactEventsTimestampGreaterThanAndAddressCityIn(LocalDateTime timestamp, Collection<String> cities);

}

很酷的是,使用SD的Repository抽象,我可以通过对extension的某些conventions来表达非常简单或复杂的查询。

无论如何,缓存与存储库是两个独立的东西,甚至可以合并。

希望这有帮助!

-John