Tiny并行计算框架之使用介绍

呵呵,昨天看到两新粉,一激动,就想着今天来写这篇文章。其实一直在关注这个领域,但是一直没有信心来写,所以一直期望着有一个开源的来用。
看到了彭渊大师的 淘宝分布式框架Fourinone介绍,确实有一种相见恨晚的感觉,于是就准备去研究一番,详细见本人的感想文章由 fourinone初步学习想到的,确实来说,感觉到有一种啃不动的感觉,当然也可能是本人水平不足的原因所致。但是不管怎么说,促动了本人来写一个简单的并行计算框架。
在此引用本人的 名言:“ 牛人的代码就是生手也一看就懂;生手的代码就是牛人来了也看不懂。
好的,亲们,不管你是生手还是牛人,let's GO!
HelloWorld之一 当然,还是从Hello说起,不过这次的hello与之前不太一样,管呢,先看看再说:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class WorkerHello extends AbstractWorker {
public WorkerHello() throws RemoteException {
super("hello");
}

public Warehouse doWork(Work work) throws RemoteException {
String name = work.getInputWarehouse().get("name");
System.out.println(String.format("id %s: Hello %s", getId(), name));
Warehouse outputWarehouse = new WarehouseDefault();
outputWarehouse.put("helloInfo", "Hello," + name);
return outputWarehouse;
}
}


首先,工人Hello继承自抽象工人,也就是说他首先得是个工人,然后呢是个Hello工人。
在它的构造函数中,抛出一个RemoteException,表明,它是可以被远程调用的工人,在构造方法中调用super("hello"),表明这个工人是个干hello活的工人。
既然是工人么,因此当然得做工作了。
首先从工作的的仓库中取出一个叫name的字符串,然后控制台打一下,然后构建了一个输出的仓库,在里面放了一个helloInfo的字符串,然后返回输出仓库,工人的任务就算完成了。
下面看看示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
JobCenter jobCenter = new JobCenterLocal();

for (int i = 0; i < 5; i++) {
jobCenter.registerWorker(new WorkerHello());
}

Foreman helloForeman = new ForemanSelectOneWorker("hello");
jobCenter.registerForeman(helloForeman);
Warehouse inputWarehouse = new WarehouseDefault();
inputWarehouse.put("name", "world");
Work work = new WorkDefault("hello", inputWarehouse);


Warehouse outputWarehouse = jobCenter.doWork(work);
System.out.println(outputWarehouse.get("helloInfo"));
jobCenter.stop();
}


首先开个职业介绍所,然后构建一了5个Hello工人,放在注册到职业介绍所去。
然后又注册了一个专门干hello活的包工头到职业介绍所,这个包工头有点特别,随便找一个hello工人来干hello这个活。
然后,构建了一个工作,介个工作是个hello工作,它的来料仓库里放了个name是world的值。
然后他就对职业介绍所说,你帮咱把这个活干干。
活干完了,也没有发生异常,顺利的在结果仓库里找到了helloInfo这个值,并且从控制台打出。
下面是运行结果:

1
2
id 46fbffdeb18b45f28cda4617795c2a52: Hello world
Hello,world


从上面的例子当中,我们理解了下面几个概念:

1
2
3
4
5
6
7
8
职业介绍所:JobCenter,主要用于注册工人,注册包工头,接受或处理任务;

包工头:领取工作并招募工人,完成工作,并返回结果

工人:就是我们常说的民工了,只知道来料加工,处于生态环境的低层,最后还没有得工资

工作:只有工作类型和来料仓库
仓库:用于放各种来料或成品


职业介绍所,一般来说不用写,框架已经提供;工作,一般来说不用写;工头,绝大多数不需要写,框架已经提供了若干类型工头,一般够用了;工人,一定需要写。
自此,简单的hello并行计算就算完成了。
HelloWorld之二 上面的hello工作完成之后,老板突发齐想,一个hello吼得声音太小了,偶想让所有的工人都帮偶齐声喊一起Hello,World,那该多壮观,当然老板有钱,说干就干:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args) throws IOException, ClassNotFoundException {
JobCenter jobCenter = new JobCenterLocal();
for (int i = 0; i < 5; i++) {
jobCenter.registerWorker(new WorkerHello());
}
Foreman helloForeman = new ForemanSelectAllWorker("hello");
jobCenter.registerForeman(helloForeman);

Warehouse inputWarehouse = new WarehouseDefault();
inputWarehouse.put("name", "world");
Work work = new WorkDefault("hello", inputWarehouse);
jobCenter.doWork(work);
jobCenter.stop();
}


