【问题标题】:EclipseLink JPA with App Engine: cache synchronizationEclipseLink JPA 与 App Engine:缓存同步
【发布时间】:2017-01-30 14:58:18
【问题描述】:

我有一个 App Engine 项目,它使用 EclipseLink 作为 JPA 持久性管理器,将数据持久保存在 Cloud SQL 实例中。

由于 App Engine(多实例环境)的性质,我们对如何在实例之间同步 JPA 缓存有些担忧。

每个 JPA 实例在单个 App Engine 实例中运行,因此不使用 App Engine 的 Memcache 服务(否则,EclipseLink 不“知道” App Engine memcache 是什么或如何使用它)

这是一个简单的场景示例:

- Instance A read object 1: value="A"
- Instance B read object 1: value="A"

- Instance A write object 1: value="B"
- JPA cache of Instance A is evicted due to write operation

- Instance A read object 1: value="B" (the value is retrieved from the database because cache has been evicted after write operation)
- Instance B read object 1: value="A" (no write operation has been performed, the cache is still valid so the value has not been updated)

四处搜索这种行为,我发现了不同的文章,它们都在谈论这个 [1] [2] [3] [4]。

我引用:

除非数据库由其他应用程序直接修改,或由 集群环境中其他服务器上的相同应用程序

由于 App Engine 的本质,为此我们可以将其视为“集群环境中的其他服务器”,因此情况似乎就是这样。

当然,关于如何处理这个问题的正确方法应该是为 JPA 构建一个缓存层,该缓存层构建在 App Engine 内存缓存服务之上,但根据我的搜索,我了解到 EclipseLink 不允许开发自定义缓存层。 我可以构建一些可以在 EclipseLink 和 App Engine 内存缓存之间架起桥梁的东西,但是如果有正确的“钩子”来说明如何做,我找不到任何参考。

从文档中关于如何处理这个问题的建议很少:

  • 禁用共享缓存:由于失去应用程序性能,这不是一个合适的选项

  • 使用分布式缓存(例如带有 Oracle Coherence 的 Oracle TopLink Grid): 我想使用 App Engine 内存缓存服务,但据我了解,没有我们可以使用的 EclipseLink“挂钩”

  • 使用缓存协调(同步缓存,如本例所述) 提供的方法似乎不适用于 App Engine 环境

是否有关于如何正确处理此缓存方案的已知解决方案? 这里的场景很清楚,当在实例内部进行写操作时,所有现有的 JPA 缓存也需要“通知”以驱逐自己的缓存。

[1]https://wiki.eclipse.org/EclipseLink/Examples/JPA/CacheCoordination

[2]http://www.eclipse.org/eclipselink/documentation/2.5/concepts/cache011.htm

[3]https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Caching/Coordination

[4]https://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching#Caching_in_Clustered_Environments

【问题讨论】:

    标签: java google-app-engine jpa caching eclipselink


    【解决方案1】:

    我查看了 EclipseLink (EL) 源代码,看看是否有任何简单的方法可以扩展缓存协调机制以使用 GAE。

    EL 默认支持 JMS 和 RMI,并且缓存协调是围绕远程处理构建的,因此 EL 可以发送命令 (org.eclipse.persistence.sessions.coordination.Command),这些命令在集群中的每个主机上针对 AbstractSession 执行。

    我认为没有任何方法可以使用 MemCache 进行缓存,因为像 MergeChangeSetCommand 这样的命令总是在 AbstractSession 上运行。

    可以构建自己的缓存协调协议,这是通过扩展org.eclipse.persistence.sessions.coordination.TransportManager 并设置eclipselink.cache.coordination.protocol=com.example.MyTransportManager 来完成的,但DiscoveryManager 使用通常在云中不可用的多播。如果您可以发现所有 GAE 实例(并将数据直接发送到每个节点),我认为可以创建一个基于 http 的缓存协调解决方案。在 AWS 上,可以向负载均衡器询问节点列表,当我们需要使用 Hazelcast 进行节点内通信时,这就是我们解决多播问题的方法。

    【讨论】:

    • If you could discover all your GAE instances 在 App Engine 中,这只能使用基本或手动缩放,无法直接处理自动缩放中的实例。您可以阅读文档linkInstances are anonymous.。我正在寻找一种直接实现已经是同步服务的 App Engine Memcache 服务的方法
    • 在我写的时候,我很确定你不能使用 MemCache 作为 EclipseLink 的二级缓存。 JPA 是 JavaEE 规范的一部分,它并不是真正为云设计的。我认为您唯一的选择是禁用共享缓存,并为您经常访问的内容进行一些自定义缓存 - 我们通常会这样做。
    猜你喜欢
    • 2011-03-29
    • 2014-01-22
    • 2012-11-17
    • 2016-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多