我已经实现了一个 hazelcast 服务,它通过 MapStoreFactory 和 newMapLoader 将其数据存储到本地 mapdb 实例中。如果需要重新启动集群,则可以通过这种方式加载密钥:
public class HCMapStore<V> implements MapStore<String, V> {
Map<String, V> map;
/** specify the mapdb e.g. via
* DBMaker.newFileDB(new File("mapdb")).closeOnJvmShutdown().make()
*/
public HCMapStore(DB db) {
this.db = db;
this.map = db.createHashMap("someMapName").<String, Object>makeOrGet();
}
// some other store methods are omitted
@Override
public void delete(String k) {
logger.info("delete, " + k);
map.remove(k);
db.commit();
}
// MapLoader methods
@Override
public V load(String key) {
logger.info("load, " + key);
return map.get(key);
}
@Override
public Set<String> loadAllKeys() {
logger.info("loadAllKeys");
return map.keySet();
}
@Override
public Map<String, V> loadAll(Collection<String> keys) {
logger.info("loadAll, " + keys);
Map<String, V> partialMap = new HashMap<>();
for (String k : keys) {
partialMap.put(k, map.get(k));
}
return partialMap;
}}
我现在面临的问题是来自 hazelcast 的 MapLoader 接口的 loadAllKeys 方法需要返回整个集群的所有键,但每个节点只存储它拥有的对象。
示例:我有两个节点并存储了 8 个对象,那么例如 5 个对象存储在 node1 的 mapdb 中,3 个对象存储在 node2 的 mapdb 中。我认为哪个对象由哪个节点拥有由 hazelcast 决定。现在重新启动时,node1 将为 loadAllKeys 返回 5 个键,node2 将返回 3 个。Hazelcast 决定忽略这 3 个项目,数据“丢失”。
有什么好的解决办法呢?
赏金更新:在这里,我在 hc 邮件列表中提出了这个问题,提到了 2 个选项(我会再添加 1 个),我想知道 hazelcast 3.2 或 3.3 是否已经可以实现这样的事情:
目前 MapStore 接口仅从本地节点获取数据或更新。是否可以将整个集群的每个存储操作都通知 MapStore 接口?或者也许这已经可以通过一些听众魔法来实现?也许我可以强制 hazelcast 将所有对象放入一个分区并在每个节点上拥有 1 个副本。
如果我重新启动例如 2 个节点,则 MapStore 接口会被我的本地数据库正确调用,用于 node1,然后用于 node2。但是当两个节点都加入时,node2 的数据将被删除,因为 Hazelcast 假设只有主节点是正确的。我可以教 hazelcast 接受来自两个节点的数据吗?