Hazelcast / Coherence网格计算EntryProcessor,包含每个密钥的数据

时间:2016-10-18 07:12:31

标签: hazelcast oracle-coherence grid-computing

我想使用hazelcast或coherence EntryProcessor在密钥存储在缓存中的不同节点上处理并行执行中的某些逻辑。我看到我可以使用类似sendToEachKey(EntryProcessor进程)的东西。

我的问题出现了,当我需要向逻辑发送一块数据来处理属于另一个系统并且我收到它(例如在http请求中)。

当然我可以做类似sendToEachKey(EntryProcessor(数据)进程)的事情。但是,如果数据与每个密钥不同,并且我想发送给特定密钥,只有他要处理的数据,我该怎么做?为什么我要这样做是因为数据太大而且网络过载。

当然,如果我打开一个线程池来将每个数据发送到每个密钥是可能的,但是由于巨大的请求它是低效的。

谢谢!

3 个答案:

答案 0 :(得分:1)

对于Hazelcast,您可以检索所有值并将每个键发送给自己的EntryProcessor,但这会产生大量开销。

另一种选择是使用EntryProcessor和我们的分布式ExecutorService的组合。

您将Runnable发送到ExecutorService。在Runnable内部检索本地密钥集,检索所有外部值(所有已经在节点本地的值),然后每个本地密钥发出一个EntryProcessor。由于您已经在节点本地,因此没有更多的流量飞来飞去(除了备份,显然:))。也就是说,您可能希望实现一个特定的EntryProcessor,它只传输更改后的值,而不是完整的处理器本身(以节省更多流量)。

答案 1 :(得分:1)

在Coherence中,您可以使用PartitionedService查找缓存键与群集成员的关联。然后,您可以使用PartitionedFilter为每个成员调用包含数据的条目处理器,以确保仅将数据发送给该成员。像这样:

// keys in this map are also keys in cache
void processData(Map<String, Data> externalData) { 
    PartitionedService partitionedService = (PartitionedService) cache.getCacheService();
    Map<Member, Map<String, Data>> dataForMembers = splitDataByMembers(partitionedService, externalData);

    for (Entry<Member, Map<String, Data>> dataForMember : dataForMembers.entrySet()) {
        Member member = dataForMember.getKey();
        Map<String, Data> data = dataForMember.getValue();

        PartitionSet partitions = partitionedService.getOwnedPartitions(member);
        PartitionedFilter filter = new PartitionedFilter<>(Filters.always(), partitions);
        EntryProcessor processor = new MyEntryProcessor(data);
        cache.async().invokeAll(filter, processor);
    }
}

Map<Member, Map<String, Data>> splitDataByMembers(
        PartitionedService partitionedService,
        Map<String, Data> externalData) {
    Map<Member, Map<String, Data>> dataForMembers = new HashMap<>();

    for (Object member : partitionedService.getInfo().getServiceMembers()) {
        dataForMembers.put((Member) member, new HashMap<>());
    }
    for (Entry<String, Data> dataForKey : externalData.entrySet()) {
        Member member = partitionedService.getKeyOwner(dataForKey.getKey());
        dataForMembers.get(member).put(dataForKey.getKey(), dataForKey.getValue());
    }
    return dataForMembers;
}

这样,集群中每个成员只会有一个入口处理器调用,每个成员只会获得它感兴趣的数据。

我使用String作为缓存键和任意Data类型用于与此键关联的数据,但您当然可以使用任何其他类型(并且您不必将外部数据建模为一张地图。)

答案 2 :(得分:0)

在Hazelcast中你会做executeOnKeys(keys, new EntryProcessor(data))这太多了,因为数据太大了。

为什么不

executeOnKey(key1, new EntryProcessor(data1));
executeOnKey(key2, new EntryProcessor(data2));
executeOnKey(key3, new EntryProcessor(data3));

发送每个密钥需要的数据子集?