当然,这次的包工头换了一下,这个包工头会找所有的工人来干活,结果如下:

1
2
3
4
5
id 83274d8f8c194bb89d773c232e867cc4: Hello world
id 16fbf219d3cf4ba48eef23c260de509a: Hello world
id 9c17a119a4f341d68b589a503712b0f9: Hello world
id e7e3b2bdc9444a179ad62abdd35275e1: Hello world
id 4b12a1b70f5d43e2bff473382096dfbe: Hello world


老板一看,尼妈,这帮工人喊是喊完了,这声音就响过(用的是System.out)就没有了,也不知道有几个工人给喊过,包工头说哦,我没有干这收集数据的活,你想要呀,你想要就吱声呀,我加个结果合并给你:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) throws IOException, ClassNotFoundException {
JobCenter jobCenter = new JobCenterLocal();
for (int i = 0; i < 5; i++) {
jobCenter.registerWorker(new WorkerHello());
}
Foreman helloForeman = new ForemanSelectAllWorker("hello", new HelloWorkCombiner());
jobCenter.registerForeman(helloForeman);

Warehouse inputWarehouse = new WarehouseDefault();
inputWarehouse.put("name", "world");
Work work = new WorkDefault("hello", inputWarehouse);
Warehouse outputWarehouse = jobCenter.doWork(work);
List<String> result = outputWarehouse.get("helloInfo");
System.out.println(result.size());
jobCenter.stop();
}


Hello结果收集器,用于把工人干的活合并成一个结果出来:

1
2
3
4
5
6
7
8
9
10
11
12
public class HelloWorkCombiner implements WorkCombiner {

public Warehouse combine(List<Warehouse> warehouseList) throws RemoteException {
Warehouse warehouse = new WarehouseDefault();
List<String> helloList = new ArrayList<String>();
for (Warehouse w : warehouseList) {
helloList.add((String) w.get("helloInfo"));
}
warehouse.put("helloInfo", helloList);
return warehouse;
}
}


老板终于称心如意了。
分布式求和 老板消停了一下下,又想,偶想知道从1加到10000这个结果值是多少。但是一个计算机算,算得太慢了,能不能多几台机器帮我看看,让我早些知道结果?(仅用于说明原理,你可以理解为从1加到10000需要几个小时)
首先造个工人:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class WorkerSum extends AbstractWorker {
public WorkerSum() throws RemoteException {
super("sum");
}

public Warehouse doWork(Work work) throws RemoteException {
long start = (Long) work.getInputWarehouse().get("start");
long end = (Long) work.getInputWarehouse().get("end");
long sum = 0;
for (long i = start; i <= end; i++) {
sum += i;
}
Warehouse outputWarehouse = new WarehouseDefault();
outputWarehouse.put("sum", sum);
return outputWarehouse;
}
}


工人从来料仓库获取开始和结束,然后计算合计值并放在输出仓库中的sum值域中。
但是这活该怎么分给工人呢,工人算完的结果又怎么合并呢?
这个时候,就需要搞个工作分解合并器给包工头用了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class SumSplitterCombiner implements WorkSplitterCombiner {
public List<Warehouse> split(Work work, List<Worker> workers) throws RemoteException {
List<Warehouse> list = new ArrayList<Warehouse>();
long start = (Long) work.getInputWarehouse().get("start");
long end = (Long) work.getInputWarehouse().get("end");
long count = end - start + 1;
long step = count / workers.size();
for (int i = 0; i < workers.size(); i++) {
Warehouse subInputWarehouse = new WarehouseDefault();
subInputWarehouse.put("start", step * i + start);
if (i == workers.size() - 1) {
subInputWarehouse.put("end", end);
} else {
subInputWarehouse.put("end", step * (i + 1));
}
list.add(subInputWarehouse);
}
return list;
}


public Warehouse combine(List<Warehouse> warehouseList) throws RemoteException {
Warehouse outputWarehouse = new WarehouseDefault();
long sum = 0;
for (Warehouse w : warehouseList) {
sum += (Long) w.get("sum");
}
outputWarehouse.put("sum", sum);
return outputWarehouse;
}
}


