2013年总结,和2014年的预期

仿佛昨天还在担心世界末日是否来临般,2013年就这么悄悄地过去了。

在这里做一下2013的回首吧。

2013年1月,我终于结束了自己的博士生涯,穿上博士服,和董可心穿硕士服一块照相,和学生生涯说了声再见。在网上找钻戒,找到一家不错的公司,要他们先做一个样品。

2013年2月,情人节和董可心吃的牛排,吃完她喊肚子胀。想写个安卓程序去挣广告费,感觉现在挣的不够花。

2013年3月,钻戒样品到了,要董可心试戴,然后告诉她是假的-银做的而且钻不知道是神马石头。

2013年4月,月初钻戒到了,藏了起来,在董可心的生日向她求婚,她同意了。我感觉非常幸福,完成人生第一次责任性的转变。

2013年5月中旬,第一次以出差的身份回国,作了人生第一次非学术的演讲,认识了不少同业人,年龄相仿,赢得了老板的信任。

2013年6月,和董可心开开心心地玩了次德国奥地利捷克,记忆尤新。

2013年7月-9月,天气炎热,和董可心同学们烧烤,游CLARE GLENS,将脚伸进水里,感受那种丝丝的凉意和快乐。写安卓程序的想法作罢,因为挣不了多少,有时间该去干更喜欢和挣钱的事情。

2013年8月开始,公司财政困难,9月起工资暂付60%,生活很艰苦,王一越陈拯善搬离了家里,大嘴和张洋住了进来,每天回家都感觉很快乐。本来打算买房子的,看公司情况只能暂时作罢。

2013年9月,路京回来了,聊了几次长的,他在国内也不容易,大家都不容易。

2013年10月,董可心回去参加好朋友的婚礼,每天吃简单健康的煮菜度日。每天打个电话,日子简单。同月,老纪回到爱尔兰,给我开阔了眼界,原来博士身份有这种用途。10月中旬,董可心回来了,日子回归到如常,出去玩的时间开始少了。同月我的签证变成绿卡,变太晚了,搞得要2015年7月,延期3个月才能变成STAMP 4。如果董可心在都柏林或考克,或任何地方找到工作,就在那买套房子,董可心住过去,我搬去香浓,然后周末过去。

2013年11月,董可心有了人生第一次有挑战的面试,都柏林机场大数据分析师,经过2轮面试没有成功,她很失落。隋易安回来了,日子更像以前一样。张云翔带自己心仪女生给我们看,大家感觉一般。

2013年12月,老纪回去了,张洋和隋易安也回去了,圣诞节后我们去了一次抢购,花了大概300-400欧。同月,都柏林买房子事宜打算延后,决定还是在LIMERICK先买套房子。

感觉还是颇为充实的。我记得每年年尾,都觉得明年是自己的转折点,可能,我的人生到处都得是转折点,不然我觉得日日重复的人生太难受了。那2014年,我觉得又是一个转折点,而且是最大的。照常,我在这里写一下2014年的任务。

1. 上半年和董可心领结婚证

2. 上半年在LIMERICK买套房子,7月前和董可心住进去。

3. 上半年做完学位公证。

4. 7月接父母来爱尔兰,住进新房子里。

5. 年内帮助在中国销售业绩翻4番(应该不难,现在才2000多欧的业绩)。

6. 年内涨工资。期望年内董可心找到工作。

7. 年内保底出差回国能有一次,争取2次。

Win32 Mutithread Functions Description.

HANDLE WINAPI GetStdHandle(
  _In_  DWORD nStdHandle
);

GetStdHandle()返回标准的输入、输出或错误的设备的句柄,也就是获得输入、输出/错误的屏幕缓冲区的句柄。

参数

nStdHandle 需要传递标准设备标识符,可以是如下任一值

STD_INPUT_HANDLE 控制台(console)标准输入设备。初始化为控制台输入缓存(buffer) CONIN$.

STD_OUTPUT_HANDLE 控制台标准输出设备,初始化为活跃的控制台屏幕缓存 CONOUT$.

STD_ERROR_HANDLE 控制台标准错误设备,和STD_OUTPUT_HANDLE一样,初始为屏幕缓存 CONOUT$.。

返回值

成功执行该函数,返回参数所指设备的句柄,或由SetStdHandle函数调用时重新指向的句柄。返回的句柄对设备拥有GENERIC_READ和GENERIC_WRITE访问权限。

