当前位置:Java -> 简化分布式计算

简化分布式计算

分布式计算,也称为分布式处理,涉及通过网络连接多台计算机服务器,形成一个集群。这个被称为"分布式系统"的集群使数据共享和处理能力协调。分布式计算提供了许多好处,例如:

  • 可伸缩性利用"横向扩展体系结构"
  • 通过并行性提高性能
  • 通过冗余增加了弹性
  • 通过使用低成本、通用硬件提高成本效益

分布式计算有两个主要优势:

  1. 利用集群系统的集体处理能力
  2. 通过在处理数据的集群上进行计算来最小化网络跳数

在本篇博客文章中,我们将探讨Hazelcast如何简化分布式计算(无论是自管理型还是托管服务)。Hazelcast根据使用情况提供了三种分布式计算解决方案:

选项#1:Entry Processor

一个条目处理器是一种功能,以确保原子性的方式在映射条目上执行代码。因此,您可以在集群成员(服务器)上更新、删除和读取映射条目。这是在IMap上执行批量处理的一个不错的选择。

如何创建EntryProcessor

public class IncrementingEntryProcessor implements EntryProcessor<Integer, Integer, Integer> {
    public Integer process( Map.Entry<Integer, Integer> entry ) {
        Integer value = entry.getValue();
        entry.setValue( value + 1 );
        return value + 1;
    }
    @Override
    public EntryProcessor<Integer, Integer, Integer> getBackupProcessor() {
        return IncrementingEntryProcessor.this;
    }
}


如何使用EntryProcessor

IMap<Integer, Integer> map = hazelcastInstance.getMap( "myMap" );
for ( int i = 0; i < 100; i++ ) {
    map.put( i, i );
}
Map<Integer, Object> res = map.executeOnEntries( new IncrementingEntryProcessor() );


如何优化EntryProcessor性能

  • Offloadable指的是从分区线程转移到执行线程的能力。
  • ReadOnly表示无需对键进行锁定的能力。

您可以在我们的文档中了解更多关于条目处理器的内容。

选项#2:Java Executor Service

简单来说,您可以在集群成员上运行您的Java代码并获得结果输出。Java在其Executor框架中拥有一个杰出的特性,使得可以异步执行任务,如数据库查询、复杂计算和图像渲染。在Java Executor框架中,您可以通过Callable或Runnable两种方式实现任务。同样地,使用Hazelcast,您也可以通过CallableRunnable两种方式实现任务。

如何实现一个Callable任务

public class SumTask

        implements Callable<Integer>, Serializable, HazelcastInstanceAware {
    private transient HazelcastInstance hazelcastInstance;
    public void setHazelcastInstance( HazelcastInstance hazelcastInstance ) {
        this.hazelcastInstance = hazelcastInstance;
    }
    public Integer call() throws Exception {
        IMap<String, Integer> map = hazelcastInstance.getMap( "map" );
        int result = 0;
        for ( String key : map.localKeySet() ) {
            System.out.println( "Calculating for key: " + key );
           result += map.get( key );
        }
        System.out.println( "Local Result: " + result );
       return result;
    }
}


如何实现一个Runnable任务

public class EchoTask implements Runnable, Serializable {
    private final String msg;
    public EchoTask( String msg ) {
        this.msg = msg;
    }
    @Override
    public void run() {
        try {
            Thread.sleep( 5000 );
        } catch ( InterruptedException e ) {

        }
        System.out.println( "echo:" + msg );
    }
}


如何扩展Executor Service

要进行扩展,您应该提高集群成员(JVM)的处理能力。可以通过增加配置Executor Service中提到的线程池大小(即增加线程数量)来实现。不过,请注意您的成员的容量。如果您认为增加线程数造成的额外负载超出了成员的处理能力,您可能需要考虑改进成员的资源(CPU、内存等)。例如,将池大小设置为5并运行上述MasterMember。您会发现EchoTask在产生后立即运行。

要进行扩展,不仅仅是增加一个成员的容量,而是添加更多成员。您可能需要通过添加更多物理或虚拟机来扩展您的集群。例如,在Runnable部分的EchoTask场景中,您可以创建另一个Hazelcast实例,该实例会自动参与MasterMember开始的执行并启动处理。您可以在我们的文档中阅读更多有关Executor Service的内容。

选项#3:Pipeline

开发一个能够在集群参与者之间迅速执行批处理或流处理的数据管道。它由三个元素组成:一个或多个源、处理阶段,以及至少一个接收端。根据数据源不同,数据管道可用于不同的用例,如在连续数据流(即事件)上进行实时流处理,以实时生成数据,或者对静态数据的固定数量进行批处理用于例行任务,如生成日常报告。在Hazelcast中,数据管道可以使用SQL或Jet API进行定义。

以下是一些其他资源:

何时应该选择Entry Processor,Executor Service,或Pipeline?

选择条目处理器适用于对映射进行批处理的场景。通常情况下,这涉及遍历键循环,获取值(map.get(key)),修改值,最终使用map.put(key, value)将条目重新整合到映射中。

Executor服务非常适合在集群成员上执行任意Java代码。

数据管道适用于需要处理多个条目(如聚合或连接),或需要并行执行多个计算步骤的场景。使用数据管道,您可以根据计算结果更新映射并使用条目处理器 sink。

所以您在Hazelcast中有三种选择进行分布式计算。我们期待您对本博客文章的反馈和评论!在Hazelcast的GitHub存储库上分享您对Hazelcast的使用经验。

推荐阅读: 阿里巴巴面经(44)

本文链接: 简化分布式计算