一共两方法,一个分解方法,一个合并方法,非常容易理解。
万事具备,呵呵,开工:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
JobCenter jobCenter = new JobCenterLocal();
JobCenter center = new JobCenterRemote();
for (int i = 0; i < 5; i++) {
center.registerWorker(new WorkerSum());
}
Foreman helloForeman = new ForemanSelectAllWorker("sum", new SumSplitterCombiner());
center.registerForeman(helloForeman);
Warehouse inputWarehouse = new WarehouseDefault();
inputWarehouse.put("start", 1l);
inputWarehouse.put("end", 10000l);
Work work = new WorkDefault("sum", inputWarehouse);

Warehouse outputWarehouse = center.doWork(work);
System.out.println(outputWarehouse.get("sum"));
jobCenter.stop();
center.stop();
}
}


注意,输入仓库是两个长整型数,因此,下面两句最后的值是1-10000,而不是11~100001

1
2
inputWarehouse.put("start", 1l);
inputWarehouse.put("end", 10000l);


下面是运算输出结果:

150005000


多阶段任务 当然,简单的任务都是一下就干完了的,复杂的工作就需要分成多个阶段进行了。不同的阶段需要的包工头或工人又都是不一定相同的。对于解决这种类型的任务,咱也有相当简单的解决办法。
先造个工人:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class WorkerHello extends AbstractWorker {
public WorkerHello() throws RemoteException {
super("hello");
}

public Warehouse doWork(Work work) throws RemoteException {
String name = work.getInputWarehouse().get("name");
System.out.println(String.format("id %s: Hello %s", getId(), name));
Warehouse outputWarehouse = new WarehouseDefault();
outputWarehouse.put("name", name + "_1");
return outputWarehouse;
}
}


这个工人有点怪,每次都是给名字后面附加一个"_1",然后原样返回。别的没有啥子不同。
EN,然后来做做一系列的工作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class TestSerialWork {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
JobCenter jobCenter = new JobCenterLocal();
for (int i = 0; i < 5; i++) {
jobCenter.registerWorker(new WorkerHello());
}
Foreman helloForeman = new ForemanSelectOneWorker("hello");
jobCenter.registerForeman(helloForeman);
Warehouse inputWarehouse = new WarehouseDefault();
inputWarehouse.put("name", "world");
Work work = new WorkDefault("hello", inputWarehouse);
work.setNextWork(new WorkDefault("hello")).setNextWork(new WorkDefault("hello"));
Warehouse warehouse = jobCenter.doWork(work);
System.out.println(warehouse.get("name"));
jobCenter.stop();
}
}


与前面的例子唯一的不同就是


1work.setNextWork(new WorkDefault("hello")).setNextWork(new WorkDefault("hello"));


这里通过指定下一工作,来建立了一个系列工作,这里定义的工作是三步,下面是运行结果:


1
2
3
4
id 2a53a967e3b84289beb3dbaf12a7d8be: Hello world
id e3d471c27e264a1a87cf263605bfe9bd: Hello world_1
id 2a53a967e3b84289beb3dbaf12a7d8be: Hello world_1_1
world_1_1_1


运行结果与预期完全一致。
通过序列工作的方式可以把复杂的工作分解成简单的工作,而且不同的工作可以由不同的包工头和工人来完成。

圆周率计算 圆周率的计算一般来说是比较费时间的,详细fourinone作者在文章 http://my.oschina.net/fourinone/blog/113731?p=3#comments中已经在详细的描述,这里仅采用其文章中所述方法。

1
2
3
4
5
6
7
8
public static void main(String[] args)
{
double pi=0.0;
for(double i=1.0;i<1000000001d;i++){
pi += Math.pow(-1,i+1)/(2*i-1);
}
System.out.println(4*pi);
}


来计算,先 创建个工人:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class PiWorker extends AbstractWorker {
public PiWorker() throws RemoteException {
super("pi");
}

@Override
protected Warehouse doWork(Work work) throws RemoteException {
long m = (Long) work.getInputWarehouse().get("start");
long n = (Long) work.getInputWarehouse().get("end");
double pi = 0.0d;
for (double i = m; i < n; i++) {
pi += Math.pow(-1, i + 1) / (2 * i - 1);
}
work.getInputWarehouse().put("pi", 4 * pi);
return work.getInputWarehouse();
}
}