函数执行失败时,返回INVALID_HANDLE_VALUE,可以使用GetLastError得知更详细的出错信息。

若应用无相关的标准句柄,如在交互桌面上运行的服务,且之前未使用SetStdHandle进行重新指向,返回值为NULL

函数描述

由GetStdHandle返回的句柄可被调用该函数的应用来对终端进行读写操作。当终端被创建时,其指向输入缓存的句柄即为终端的标准输入句柄。标准的输出和错误句柄指向的则是终端屏幕缓存。ReadFile和WriteFile函数,或任何需要访问终端输入缓存或屏幕缓存的终端函数(如ReadConsoleInput, WriteConsole,或者GetConsoleScreenBufferInfo等)都可使用该句柄。

使用SetStdHandle,可以重新指向一个进程的标准句柄。假设已经这么做了,GetStdHandle则会返回重新指向过了的句柄。假设标准句柄已经被重新指向,调用CreateFile函数时仍可传递CONIN$值来访问终端的主动屏幕缓存。

When attaching to a new console, standard handles are always replaced with console handles unlessSTARTF_USESTDHANDLES was specified during process creation.

If the existing value of the standard handle is NULL, or the existing value of the standard handle looks like a console pseudohandle, the handle is replaced with a console handle.

When a parent uses both CREATE_NEW_CONSOLE and STARTF_USESTDHANDLES to create a console process, standard handles will not be replaced unless the existing value of the standard handle is NULL or a console pseudohandle.

CONSOLE_SCREEN_BUFFER_INFO 结构

该结构包括了终端屏幕缓存的欣喜

typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
  COORD      dwSize;
  COORD      dwCursorPosition;
  WORD       wAttributes;
  SMALL_RECT srWindow;
  COORD      dwMaximumWindowSize;
} CONSOLE_SCREEN_BUFFER_INFO;

其中,COORD是在屏幕缓存中的一个字符细胞(CELL)的坐标结构。

而SMALL_RECT定义了一个矩形坐上和右下角的坐标。

dwSize是终端屏幕缓存的尺寸,单位则是字符个数

dwCursorPosition是光标的坐标。

wAttribute是有WriteFile或WriteConsole函数写进屏幕缓存的,或者是ReadFile合ReadConsole返回的屏幕缓存的字符的属性

srWindow是终端屏幕缓存的左上右下角坐标值

dwMaximumWindowSize是终端能达到的最大尺寸坐标值。

CreateMutex函数

HANDLE WINAPI CreateMutex(
  _In_opt_  LPSECURITY_ATTRIBUTES lpMutexAttributes,
  _In_      BOOL bInitialOwner,
  _In_opt_  LPCTSTR lpName
);

该函数创建或打开一个有命名或者没有命名的互斥锁对象。

参数

lpMutexAttributes [in, 可选]: 指向一个SECURITY_ARRTIBUTES结构的指针,若该参数为NULL,则生成的互斥锁具备缺省的安全描述*,且该句柄无法被子线程所继承。

*缺省安全描述:访问控制列表*

访问控制列表:由0个或多个访问控制实例(Access Control Entry, ACE)组成。ACE控制或监控特殊的受托实例(trustee)对某个对象的访问。有6种不同的ACE

Handle in C/C++

句柄(HANDLE, 源码中全大写)是个非常抽象的概念,微软对其没有精确定义。在某个特殊操作系统中,他使用了一种内部含义,而在其他版本中,就不保证这样。

API和句柄同是接口。但句柄和API有所不同:句柄不能唯一标示对象,一个对象可以有多个句柄。如:用CreateProcess创建一个进程,该进程的第一个线程的句柄会返回给调用CreateProcess的进程。同是在新创建的进程中,该线程也会有一个句柄。这样,这个线程就有两个句柄。

每个有ID的对象,在系统范围内ID是唯一的。句柄能事先的功能ID却无法实现,毕竟ID只是一个数字,记录信息不多;而句柄可能在其内部结构中记录很多信息,如权限,有无信号等。

指针是用来记录内存的地址。如果简单理解知道内存首地址,那可以随时用这个地址访问对象,那就错了。windows是一个虚拟内存为基础的操作系统,因此内存管理器经常在内存中来回移动对象,对象被移动,则意味着它的地址变化了。为解决之后在内存中找对象的问题,windows为各应用程序腾出一些内存存储地址,用来专门等级应用对象在内存中的地址变化,而这个存储单元的地址本身则不变 – 它就是句柄。windows内存管理器在移动对象在内存中的位置之后,把对象新的地址告知句柄来保存。因此,只需记住句柄地址,即可间接知道对象具体的内存地址。

