在 Ignite 中使用 Map 作为缓存键的错误

Posted

技术标签:

【中文标题】在 Ignite 中使用 Map 作为缓存键的错误【英文标题】:Bug using Map as a cache key in Ignite 【发布时间】:2017-02-10 14:03:06 【问题描述】:

所以我最近在使用 Ignite 时遇到了一个错误,这让我发疯了,我认为这篇文章可能会帮助一些迷失的灵魂,所以这里是:

场景如下:我有一个类 A,它只有一个 java.util.Map 字段,我将其用作 ignite 缓存键以映射到一些价值。

我有 2 个相同服务的实例: S1S2 ,每个实例都运行一个 ignite 节点。 我们将实例的 ignite 节点称为节点 NM

两个服务都在 ignite 上进行 affinityCalls,因此无论使用该服务的哪个实例,ignite 调用都将转到同一个节点。

发生的场景如下: 1. 服务 S1N 进行亲和调用,并在 N 的缓存中存储 A 的映射 - > 价值 V 2. 服务 S2 执行相同的关联调用并转到 N,但是,当尝试检索放入 N 的值时通过第 1 步缓存,它无法检索它,就好像缓存不包含它一样。

为了让事情更清楚,请考虑以下伪代码:

S1步骤 1 中执行以下操作。

IgniteCache igniteCache=....;

地图 map1= 新地图(); map1.put("某个键","某个值");

A cacheKey= new A(map);

igniteCache.put(keyInCache, 任何东西);

S2步骤 2

中执行以下操作

IgniteCache igniteCache=....;

地图 map2= 新地图(); map2.put("某个键", "某个值");

A keyToRetrieve= new A(map2);

igniteCache.contains(keyToRetrive) --> false.

即使 keyToRetrieve.equals(cacheKey) 为真。

而且缓存确实包含cacheKey。

我发现问题的罪魁祸首是使用 Map 作为 A 类型键中的字段。 似乎 ignite 在处理具有 Map 成员的键时遇到了麻烦,这里也提到了:

Ignite cache.containsKey returns false although keys are equal

【问题讨论】:

【参考方案1】:

使用Map 作为缓存键是非常不典型的,我不建议这样做。如果键是具有多个字段的复合对象,并且没有类,则可以使用二进制构建器构建它:https://apacheignite.readme.io/docs/binary-marshaller#modifying-binary-objects-using-binaryobjectbuilder

【讨论】:

【参考方案2】:

答案是:

使用 Map 以外的东西作为键。我使用了一个整数,然后所有问题都消失了。

我怀疑这可能与在 Ignite 中如何在后台检查地图是否相等有关。

【讨论】:

以上是关于在 Ignite 中使用 Map 作为缓存键的错误的主要内容,如果未能解决你的问题,请参考以下文章

获取apache ignite缓存中的数据行数少于实际行数

Apache Ignite 作为 Postgresql 表的透明缓存

Apache Ignite 频繁缓存关闭异常

不能将Ignite loadCache方法与IgniteBiPredicate一起使用

Apache Ignite 索引性能

Apache Ignite 吞吐量、值大小和最大缓存计数?