再写个拆分合并器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class PiSplitterCombiner implements WorkSplitterCombiner {
public List<Warehouse> split(Work work, List<Worker> workers) throws RemoteException {
List<Warehouse> list = new ArrayList<Warehouse>();
long start = (Long) work.getInputWarehouse().get("start");
long end = (Long) work.getInputWarehouse().get("end");
long count = end - start + 1;
long step = count / workers.size();
for (int i = 0; i < workers.size(); i++) {
Warehouse subInputWarehouse = new WarehouseDefault();
subInputWarehouse.put("start", step * i + start);
if (i == workers.size() - 1) {
subInputWarehouse.put("end", end);
} else {
subInputWarehouse.put("end", step * (i + 1));
}
list.add(subInputWarehouse);
}
return list;
}
public Warehouse combine(List<Warehouse> warehouseList) throws RemoteException {
Warehouse outputWarehouse = new WarehouseDefault();
double pi = 0d;
for (Warehouse w : warehouseList) {
pi += (Double) w.get("pi");
}
outputWarehouse.put("pi", pi);
return outputWarehouse;
}
}


接下来是测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
JobCenter jobCenter = new JobCenterLocal();
for (int i = 0; i < 10; i++) {
jobCenter.registerWorker(new PiWorker());
}
Foreman helloForeman = new ForemanSelectAllWorker("pi", new PiSplitterCombiner());
jobCenter.registerForeman(helloForeman);
Warehouse inputWarehouse = new WarehouseDefault();
inputWarehouse.put("start", 1l);
inputWarehouse.put("end", 1000000001l);
Work work = new WorkDefault("pi", inputWarehouse);

Warehouse outputWarehouse = jobCenter.doWork(work);
System.out.println("pi:"+outputWarehouse.get("pi"));
jobCenter.stop();
}
}


运行结果:
1
2
3
4
并行计算运行结果:
time:10326ms pi:3.141592694075038
单线程计算运行结果
time:24857ms pi:3.1415926525880504