但是,必须注意程序重新启动时,系统不保证非配给程序的句柄还是原来那个句柄-绝大多数情况句柄会变化。

Include Files for Multithreading and C Run-time Library Functions for Thread Control

Include Files for Multithreading

To compile a multithread application, one can use compiler option, or define the symbolic constant _MT in the source file or on the command line with /D compiler option.

Standard include files declare C run-time library functions as they are implemented in the libraries. If Full Optimization (/Ox) or Fastcall Calling Convention (/Gr) is used, the compiler assumes all functions should be called using the register calling convention.

C Run-time Library Functions for Thread Control

All Win32 programs have at least ONE thread. Any thread can create additional threads. A thread can quickly complete its work and then terminate, or stay alive until the program is finished.

LIBCMT and MSVCRT C runtime libraries provides two functions for thread creation and termination: _beginthread and _endthread.

_beginthread creates a new thread and returns a thread identifier if the operation is successful. The thread terminates automatically if it completes execution, or it can terminate itself with a call to _endthread.

WARNING: LIBCMT.LIB restricts the program calling its C run-time routines has to start threads with the _beginthread function. Using Win32 functions like ExitThread and CreateThread, SuspendThread is prohibited and can lead to dead lock.

The _beginthread Function

This function creates a new thread. A thread shares the code and data segments of a process with other threads in the process, but has its own register values, stack space, and current instruction address. The system gives CPU time to each thread, so that all threads in a process can execute concurrently.

The _beginthread function is similar to the CreateThread function in Win32 API. The differences between the two are

  • The _beginthread function lets you pass multiple arguments to the thread.
  • The _beginthread function initializes certain C run-time library variables.
  • CreateThread provides control over security attributes. It is possible to start a thread in a suspended state.

The _beginthread function returns a handle to the new thread if successful or -1 if there was an error.

The _endthread Function

This function terminates a thread created by _beginthread. Threads terminate automatically when they finish. The _endthread function is useful for conditional termination from with a thread. E.g. A  thread terminates itself when it is not able to obtain the communications port.

Libraries for Multithreading

Library Support for Multithreading

Access to static data used by the function, such as printf function, must be restricted to one thread at a time.

Each thread has a independent stack. Thus, a function use only automatic (stack) variables is reentrant*. Standard C run-time library, such as LIBC, have only a limited number of reentrant functions. A multithread program needing to use C run-time library functions that are normally not reentrant should be built with multithread library LIBCMT.LIB

*reentrant (可重入的):在实时系统的设计中,经常会出现多个任务调用同一个函数的情况。如果这个函数不幸被设计成为不可重入的函数的话,那么不同任务调用这个函数时可能修改其他任务调用这个函数的数据,从而导致不可预料的后果。可重入是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会出错。不可重入函数在实时系统设计中被视为不安全函数。

满足下列条件的函数多数是不可重入的:

– 函数体内使用了静态的数据结构

– 函数体内调用了malloc()或者free()函数

– 函数体内调用了标准I/O函数.

写出可重入函数方法:在函数体内不访问全局变量,不使用静态局部变量,坚持只使用缺省态(auto)局部变量,写出的函数就将是可重入的。如果必须访问全局变量,记住利用互斥信号量来保护全局变量。或者调用该函数前关中断,调用后再开中断。

The Multithread C libraries: LIBCMT.LIB and MSVCRT.LIB

The above two libraries are prepared for multithread programs. To use the functions in these libraries, the following rules may apply:

  • All libraries call must use the C (__cdecl) calling convertion; programs using other calling conversions (such as __fastcall or __stdcall) must use the standard include files for the run-time library function they call.
  • Variables passed to library functions must be passed by value or cast to a pointer.

Programs built with LIBCMT.LIB do not share C run-time library code or data with any dynamic-link libraries they call.

Alternatives to LIBCMT.LIB and MSVCRT.LIB

Building a multithread program without using LIBCMT.LIB must do the following:

  • Use the standard C libraries and limit library calls to the set of reentrant functions.
  • Use the Win32 API thread management functions, such as Create Thread. 
  • Provide my own synchronization for functions that are not reentrant by using Win32 services such as semaphores and the EnterCriticalSection and LeaveCriticalSection functions

