在 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 个相同服务的实例: S1 和 S2 ,每个实例都运行一个 ignite 节点。 我们将实例的 ignite 节点称为节点 N 和 M
两个服务都在 ignite 上进行 affinityCalls,因此无论使用该服务的哪个实例,ignite 调用都将转到同一个节点。
发生的场景如下: 1. 服务 S1 对 N 进行亲和调用,并在 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 作为 Postgresql 表的透明缓存