这个结果是在本人笔记本跑出来的,笔记本是4核机器,而不是4CPU机器,所以4个并行跑,并没有得到期望的1/4的时间,而是1/2.4左右的时间,因此可以得出两个结论:
结论1:通过并行计算,确实可以缩短计算时间,更好的利用CPU资源。
绪论2:4核和4C还是有显著差异的。
小结 在上面的例子中,我们展示了分布式计算的使用,应该是老小兼宜,简单易懂。
职业介绍所,工人,工头,可以在一台计算机上的,也可以都在一台计算机上。
现在,你可以很牛掰的说,速度慢?哥给你搞个分布式计算不就快了?
  Fourinone(中文名字“四不像”)是一个四合一分布式计算框架,在写这个框架之前,我对分布式计算进行了长时间的思考,也看了老外写的其他开源框架,当我们把复杂的hadoop当作一门学科学习时,似乎忘记了我们想解决问题的初衷:我们仅仅是想写个程序把几台甚至更多的机器一起用起来计算,把更多的cpu和内存利用上,来解决我们数量大和计算复杂的问题,当然这个过程中要考虑到分布式的协同和故障处理。如果仅仅是为了实现这个简单的初衷,为什么一切会那么复杂,我觉的自己可以写一个更简单的东西,它不需要过度设计,只需要看上去更酷一点,更小巧一点,功能更强一点。于是我将自己对分布式的理解融入到这个框架中,考虑到底层实现技术的相似性,我将Hadoop,Zookeeper,MQ,分布式缓存四大主要的分布式计算功能合为一个框架内,对复杂的分布式计算应用进行了大量简化和归纳。   首先,对分布式协同方面,它实现了Zookeeper所有的功能,并且做了很多改进,包括简化Zookeeper的树型结构,用domain/node两层结构取代,简化Watch回调多线程等待编程模型,用更直观的容易保证业务逻辑完整性的内容变化事件以及状态轮循取代,Zookeeper只能存储信息不大于1M的内容,Fourinone超过1M的内容会以内存隐射文件存储,增强了它的存储功能,简化了Zookeeper的ACL权限功能,用更为程序员熟悉rw风格取代,简化了Zookeeper的临时节点和序列节点等类型,取代为在创建节点时是否指定保持心跳,心跳断掉时节点会自动删除。Fourinone是高可用的,没有单点问题,可以有任意多个复本,它的复制不是定时而是基于内容变更复制,有更高的性能,Fourinone实现了领导者选举算法(但不是Paxos),在领导者服务器宕机情况下,会自动不延时的将请求切换到备份服务器上,选举出新的领导者进行服务,这个过程中,心跳节点仍然能保持健壮的稳定性,迅速跟新的领导者保持心跳连接。基于Fourinone可以轻松实现分布式配置信息,集群管理,故障节点检测,分布式锁,以及淘宝configserver等等协同功能。   其次, Fourinone可以提供完整的分布式缓存功能。如果对一个中小型的互联网或者企业应用,仅仅利用domain/node进行k/v的存储即可,因为domain/node都是内存操作而且读写锁分离,同时拥有复制备份,完全满足缓存的高性能与可靠性。对于大型互联网应用,高峰访问量上百万的并发读写吞吐量,会超出单台服务器的承受力,Fourinone提供了fa?ade的解决方案去解决大集群的分布式缓存,利用硬件负载均衡路由到一组fa?ade服务器上,fa?ade可以自动为缓存内容生成key,并根据key准确找到散落在背后的缓存集群的具体哪台服务器,当缓存服务器的容量到达限制时,可以自由扩容,不需要成倍扩容,因为fa?ade的算法会登记服务器扩容时间版本,并将key智能的跟这个时间匹配,这样在扩容后还能准确找到之前分配到的服务器。另外,基于Fourinone可以轻松实现web应用的session功能,只需要将生成的key写入客户端cookie即可。   Fourinone对于分布式大数据量并行计算的解决方案不同于复杂的hadoop,它不像hadoop的中间计算结果依赖于hdfs,它使用不同于map/reduce的全新设计模式解决问题。Fourinone有“包工头”,“农民工”,“手工仓库”的几个核心概念。“农民工”为一个计算节点,可以部署在多个机器,它由开发者自由实现,计算时,“农民工”到“手工仓库”获取输入资源,再将计算结果放回“手工仓库”返回给“包工头”。“包工头”负责承包一个复杂项目的一部分,可以理解为一个分配任务和调度程序,它由开发者自己实现,开发者可以自由控制调度过程,比如按照“农民工”的数量将源数据切分成多少份,然后远程分配给“农民工”节点进行计算处理,它处理完的中间结果数据不限制保存在hdfs里,而可以自由控制保存在分布式缓存、数据库、分布式文件里。如果需要结果数据的合并,可以新建立一个“包工头”的任务分配进行完成。多个“包工头”之间进行责任链式处理。总的来说,是将大数据的复杂分布式计算,设计为一个链式的多“包工头”环节去处理,每个环节包括利用多台“农民工”机器进行并行计算,无论是拆分计算任务还是合并结果,都可以设计为一个单独的“包工头”环节。这样做的好处是,开发者有更大能力去深入控制并行计算的过程,去保持使用并行计算实现业务逻辑的完整性,而且对各种不同类型的并行计算场景也能灵活处理,不会因为某些特殊场景被map/reduce的框架限制住思维,并且链式的每个环节也方便进行监控过程。   Fourinone也可以当成简单的mq来使用,将domain视为mq队列,每个node为一个队列消息,监控domain的变化事件来获取队列消息。也可以将domain视为订阅主题,将每个订阅者注册到domain的node上,发布者将消息逐一更新每个node,订阅者监控每个属于自己的node的变化事件获取订阅消息,收到后删除内容等待下一个消息。但是Fourinone不实现JMS的规范,不提供JMS的消息确认和消息过滤等特殊功能,不过开发者可以基于Fourinone自己去扩充这些功能,包括mq集群,利用一个独立的domain/node建立队列或者主题的key隐射,再仿照上面分布式缓存的智能根据key定位服务器的做法实现集群管理。   Fourinone整体代码短小精悍,跟Hadoop, Zookeeper, Memcache, ActiveMq等开源产品代码上没有任何相似性,不需要任何依赖,引用一个jar包就可以嵌入式使用,良好支持window环境,可以在一台机器上模拟分布式环境,更方便开发。   开发包里自带了一系列傻瓜上手demo,包括分布式计算、统一配置管理、集群管理、分布式锁、分布式缓存、MQ等方面, 每个demo均控制在少许行代码内,但是涵盖了Fourinone主要的功能,方便大家快速理解并掌握。   Fourinone 2.0新增功能:   Fourinone2.0提供了一个4合1分布式框架和简单易用的编程api,实现对多台计算机cpu,内存,硬盘的统一利用,从而获取到强大计算能力去解决复杂问题。Fourinone框架提供了一系列并行计算模式(农民工/包工头/职介绍/手工仓库)用于利用多机多核cpu的计算能力;提供完整的分布式缓存和小型缓存用于利用多机内存能力;提供像操作本地文件一样操作远程文件(访问,并行读写,拆分,排它,复制,解析,事务等)用于利用多机硬盘存储能力;由于多计算机物理上独立,Fourinone框架也提供完整的分布式协同和锁以及简化MQ功能,用于实现多机的协作和通讯。   一、提供了对分布式文件的便利操作, 将集群中所有机器的硬盘资源利用起来,通过统一的fttp文件路径访问,如:   windows:fttp://v020138.sqa.cm4/d:/data/a.log   linux:fttp://v020138.sqa.cm4/home/user/a.log   比如以这样的方式读取远程文件:   FttpAdapter fa = FttpAdapter("fttp://v020138.sqa.cm4/home/log/a.log");   fa.getFttpReader().readAll();   提供对集群文件的操作支持,包括:   1、元数据访问,添加删除,按块拆分, 高性能并行读写,排他读写(按文件部分内容锁定),随机读写,集群复制等   2、对集群文件的解析支持(包括按行,按分割符,按最后标识读取)   3、对整形数据的高性能读写支持(ArrayInt比ArrayList存的更多更快)   4、两阶段提交和事务补偿处理   5、自带一个集群文件浏览器,可以查看集群所有硬盘上的文件(不同于hadoop的namenode,没有单点问题和容量限制)   总的来说, 将集群看做一个操作系统,像操作本地文件一样操作远程文件。   但是fourinone并不提供一个分布式存储系统,比如文件数据的导入导出、拆分存储、负载均衡,备份容灾等存储功能,不过开发人员可以利用这些api去设计和实现这些功能,用来满足自己的特定需求。   二、自动化class和jar包部署   class和jar包只需放在工头机器上, 各工人机器会自动获取并执行,兼容操作系统,不需要进行安全密钥复杂配置   三、网络波动状况下的策略处理,设置抢救期,抢救期内网络稳定下来不判定结点死亡   本软件由www.gg265.net www.fmrpg.com站长提供