The Multithread Libraries Compile Option

To build a multithread application that uses the C run-time libraries, I must tell the compiler to use a special version of the libraries (LIBCMT.LIB). To select these libraries, first open the Project Settings dialog box (Build menu) and click the C/C++ tab. Select Code Generation from the Category drop-down list box. From the Use Run-Time Library drop-down box, select Multithreaded. Click OK to return to editing.

Multi-thread Study Note – 01 – Concepts

1. Concepts

A Thread is basically a path of execution through a program, and the smallest unit of execution that Win32 schedules.

A thread consists of a stack, the state of the CPU registers, and an entry in the execution list of the system scheduler. Each thread shares all of the processor’s resources.

A process consists of one or more threads and the code, data, and other resources of a program in memory.

Typical program resources are open files, semaphores*, and dynamically allocated memory.

*Semarphore: 信号量,是在多线程环境下,保证两个或多个关键代码段不被并发调用的设施。在进入一个关键代码前,信号必须获得一个semaphore. 一旦该关键代码被执行完,该线程必须释放该semaphore。抽象来讲,信号量为一个非负整数(可为为Integer或Binary,前者允许将资源分享给多个进程,后者只允许给一个进程),所有通过它的线程将该整数减一,当该数值为0时,所有试图通过它的线程都处于等待状态。在信号量上我们定义两种操作: Wait(等待) 和 Release(释放)。当一个线程调用Wait操作时,它要么得到资源然后将信号量减一,要么一直等下去(指放入阻塞队列),直到信号量大于等于一时。Release(释放)实际上是在信号量上执行加操作。

A program executes when the system scheduler gives one of its threads execution control. The scheduler determines which threads should run or when they should run. Threads of lower priority may have to wait while higher priority threads complete their tasks. On multiprocessor machines, the scheduler can move individual threads to different processors to balance the CPU load.

Each thread in a process operates independently, and is unaware of the other threads in the process (unless you make them visible to each other).

Threads share common resources. However, they must coordinate their work by using semaphores or another method of interprocess communication.

2013 已犯错误

1. 对于MTCS下的单,未能与本公司内其他部门,包括老板充分沟通,导致老板对产品价格判断失误,生产部无法知道要生产产品具体内容。

2. 与其他人的交流欠妥,喜怒于言表,让人察觉。

3. 嘴欠,不该说的说了,该说的有时却没说。

4. 无法坚持自己该做的事情

今日和父母视频,眼尖的父亲看到我穿着刚买不久的新衣服,觉得很好看,夸耀起来。母亲随后发现,也是赞许万分。两人如两个老小孩一样,坐在沙发上看着屏幕前的我笑着。

随着自己年纪见长,对父母的感情也就越深,能体会他们的疾苦,也担心他们的一切。父母的身体是自己在国内唯一挂念的事情。除了希望他们身体安康,他们的生活快乐也是我真切希望的东西。

然后我能给他们的快乐是有限的。一年回国就那么点时间,远远不够。记得3月前回国,三人一起驱车去离家很近的靖港,靖港是一条很长的古街,两边都是民国时期的一些建筑。母亲高兴地这里看看那里看看,我则和父亲默默地走着,不时拍拍照片。

前面是个拱桥,很漂亮,我在桥中间停下来,拍了几张。母亲看着高处的我,在远处慢慢赶过来,而父亲则在我不注意之间走下桥,在偌大的古街中间停下,默默地左右打量着。我看着身在前后的父母,想着自己不久即将再次远行,鼻子一酸。

靖港镇的巷子很长,走了许久,也没见到有走完的痕迹。我开始有一种错觉,我希望这条巷子永远走不完,永远没有尽头,哪怕再无聊也无所谓,我能陪着父母永远走下去就好。傻傻的我,就在这种想法驱使下,傍着父母走着,每当看到前面的弯过了之后,面前还是一方靖港的天地,就心中暗喜。但是我还没昏到觉得这个梦境成真了。果然,再长的巷子也有走完的那一刻。到了尽头,父亲默默地打量了周围一会,说,回去吧。我们又开始踏上了返程的路。

不知道有没有人有相同的错觉,总感觉返回用的时间要比出发要快好多。我们又坐上了车,回到家中。之后时光如梭,不一会我就到了回爱的日子,告别父母,坐上飞机离他们万里之外。

