Caching Gemfire缓存引发PartionedRegionException:对象哈希代码在对等方之间不一致
当在gemfire中使用分区缓存并使用可缓存注释与spring数据集成时,它会将数据正确地放入缓存中,但当从缓存中检索时,如果密钥位于不同的分区上,则会引发PartitionedRegionException,表示缓存对等方之间的哈希代码不一致。我已经重写了类中的equals和hashCode方法,该类的对象是缓存的键。知道我哪里会出错吗?两个缓存对等点位于同一台计算机上。定位器从外部启动。 我正在使用以下方法启动缓存Caching Gemfire缓存引发PartionedRegionException:对象哈希代码在对等方之间不一致,caching,gemfire,spring-data-gemfire,Caching,Gemfire,Spring Data Gemfire,当在gemfire中使用分区缓存并使用可缓存注释与spring数据集成时,它会将数据正确地放入缓存中,但当从缓存中检索时,如果密钥位于不同的分区上,则会引发PartitionedRegionException,表示缓存对等方之间的哈希代码不一致。我已经重写了类中的equals和hashCode方法,该类的对象是缓存的键。知道我哪里会出错吗?两个缓存对等点位于同一台计算机上。定位器从外部启动。 我正在使用以下方法启动缓存 @Bean @Primary Cache getGemfireCache(
@Bean
@Primary
Cache getGemfireCache() {
Cache cache = new CacheFactory().create();
RegionFactory<Object,Object> regionFactory = cache.createRegionFactory(RegionShortcut.PARTITION);
allCacheNames.forEach(cacheName -> regionFactory.create(cacheName));
return cache;
}
@Bean
@初级的
缓存getGemfireCache(){
Cache Cache=new CacheFactory().create();
RegionFactory RegionFactory=cache.createRegionFactory(RegionShortcut.PARTITION);
所有cacheName.forEach(cacheName->regionFactory.create(cacheName));
返回缓存;
}
任何帮助都将不胜感激
谢谢 Hmmm
首先,很难准确地描述您遇到的问题,但我几乎可以肯定,与Spring数据相比,它与Spring数据的关系很小,或者在技术上,在这种情况下(特别是因为您提到了使用注释的“缓存”),而与Pivotal GemFire本身的关系不大,或者更可能与您的应用程序域模型的关系不大
其次,您遇到的问题与上面显示的配置关系不大。基本上,在您的配置中,您正在为应用程序服务方法上声明的@Cacheable
注释中标识的每个缓存创建一个“对等”缓存
实例以及区域
,在本例中,这不是特别有趣的
提示:关于配置,最好这样做:
@springboot应用程序
@EnableCachingDefinedRegions
公共类MyCachingSpringBootApplication{…}
有关详细信息,请参见和
注意:默认情况下,SBDG创建一个ClientCache
实例,而不是一个“对等”Cache
实例。如果您确实希望Spring应用程序包含嵌入式对等缓存
实例并成为服务器集群的一部分,那么您还可以通过声明@peerCache
注释来覆盖SBDG自动配置客户端缓存
实例的首选项。有关更多详细信息,请参阅
接下来,您提到您“覆盖”了equals和hashCode,这似乎表明您正在使用一些复杂的键。一般来说,在使用GemFire时,最好使用简单的键类型,例如
Long
、Integer
、String
,等等,原因与您的经历类似
如果您需要影响整个集群的分区策略或数据组织(例如,可能用于配置),那么更好的选择是实现GemFire并向PR注册
但是,可缓存服务方法的外观如下所示并不少见:
@Cacheable(“CustomerByAccount”)
由(客户){…}查找的帐户
您可能很清楚,上面显示的@Cacheable
“findBy”服务方法的“key”是Customer
,这显然是一个复杂的对象,当用作GemFire缓存区域中的key时,必须具有有效的等于和hashCode
方法,用于支持应用程序缓存“CustomerByAccount”
有几个问题:
A)您的复杂密钥的类定义(如Customer
)是否可能发生更改,例如通过添加/删除[new]字段或更改字段类型(?),以及B)支持缓存的分区区域(如“CustomerByAccount”)是否持久
您的equals
和hashCode
方法是否一致?也就是说,它们声明并使用相同的字段来确定equals
和hashCode
的结果
例如,这是无效的:
class客户{
私人长id;
私有字符串名;
私有字符串lastName;
...
@凌驾
公共布尔等于(对象obj){
if(this==obj){
返回true;
}
如果(!(客户的obj实例)){
返回false;
}
客户,即=(客户)obj;
返回this.id.equals(that.id);
}
@凌驾
公共int hashCode(){
int hashValue=17;
hashValue=37*hashValue+this.firstName.hashCode();
hashValue=37*hashValue+this.lastName.hashCode();
返回哈希值;
}
...
}
或者等于
/hashCode
的任何其他组合可能会产生不同的结果,具体取决于之前存储在GemFire中的状态
您还可以尝试清除缓存和重新水化(根据需要急切地或懒散地),尤其是在类定义已更改的情况下,尤其是在某些类类型用作键的情况下
此外,一般来说,如果不能严格遵循简单/标量类型(例如Long
或String
),我建议尽可能多地使用不可变键。
也许,如果您可以在应用程序域模型类中共享更多细节,比如用作键的类型,以及在服务方法上使用Spring的缓存抽象,这可能会有所帮助
此外,任何重现该问题的示例或测试用例都将受到极大的赞赏
谢谢