淘宝Fourinone2.0提供了一个4合1分布式框架和简单易用的编程API,实现对多台计算机CPU,内存,硬盘的统一利用,从而获取到强大计算能力去解决复杂问题。Fourinone框架提供了一系列并行计算模式(农民工/包工头/职介绍/手工仓库)用于利用多机多核CPU的计算能力;提供完整的分布式缓存和小型缓存用于利用多机内存能力;提供像操作本地文件一样操作远程文件(访问,并行读写,拆分,排它,复制,解析,事务等)用于利用多机硬盘存储能力;由于多计算机物理上独立,Fourinone框架也提供完整的分布式协同和锁以及简化MQ功能,用于实现多机的协作和通讯。 fourinone-2.05.28\fourinone2.0 .................\............\config.xml .................\............\fourinone-2.05.28-src.jar .................\............\fourinone-2.05.28.jar .................\............\指南和demo .................\............\..........\MQ demo .................\............\..........\.......\MQ demo.txt .................\............\..........\.......\ParkServerDemo.java .................\............\..........\.......\Publisher.java .................\............\..........\.......\Receiver.java .................\............\..........\.......\Sender.java .................\............\..........\.......\Subscriber.java .................\............\..........\WordCount .................\............\..........\.........\inputdata.txt .................\............\..........\.........\ParkServerDemo.java .................\............\..........\.........\WordCount.txt .................\............\..........\.........\WordcountCT.java .................\............\..........\.........\WordcountWK.java .................\............\..........\分布式文件访问和操作demo .................\............\..........\........................\FttpBatchWriteReadDemo.java .................\............\..........\........................\FttpCopyDemo.java .................\............\..........\........................\FttpMulCopyDemo.java .................\............\..........\........................\FttpMulWriteReadDemo.java .................\............\..........\........................\FttpOperateDemo.java .................\............\..........\........................\FttpParseDemo.java .................\............\..........\........................\FttpRo
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值