每日都要和父母通通电话,有了IPAD就更方便我们互相看看。我急切期待下次见到他们的日子,但其实心里也是一种如针扎般的煎熬。回去一趟,他们就老了一岁。父母总有不在自己身边的那一天,我打出这行字时的那种感觉,真心不舒服。这是无法避免的事情,也是不得不面对的事情。有人说,趁他们还好时,对他们好一点,其实我说实话,多好都不够。母亲今天弱弱地问我,来爱尔兰时,能不能带他们去一趟西班牙,我就是拼了老命,也得带他们去西班牙玩舒坦了。虽然那也不够,但-有多少是多少。

Hadoop学习笔记

什么是 HADOOP

 

Hadoop框架中最核心的设计就是:MapReduceHDFSMapReduce的思想是由Google的一篇论文所提及而被广为流传的,简单的一句话解释MapReduce就是任务的分解与结果的汇总HDFSHadoop分布式文件系统(Hadoop Distributed File System)的缩写,为分布式计算存储提供了底层支持。

 

MapReduce从它名字上来看就大致可以看出个缘由,两个动词MapReduce,”Map(展开)”就是将一个任务分解成为多个任务,”Reduce“就是将分解后多任务处理的结果汇总起来,得出最后的分析结果。这不是什么新思想,其实在前面提到的多线程,多任务的设计就可以找到这种思想的影子。不论是现实社会,还是在程序设计中,一项工作往往可以被拆分成为多个任务,任务之间的关系可以分为两种:一种是不相关的任务,可以并行执行;另一种是任务之间有相互的依赖,先后顺序不能够颠倒,这类任务是无法并行处理的。回到大学时期,教授上课时让大家去分析关键路径,无非就是找最省时的任务分解执行方式。在分布式系统中,机器集群就可以看作硬件资源池,将并行的任务拆分,然后交由每一个空闲机器资源去处理,能够极大地提高计算效率,同时这种资源无关性,对于计算集群的扩展无疑提供了最好的设计保证。(其实我一直认为Hadoop的卡通图标不应该是一个小象,应该是蚂蚁,分布式计算就好比蚂蚁吃大象,廉价的机器群可以匹敌任何高性能的计算机,纵向扩展的曲线始终敌不过横向扩展的斜线)。任务分解处理以后,那就需要将处理以后的结果再汇总起来,这就是Reduce要做的工作。


1MapReduce结构示意图

上图就是MapReduce大致的结构图,在Map前还可能会对输入的数据有Split(分割)的过程,保证任务并行效率,在Map之后还会有Shuffle(混合)的过程,对于提高Reduce的效率以及减小数据传输的压力有很大的帮助。后面会具体提及这些部分的细节。

HDFS是分布式计算的存储基石,Hadoop的分布式文件系统和其他分布式文件系统有很多类似的特质。分布式文件系统基本的几个特点:

  1. 对于整个集群有单一的命名空间。
  2. 数据一致性。适合一次写入多次读取的模型,客户端在文件没有被成功创建之前无法看到文件存在。
  3. 文件会被分割成多个文件块,每个文件块被分配存储到数据节点上,而且根据配置会由复制文件块来保证数据的安全性。


2HDFS结构示意图

上图中展现了整个HDFS三个重要角色:NameNodeDataNodeClientNameNode可以看作是分布式文件系统中的管理者,主要负责管理文件系统的命名空间、集群配置信息和存储块的复制等。NameNode会将文件系统的Meta-data存储在内存中,这些信息主要包括了文件信息、每一个文件对应的文件块的信息和每一个文件块在DataNode的信息等。DataNode是文件存储的基本单元,它将Block存储在本地文件系统中,保存了BlockMeta-data,同时周期性地将所有存在的Block信息发送给NameNodeClient就是需要获取分布式文件系统文件的应用程序。这里通过三个操作来说明他们之间的交互关系。

文件写入:

  1. ClientNameNode发起文件写入的请求。
  2. NameNode根据文件大小和文件块配置情况,返回给Client它所管理部分DataNode的信息。
  3. Client将文件划分为多个Block,根据DataNode的地址信息,按顺序写入到每一个DataNode块中。

文件读取:

  1. ClientNameNode发起文件读取的请求。
  2. NameNode返回文件存储的DataNode的信息。
  3. Client读取文件信息。

