嗯。
首先,很难准确描述您遇到了什么问题,但我几乎可以肯定它与 Spring Data 或技术上的 Spring's Cache Abstraction 在这种情况下几乎没有关系(尤其是因为您使用 @Cacheable 注释提到“缓存”),而不是说 Pivotal GemFire 本身,或者更可能在您的应用程序域模型中。
其次,您遇到的问题与上面显示的配置关系不大。本质上,在您的配置中,您正在为应用程序服务方法上声明的@Cacheable 注释中标识的每个缓存创建一个“对等”Cache 实例以及Regions,这在这种情况下并不是特别有趣。
提示:关于配置,最好这样做:
@SpringBootApplication
@EnableCachingDefinedRegions
public class MyCachingSpringBootApplication { ... }
有关详细信息,请参阅 here、here 和 here。
注意:SBDG 默认创建 ClientCache 实例,不是“对等”Cache 实例。如果您确实希望您的 Spring 应用程序包含一个嵌入式对等点 Cache 实例并成为服务器集群的一部分,那么您还可以通过声明@PeerCacheApplication 注释。有关详细信息,请参阅here。
接下来,您提到您“覆盖”了 equals 和 hashCode,这似乎表明您正在使用一些复杂的密钥。一般来说,使用 Pivotal GemFire 时最好保留简单的键类型,例如 Long、Integer、String 等,原因类似于您遇到的情况。
如果您需要影响整个集群的分区策略或数据组织(例如,可能是为了搭配),一个更好的选择是实施 GemFire 的 PartitionResolver 并将其注册到 PR。
但是,您的可缓存服务方法如下所示并不少见:
@Cacheable("CustomersByAccount")
Account findBy(Customer customer) { ... }
你可能很清楚,上面显示的@Cacheable“findBy”服务方法的“key”是Customer,这显然是一个复杂的对象,必须有一个有效的equals和hashCode方法当用作 GemFire 缓存区域中的键,用于备份应用程序缓存“CustomersByAccount”。
几个问题:
是否有可能 A) 您的复杂键的类定义(例如 Customer)已更改,例如通过添加/删除 [new] 字段或更改字段类型 (?) 和 B) 您的支持缓存的分区区域(例如“CustomersByAccount”)是持久的?
您的equals 和hashCode 方法是否一致?那就是他们声明并使用相同的字段来确定equals和hashCode的结果?
例如,这将是无效的:
class Customer {
private Long id;
private String firstName;
private String lastName;
...
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Customer)) {
return false;
}
Customer that = (Customer) obj;
return this.id.equals(that.id);
}
@Override
public int hashCode() {
int hashValue = 17;
hashValue = 37 * hashValue + this.firstName.hashCode();
hashValue = 37 * hashValue + this.lastName.hashCode();
return hashValue;
}
...
}
或任何其他组合,其中equals/hashCode 可能会根据先前存储在 GemFire 中的状态产生不同的结果。
您也可以尝试清除缓存并重新补水(根据需要急切地或懒惰地),特别是如果您的类定义已更改,尤其是如果其中一些类类型用作键。
另外,一般来说,如果无法严格遵守简单/标量类型(例如Long 或String),我会尽可能推荐不可变键。
也许,如果您可以在您的应用程序域模型类中分享更多细节,例如用作键的类型,以及您在服务方法上使用 Spring 的缓存抽象,这可能会有所帮助。
此外,非常感谢任何重现该问题的示例或测试用例。
谢谢!