文件Block复制:

  1. NameNode发现部分文件的Block不符合最小复制数或者部分DataNode失效。
  2. 通知DataNode相互复制Block
  3. DataNode开始直接相互复制。

最后再说一下HDFS的几个设计特点(对于框架设计值得借鉴):

  1. Block的放置:默认不配置。一个Block会有三份备份,一份放在NameNode指定的DataNode,另一份放在与指定DataNode非同一Rack上的DataNode,最后一份放在与指定DataNode同一Rack上的DataNode上。备份无非就是为了数据安全,考虑同一Rack的失败情况以及不同Rack之间数据拷贝性能问题就采用这种配置方式。
  2. 心跳检测DataNode的健康状况,如果发现问题就采取数据备份的方式来保证数据的安全性。
  3. 数据复制(场景为DataNode失败、需要平衡DataNode的存储利用率和需要平衡DataNode数据交互压力等情况):这里先说一下,使用HDFSbalancer命令,可以配置一个Threshold来平衡每一个DataNode磁盘利用率。例如设置了Threshold10%,那么执行balancer命令的时候,首先统计所有DataNode的磁盘利用率的均值,然后判断如果某一个DataNode的磁盘利用率超过这个均值Threshold以上,那么将会把这个DataNodeblock转移到磁盘利用率低的DataNode,这对于新节点的加入来说十分有用。
  4. 数据交验:采用CRC32作数据交验。在文件Block写入的时候除了写入数据还会写入交验信息,在读取的时候需要交验后再读入。
  5. NameNode是单点:如果失败的话,任务处理信息将会纪录在本地文件系统和远端的文件系统中。
  6. 数据管道性的写入:当客户端要写入文件到DataNode上,首先客户端读取一个Block然后写到第一个DataNode上,然后由第一个DataNode传递到备份的DataNode上,一直到所有需要写入这个BlockNataNode都成功写入,客户端才会继续开始写下一个Block
  7. 安全模式:在分布式文件系统启动的时候,开始的时候会有安全模式,当分布式文件系统处于安全模式的情况下,文件系统中的内容不允许修改也不允许删除,直到安全模式结束。安全模式主要是为了系统启动的时候检查各个DataNode上数据块的有效性,同时根据策略必要的复制或者删除部分数据块。运行期通过命令也可以进入安全模式。在实践过程中,系统启动的时候去修改和删除文件也会有安全模式不允许修改的出错提示,只需要等待一会儿即可。

下面综合MapReduceHDFS来看Hadoop的结构:


3Hadoop结构示意图

Hadoop的系统中,会有一台Master,主要负责NameNode的工作以及JobTracker的工作。JobTracker的主要职责就是启动、跟踪和调度各个Slave的任务执行。还会有多台Slave,每一台Slave通常具有DataNode的功能并负责TaskTracker的工作。TaskTracker根据应用要求来结合本地数据执行Map任务以及Reduce任务。

说到这里,就要提到分布式计算最重要的一个设计点:Moving Computation is Cheaper than Moving Data。就是在分布式处理中,移动数据的代价总是高于转移计算的代价。简单来说就是分而治之的工作,需要将数据也分而存储,本地任务处理本地数据然后归总,这样才会保证分布式计算的高效性。

为什么要选择Hadoop

说完了What,简单地说一下Why。官方网站已经给了很多的说明,这里就大致说一下其优点及使用的场景(没有不好的工具,只用不适用的工具,因此选择好场景才能够真正发挥分布式计算的作用):

  1. 可扩展:不论是存储的可扩展还是计算的可扩展都是Hadoop的设计根本。
  2. 经济:框架可以运行在任何普通的PC上。
  3. 可靠:分布式文件系统的备份恢复机制以及MapReduce的任务监控保证了分布式处理的可靠性。
  4. 高效:分布式文件系统的高效数据交互实现以及MapReduce结合Local Data处理的模式,为高效处理海量的信息作了基础准备。

使用场景:个人觉得最适合的就是海量数据的分析,其实Google最早提出MapReduce也就是为了海量数据分析。同时HDFS最早是为了搜索引擎实现而开发的,后来才被用于分布式计算框架中。海量数据被分割于多个节点,然后由每一个节点并行计算,将得出的结果归并到输出。同时第一阶段的输出又可以作为下一阶段计算的输入,因此可以想象到一个树状结构的分布式计算图,在不同阶段都有不同产出,同时并行和串行结合的计算也可以很好地在分布式集群的资源下得以高效的处理。