﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-jack-wang-随笔分类-分布式系统</title><link>http://www.cppblog.com/jack-wang/category/12828.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 01 Apr 2010 17:36:14 GMT</lastBuildDate><pubDate>Thu, 01 Apr 2010 17:36:14 GMT</pubDate><ttl>60</ttl><item><title>kosmix，又一个开源的类似GFS的分布式文件系统</title><link>http://www.cppblog.com/jack-wang/archive/2010/04/01/111246.html</link><dc:creator>小王</dc:creator><author>小王</author><pubDate>Thu, 01 Apr 2010 01:47:00 GMT</pubDate><guid>http://www.cppblog.com/jack-wang/archive/2010/04/01/111246.html</guid><wfw:comment>http://www.cppblog.com/jack-wang/comments/111246.html</wfw:comment><comments>http://www.cppblog.com/jack-wang/archive/2010/04/01/111246.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/jack-wang/comments/commentRss/111246.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jack-wang/services/trackbacks/111246.html</trackback:ping><description><![CDATA[<p>来自startup的垂直搜索引擎<a title=http://www.kosmix.com/ href="http://www.kosmix.com/"><u><font color=#0000ff>http://www.kosmix.com/</font></u></a>的开源项目，又一个开源的类似google mapreduce 的分布式文件系统，可以应用在诸如图片存储、搜索引擎、网格计算、数据挖掘这样需要处理大数据量的<a onclick="javascript:tagshow(event, '%E7%BD%91%E7%BB%9C');" href="javascript:;" target=_self><u><strong><font color=#0000ff>网络</font></strong></u></a>应用中。与hadoop集成得也比较好，这样可以充分利用了hadoop一些现成的功能，基于C++。</p>
<h5>Introduction</h5>
<p>Applications that process large volumes of data (such as, search engines, grid computing applications, data mining applications, etc.) require a backend infrastructure for storing data. Such infrastructure is required to support applications whose workload could be characterized as:</p>
<ul>
    <li>Primarily write-once/read-many workloads
    <li>Few millions of large files, where each file is on the order of a few tens of MB to a few tens of GB in size
    <li>Mostly sequential access </li>
</ul>
<p>We have developed the Kosmos Distributed File System (KFS), a high performance distributed file system to meet this infrastructure need.</p>
<p>The system consists of 3 components:</p>
<ol>
    <li><strong>Meta-data server</strong>: a single meta-data server that provides a global namespace
    <li><strong>Block server</strong>: Files are split into blocks or<em>chunks</em>and stored on block servers. Blocks are also known as chunk servers. Chunkserver store the chunks as files in the underlying file system (such as, XFS on Linux)
    <li><strong>Client library</strong>: that provides the file system API to allow applications to interface with KFS. To integrate applications to use KFS, applications will need to be modified and relinked with the KFS client library. </li>
</ol>
<p>KFS is implemented in C++. It is built using standard system components such as, TCP sockets, aio (for disk I/O), STL, and boost libraries. It has been tested on 64-bit x86 architectures running Linux FC5.</p>
<p>While KFS can be accessed natively from C++ applications, support is also provided for Java applications. JNI glue code is included in the release to allow Java applications to access the KFS client library APIs.</p>
<h5>Features</h5>
<ul>
    <li>Incremental scalability: New chunkserver nodes can be added as storage needs increase; the system automatically adapts to the new nodes.
    <li>Availability: Replication is used to provide availability due to chunk server failures. Typically, files are replicated 3-way.
    <li>Per file degree of replication: The degree of replication is configurable on a per file basis, with a max. limit of 64.
    <li>Re-replication: Whenever the degree of replication for a file drops below the configured amount (such as, due to an extended chunkserver outage), the metaserver forces the block to be re-replicated on the remaining chunk servers. Re-replication is done in the background without overwhelming the system.
    <li>Re-balancing: Periodically, the meta-server may rebalance the chunks amongst chunkservers. This is done to help with balancing disk space utilization amongst nodes.
    <li>Data integrity: To handle disk corruptions to data blocks, data blocks are checksummed. Checksum verification is done on each read; whenever there is a checksum mismatch, re-replication is used to recover the corrupted chunk.
    <li>File writes: The system follows the standard model. When an application creates a file, the filename becomes part of the filesystem namespace. For performance, writes are cached at the KFS client library. Periodically, the cache is flushed and data is pushed out to the chunkservers. Also, applications can force data to be flushed to the chunkservers. In either case, once data is flushed to the server, it is available for reading.
    <li>Leases: KFS client library uses caching to improve performance. Leases are used to support cache consistency.
    <li>Chunk versioning: Versioning is used to detect stale chunks.
    <li>Client side fail-over: The client library is resilient to chunksever failures. During reads, if the client library determines that the chunkserver it is communicating with is unreachable, the client library will fail-over to another chunkserver and continue the read. This fail-over is transparent to the application.
    <li>Language support: KFS client library can be accessed from C++, Java, and Python.
    <li>FUSE support on Linux: By mounting KFS via FUSE, this support allows existing linux utilities (such as, ls) to interface with KFS.
    <li>Tools: A shell binary is included in the set of tools. This allows users to navigate the filesystem tree using utilities such as, cp, ls, mkdir, rmdir, rm, mv. Tools to also monitor the chunk/meta-servers are provided.
    <li>Deploy scrīpts: To simplify launching KFS servers, a set of scrīpts to (1) install KFS binaries on a set of nodes, (2) start/stop KFS servers on a set of nodes are also provided.
    <li>Job placement support: The KFS client library exports an API to determine the location of a byte range of a file. Job placement systems built on top of KFS can leverage this API to schedule jobs appropriately.
    <li>Local read optimization: When applications are run on the same nodes as chunkservers, the KFS client library contains an optimization for reading data locally. That is, if the chunk is stored on the same node as the one on which the application is executing, data is read from the local node. </li>
</ul>
<h5>KFS with Hadoop</h5>
<p>KFS has been integrated with Hadoop using Hadoop&#8217;s filesystem interfaces. This allows existing Hadoop applications to use KFS seamlessly. The integration code has been submitted as a patch to Hadoop-JIRA-1963 (this will enable distribution of the integration code with Hadoop). In addition, the code as well as instructions will also be available for download from the KFS project page shortly. As part of the integration, there is job placement support for Hadoop. That is, the Hadoop Map/Reduce job placement system can schedule jobs on the nodes where the chunks are stored.</p>
<h3>参考资料：</h3>
<ul>
    <li>distribute file system </li>
</ul>
<p><a title=http://lucene.apache.org/hadoop/ href="http://lucene.apache.org/hadoop/"><u><font color=#0000ff>http://lucene.apache.org/hadoop/</font></u></a></p>
<p><a title=http://www.danga.com/mogilefs/ href="http://www.danga.com/mogilefs/"><u><font color=#0000ff>http://www.danga.com/mogilefs/</font></u></a></p>
<p><a title=http://www.lustre.org/ href="http://www.lustre.org/"><u><font color=#0000ff>http://www.lustre.org/</font></u></a></p>
<p><a title=http://oss.sgi.com/projects/xfs/ href="http://oss.sgi.com/projects/xfs/"><u><font color=#0000ff>http://oss.sgi.com/projects/xfs/</font></u></a></p>
<p>&nbsp;</p>
<p><a title=http://www.megite.com/discover/filesystem href="http://www.megite.com/discover/filesystem"><u><font color=#0000ff>http://www.megite.com/discover/filesystem</font></u></a></p>
<p><a title=http://swik.net/distributed+cluster href="http://swik.net/distributed+cluster"><u><font color=#0000ff>http://swik.net/distributed+cluster</font></u></a></p>
<ul>
    <li>cluster&amp;high availability </li>
</ul>
<p><a title=http://www.gluster.org/index.php href="http://www.gluster.org/index.php"><u><font color=#0000ff>http://www.gluster.org/index.php</font></u></a></p>
<p><a title=http://www.linux-ha.org/ href="http://www.linux-ha.org/"><u><font color=#0000ff>http://www.linux-ha.org/</font></u></a></p>
<p><a title=http://openssi.org/cgi-bin/view?page=openssi.html href="http://openssi.org/"><u><font color=#0000ff>http://openssi.org</font></u></a></p>
<p><a title=http://kerrighed.org/ href="http://kerrighed.org/"><u><font color=#0000ff>http://kerrighed.org/</font></u></a></p>
<p><a title=http://openmosix.sourceforge.net/ href="http://openmosix.sourceforge.net/"><u><font color=#0000ff>http://openmosix.sourceforge.net/</font></u></a></p>
<p>&nbsp;</p>
<p><a title=http://www.linux.com/article.pl?sid=06/09/12/1459204 href="http://www.linux.com/article.pl?sid=06/09/12/1459204"><u><font color=#0000ff>http://www.linux.com/article.pl?sid=06/09/12/1459204</font></u></a></p>
<p><a title=http://labs.google.com/papers/mapreduce.html href="http://labs.google.com/papers/mapreduce.html"><u><font color=#0000ff>http://labs.google.com/papers/mapreduce.html</font></u></a></p>
<img src ="http://www.cppblog.com/jack-wang/aggbug/111246.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jack-wang/" target="_blank">小王</a> 2010-04-01 09:47 <a href="http://www.cppblog.com/jack-wang/archive/2010/04/01/111246.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>谷歌技术“三宝”之一的Google文件系统和Kosmos 文件系统</title><link>http://www.cppblog.com/jack-wang/archive/2010/02/26/108503.html</link><dc:creator>小王</dc:creator><author>小王</author><pubDate>Fri, 26 Feb 2010 09:17:00 GMT</pubDate><guid>http://www.cppblog.com/jack-wang/archive/2010/02/26/108503.html</guid><wfw:comment>http://www.cppblog.com/jack-wang/comments/108503.html</wfw:comment><comments>http://www.cppblog.com/jack-wang/archive/2010/02/26/108503.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jack-wang/comments/commentRss/108503.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jack-wang/services/trackbacks/108503.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 10pt">转：<a href="http://blog.csdn.net/boyplayee/archive/2010/02/22/5318092.aspx">http://blog.csdn.net/boyplayee/archive/2010/02/22/5318092.aspx</a><br><br>谷歌技术&#8220;三宝&#8221;之一的Google文件系统和Kosmos 文件系统 收藏 <br>&nbsp;&nbsp;&nbsp; 虽然针对大规模分布式存储系统，Google将推陈出新，推新的理由有很多，如"single-master design,&#8230;&#8230; but it was certainly unacceptable for latency-sensitive applications, such as video serving."。参考《Google File System II: Dawn of the Multiplying Master Nodes》和《GFS:Evolution on Fast-forward》。但是GFS毕竟为其服务了10年时间，连李开复博士也宣称每个计算机学生都有必要学学这套系统。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 本篇也一起谈谈Kosmos文件系统，传闻Google的两个共同创始人佩奇和布林有两个大学同窗，是两个印度人,名叫Anand Rajaraman和Venky Harinarayan，看到Google获得巨大成功之后，就动手做了个一个新的搜索引擎CloudStore (原先一直叫Kosmos filesystem，现在搭上了云计算的顺风车改了头衔)。在做这个搜索引擎的过程中，他们实现了一个类似GFS的文件系统KFS(很多理念都从GFS那里搬过来，比如constant monitoring, error detection, fault tolerance, and automatic recovery)。因为GFS的论文只是设计，而KFS是开源的，两者结合看效果可能比较好。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp; 首先，看过谷歌工程师写地这篇《The Google File System》的能不能做下面这道证明题：考虑一个拥有1000个节点的GFS集群，定性(不定量)证明：在有800个节点失效的情况下，剩下的200个节点仍然能够完成工作，即performance下降的情况下，scalability,reliability,availability等保持良好。</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">本文想阐释谷歌文件系统的一些设计理念。</p>
<p style="FONT-SIZE: 10pt">一 架构：</p>
<p style="FONT-SIZE: 10pt">下图为谷歌文件系统的结构图，一个GFS集群包含一个主服务器和多个块服务器, 这是一个单一主服务器模型：</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 概括一下块(chunk)的一些信息：块尺寸是64MB；文件被分割成固定尺寸的块，在每个块创建的时候，服务器分配给它一个不变的、唯一的64位的块句柄对它进行标识；每个块都会复制到多个块服务器上。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 主服务器保存三种主要类型的metadata：文件和块的命名空间，文件到块的映射，以及每个块副本的位置，它通过全局的信息精确确定块的位置以及进行复制决定。主服务器的主要工作有：主服务器在后台周期扫猫自己的整个状态，用来在块服务器间实现块的垃圾收集的功能，用来实现块服务器失效的时复制新副本的功能，用来实现负载均衡的块移动的功能，以及用来实现统计硬盘使用情况的功能等。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 块服务器保存着块，并根据指定的块句柄和字节区间来读写块数据。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 客户端不通过主服务器读写数据。反之，客户端向主服务器询问它应该联系的块服务器。客户端短期缓存这些信息，后续的操作直接跟块服务器进行。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 读取流程:首先，利用固定的块尺寸，客户端把文件名和程序指定的字节偏移转换成文件的块索引。然后，它把文件名和块索引发送给主服务器。主服务器回答相应的块句柄和副本们的位置。客户端用文件名和块索引作为键值缓存这些信息。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 此系统可靠性方面相关的一些设计，下面概要叙述一下，后面会有详细描述：</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1主服务器不持久化保存块的位置信息。主服务器在自己启动以及块服务器加入集群的时候，询问块服务器它所包含的块的信息，然后定期的心跳信息监控块服务器的状态。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2 名称空间和文件块映射的metadata，会用log的方式保存在主服务器的硬盘上的操作日志内，并在远程的机器内复制一个副本。使用log，可以更新主服务器的状态，而且不用担心服务器崩溃带来的数据不一致的风险。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3. 主服务器通过重放operation log恢复其文件系统。operation log是metadata唯一的持久化存储记录，起到了定义同步操作顺序的逻辑时间线的作用。文件和块及其版本都是唯一和持久地由他们创建时的逻辑时间标识的。进行恢复仅需要最新的checkpoint和相应的日志文件。日志增长到一个特定尺寸的时候，主服务器汇总的状态为一个checkpoint。</p>
<p style="FONT-SIZE: 10pt">4文件命名空间的修改（例如，文件创建）是原子性的。他们仅受主服务器的控制：命名空间锁定保证了原子性和正确性；主服务器的操作日志定义了这些操作的全局总顺序。在修改操作成功后，部件故障仍可以使数据受到破坏。GFS通过master和chunkserver间定期的handshake，借助校验和来检测对数据的破坏。一旦检测到，就从一个有效的副本尽快重新存储。只有在GFS检测前，所有的副本都失效，这个块才会丢失。</p>
<p style="FONT-SIZE: 10pt">5&#8230;&#8230;&#8230;&#8230;&#8230;.</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">二 系统交互</p>
<p style="FONT-SIZE: 10pt">这一节讨论客户机，服务器和块服务器三者如何交互以实现数据操作，原子化的记录追加及快照。</p>
<p style="FONT-SIZE: 10pt">2.1 leases and mutation order</p>
<p style="FONT-SIZE: 10pt">Mutations是一个会改变块内容或者元数据的操作，例如写入或者记录追加。每个变更执行在块的所有副本上。使用leases来保持多个副本间变更顺序的一致性，leases机制的设计是为了最小化主服务器的管理负载。由于Master首先grants一个主块（即副本中的一个块lease），所以全局的mutation order就形成了：首先由主服务器选择的lease生成顺序决定，然后由lease中主块分配的序列号决定。再用图来说明写入操作的控制流程：</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1客户机向主服务器询问哪一个块服务器保存了当前的lease，以及其它副本的位置。如果没有一个块服务器有lease，主服务器就选择一个副本给它一个lease（没有被显示出来）。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2主服务器回复主块的标识符以及其他副本的位置。客户机为了后续的操作缓存这个数据。只有主块不可用，或者主块回复说它已经不再拥有lease的时候，客户机才需要重新跟主服务器联络。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3客户机把数据推送到所有的副本上。客户机可以用任意的顺序推送。每个块服务器会把这些数据保存在它的内部LRU缓冲内，直到数据被使用或者过期。通过把数据流和控制流分离，我们可以基于网络负载状况对昂贵的数据流进行规划，以提高性能，而不用去管哪个块服务器是主块。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4所有的副本都被确认已经得到数据后，客户机发送写请求到主块。这个请求标识了早前推送到所有副本的数据。主块为收到的所有操作分配连续的序列号，这些可能来自不同的客户机。它依照序列号的顺序把这些操作应用到它自己的本地状态中。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5主块把写请求传递到所有的二级副本。每个二级副本依照主块分配的序列号的顺序应用这些操作。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6所有二级副本回复主块说明他们已经完成操作。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7主块回复客户机。任何副本产生的错误都会报告给客户机。错误的情况下，主块和一些二级副本可能成功的写入了数据。（如果主块写入失败，操作就不会被分配序列号，也不会被传递。）客户端请求被确认为失败，已经修改的区域保持不一致的状态。我们的客户机代码通过重复失败的操作来处理这样的错误。在完全从头开始写入之前，可能会先从步骤3到步骤7进行几次尝试。</p>
<p style="FONT-SIZE: 10pt">&nbsp;2.2 数据流</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据流和控制流分开。控制流从客户机到主块然后再到所有二级副本的同时，数据顺序推送到一个精心选择的管道形式的块服务器链。特点：用IP地址就可以计算出节点的远近；用在TCP连接上管道化数据传输来最小化延迟。</p>
<p style="FONT-SIZE: 10pt">2.3 原子性的记录追加</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GFS提供了一个原子性的添加操作：record append。在传统的写操作中，client指定被写数据的偏移位置，向同一个区间的并发的写操作是不连续的：区间有可能包含来自多个client的数据碎片。在record append中， client只是指定数据。GFS在其选定的偏移出将数据至少原子性的加入文件一次，并将偏移返回给client。</p>
<p style="FONT-SIZE: 10pt">在分布式的应用中，不同机器上的许多client可能会同时向一个文件执行添加操作，添加操作被频繁使用。如果用传统的write操作，可能需要额外的、复杂的、开销较大的同步，例如通过分布式锁管理。在我们的工作量中，这些文件通常以多个生产者单个消费者队列的方式或包含从多个不同 client的综合结果。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Record append和前面讲的write操作的控制流差不多，只是在primary上多了一些逻辑判断。首先，client将数据发送到文件最后一块的所有副本上。然后向primary发送请求。Primary检查添加操作是否会导致该块超过最大的规模（64M）。如果这样，它将该块扩充到最大规模，并告诉其它副本做同样的事，同时通知client该操作需要在下一个块上重新尝试。如果记录满足最大规模的要求，primary就会将数据添加到它的副本上，并告诉其它的副本在同样的偏移处写数据，最后primary向client报告写操作成功。如果在任何一个副本上record append操作失败，client将重新尝试该操作。这时候，同一个块的副本可能包含不同的数据，因为有的可能复制了全部的数据，有的可能只复制了部分。GFS不能保证所有的副本每个字节都是一样的。它只保证每个数据作为一个原子单元被写过至少一次。这个是这样得出的：操作要是成功，数据必须在所有的副本上的同样的偏移处被写过。进一步，从这以后，所有的副本至少和记录一样长，所以后续的记录将被指定到更高的偏移处或者一个不同的块上，即使另一个副本成了primary。根据一致性保证，成功的record append操作的区间是已定义的。而受到干扰的区间是不一致的。</p>
<p style="FONT-SIZE: 10pt">&nbsp;2.4快照</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 快照操作几乎在瞬间构造一个文件和目录树的副本，同时将正在进行的其他修改操作对它的影响减至最小。</p>
<p style="FONT-SIZE: 10pt">我们使用copy-on-write技术来实现snapshot。当master受到一个snapshot请求时，它首先要撤消将要snapshot的文件上块上的lease。这使得任何一个向这些块写数据的操作都必须和master交互以找到拥有lease的副本。这就给master一个创建这个块的副本的机会。</p>
<p style="FONT-SIZE: 10pt">副本被撤销或终止后，master在磁盘上登记执行的操作，然后复制源文件或目录树的metadata以对它的内存状态实施登记的操作。这个新创建的snapshot文件和源文件（其metadata）指向相同的块（chunk）。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Snapshot之后，客户第一次向chunk c写的时候，它发一个请求给master以找到拥有lease的副本。Master注意到chunk c的引用记数比1大，它延迟对用户的响应，选择一个chunk handle C&#8217;,然后要求每一有chunk c的副本的chunkserver创建一个块C&#8217;。每个chunkserver在本地创建chunk C&#8217;避免了网络开销。从这以后和对别的块的操作没有什么区别。</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">3.Mast操作</p>
<p style="FONT-SIZE: 10pt">MASTER执行所有名字空间的操作，除此之外，他还在系统范围管理数据块的复制：决定数据块的放置方案，产生新数据块并将其备份，和其他系统范围的操作协同来确保数据备份的完整性，在所有的数据块服务器之间平衡负载并收回没有使用的存储空间。</p>
<p style="FONT-SIZE: 10pt">3.1 名字空间管理和加锁</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 与传统文件系统不同的是，GFS没有与每个目录相关的能列出其所有文件的数据结构，它也不支持别名（unix中的硬连接或符号连接），不管是对文件或是目录。GFS的名字空间逻辑上是从文件元数据到路径名映射的一个查用表。</p>
<p style="FONT-SIZE: 10pt">MASTER在执行某个操作前都要获得一系列锁，例如，它要对/d1/d2&#8230;/dn/leaf执行操作，则它必须获得/d1，/d1/d2，&#8230;， /d1/d2/&#8230;/dn的读锁，/d1/d2&#8230;/dn/leaf的读锁或写锁（其中leaf可以使文件也可以是目录）。MASTER操作的并行性和数据的一致性就是通过这些锁来实现的。</p>
<p style="FONT-SIZE: 10pt">3.2 备份存储放置策略</p>
<p style="FONT-SIZE: 10pt">一个GFS集群文件系统可能是多层分布的。一般情况下是成千上万个文件块服务器分布于不同的机架上，而这些文件块服务器又被分布于不同机架上的客户来访问。因此，不同机架上的两台机器之间的通信可能通过一个或多个交换机。数据块冗余配置策略要达到多个目的：最大的数据可靠性和可用性，最大的网络带宽利用率。因此，如果仅仅把数据的拷贝置于不同的机器上很难满足这两个要求，必须在不同的机架上进行数据备份。这样即使整个机架被毁或是掉线，也能确保数据的正常使用。这也使数据传输，尤其是读数据，可以充分利用带宽，访问到多个机架，而写操作，则不得不涉及到更多的机架。</p>
<p style="FONT-SIZE: 10pt">3.3 产生、重复制、重平衡数据块</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当MASTER产生新的数据块时，如何放置新数据块，要考虑如下几个因素：（1）尽量放置在磁盘利用率低的数据块服务器上，这样，慢慢地各服务器的磁盘利用率就会达到平衡。（2）尽量控制在一个服务器上的&#8220;新创建&#8221;的次数。（3）由于上一小节讨论的原因，我们需要把数据块放置于不同的机架上。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MASTER在可用的数据块备份低于用户设定的数目时需要进行重复制。这种情况源于多种原因：服务器不可用，数据被破坏，磁盘被破坏，或者备份数目被修改。每个被需要重复制的数据块的优先级根据以下几项确定：第一是现在的数目距目标的距离，对于能阻塞用户程序的数据块，我们也提高它的优先级。最后， MASTER按照产生数据块的原则复制数据块，并把它们放到不同的机架内的服务器上。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MASTER周期性的平衡各服务器上的负载：它检查chunk分布和负载平衡，通过这种方式来填充一个新的服务器而不是把其他的内容统统放置到它上面带来大量的写数据。数据块放置的原则与上面讨论的相同，此外，MASTER还决定哪些数据块要被移除，原则上它会清除那些空闲空间低于平均值的那些服务器。</p>
<p style="FONT-SIZE: 10pt">3.4 垃圾收集</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在一个文件被删除之后，GFS并不立即收回磁盘空间，而是等到垃圾收集程序在文件和数据块级的的检查中收回。</p>
<p style="FONT-SIZE: 10pt">当一个文件被应用程序删除之后，MASTER会立即记录下这些变化，但文件所占用的资源却不会被立即收回，而是重新给文件命了一个隐藏的名字，并附上了删除的时间戳。在MASTER定期检查名字空间时，它删除超过三天（可以设定）的隐藏的文件。在此之前，可以以一个新的名字来读文件，还可以以前的名字恢复。当隐藏的文件在名字空间中被删除以后，它在内存中的元数据即被擦除，这就有效地切断了他和所有数据块的联系。</p>
<p style="FONT-SIZE: 10pt">在一个相似的定期的名字空间检查中，MASTER确认孤儿数据块（不属于任何文件）并擦除它的元数据，在和MASTER的心跳信息交换中，每个服务器报告他所拥有的数据块，MASTER返回元数据不在内存的数据块，服务器即可以删除这些数据块。</p>
<p style="FONT-SIZE: 10pt">3.5 过时数据的探测</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在数据更新时如果服务器停机了，那么他所保存的数据备份就会过时。对每个数据块，MASTER设置了一个版本号来区别更新过的数据块和过时的数据块。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当MASTER授权一个新的lease时，他会增加数据块的版本号并会通知更新数据备份。MASTER和备份都会记录下当前的版本号，如果一个备份当时不可用，那么他的版本号不可能提高，当ChunkServer重新启动并向MASTER报告他的数据块集时，MASTER就会发现过时的数据。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MASTER在定期的垃圾收集程序中清除过时的备份，在此以前，处于效率考虑，在各客户及英大使，他会认为根本不存在过时的数据。作为另一个安全措施， MASTER在给客户及关于数据块的应答或是另外一个读取数据的服务器数据是都会带上版本信息，在操作前客户机和服务器会验证版本信息以确保得到的是最新的数据。</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">4、容错和诊断 </p>
<p style="FONT-SIZE: 10pt">4.1 高可靠性 </p>
<p style="FONT-SIZE: 10pt">4.1.1 快速恢复 </p>
<p style="FONT-SIZE: 10pt">不管如何终止服务，MASTER和数据块服务器都会在几秒钟内恢复状态和运行。实际上，我们不对正常终止和不正常终止进行区分，服务器进程都会被切断而终止。客户机和其他的服务器会经历一个小小的中断，然后它们的特定请求超时，重新连接重启的服务器，重新请求。 </p>
<p style="FONT-SIZE: 10pt">4.1.2 数据块备份 </p>
<p style="FONT-SIZE: 10pt">如上文所讨论的，每个数据块都会被备份到放到不同机架上的不同服务器上。对不同的名字空间，用户可以设置不同的备份级别。在数据块服务器掉线或是数据被破坏时，MASTER会按照需要来复制数据块。 </p>
<p style="FONT-SIZE: 10pt">4.1.3 MASTER备份 </p>
<p style="FONT-SIZE: 10pt">为确保可靠性，MASTER的状态、操作记录和检查点都在多台机器上进行了备份。一个操作只有在数据块服务器硬盘上刷新并被记录在MASTER和其备份的上之后才算是成功的。如果MASTER或是硬盘失败，系统监视器会发现并通过改变域名启动它的一个备份机，而客户机则仅仅是使用规范的名称来访问，并不会发现MASTER的改变。 </p>
<p style="FONT-SIZE: 10pt">4.2 数据完整性 </p>
<p style="FONT-SIZE: 10pt">每个数据块服务器都利用校验和来检验存储数据的完整性。原因：每个服务器随时都有发生崩溃的可能性，并且在两个服务器间比较数据块也是不现实的，同时，在两台服务器间拷贝数据并不能保证数据的一致性。 </p>
<p style="FONT-SIZE: 10pt">每个Chunk按64kB的大小分成块，每个块有32位的校验和，校验和和日志存储在一起，和用户数据分开。 </p>
<p style="FONT-SIZE: 10pt">在读数据时，服务器首先检查与被读内容相关部分的校验和，因此，服务器不会传播错误的数据。如果所检查的内容和校验和不符，服务器就会给数据请求者返回一个错误的信息，并把这个情况报告给MASTER。客户机就会读其他的服务器来获取数据，而MASTER则会从其他的拷贝来复制数据，等到一个新的拷贝完成时，MASTER就会通知报告错误的服务器删除出错的数据块。 </p>
<p style="FONT-SIZE: 10pt">附加写数据时的校验和计算优化了，因为这是主要的写操作。我们只是更新增加部分的校验和，即使末尾部分的校验和数据已被损坏而我们没有检查出来，新的校验和与数据会不相符，这种冲突在下次使用时将会被检查出来。 </p>
<p style="FONT-SIZE: 10pt">相反，如果是覆盖现有数据的写，在写以前，我们必须检查第一和最后一个数据块，然后才能执行写操作，最后计算和记录校验和。如果我们在覆盖以前不先检查首位数据块，计算出的校验和则会因为没被覆盖的数据而产生错误。 </p>
<p style="FONT-SIZE: 10pt">在空闲时间，服务器会检查不活跃的数据块的校验和，这样可以检查出不经常读的数据的错误。一旦错误被检查出来，服务器会拷贝一个正确的数据块来代替错误的。 </p>
<p style="FONT-SIZE: 10pt">4.3 诊断工具 </p>
<p style="FONT-SIZE: 10pt">广泛而细致的诊断日志以微小的代价换取了在问题隔离、诊断、性能分析方面起到了重大的作用。GFS服务器用日志来记录显著的事件（例如服务器停机和启动）和远程的应答。远程日志记录机器之间的请求和应答，通过收集不同机器上的日志记录，并对它们进行分析恢复，我们可以完整地重现活动的场景，并用此来进行错误分析。</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">以下是Kosmos filesystem的一些特性：</p>
<p style="FONT-SIZE: 10pt">自动存储扩充（添加新的chunckserver,系统自动感知）</p>
<p style="FONT-SIZE: 10pt">有效性（复制机制保证文件有效性，一般文件会被以三种方式存储，当其中一个chunkserver出现错误的时候，不会影响&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据的读取）</p>
<p style="FONT-SIZE: 10pt">文件复制粒度：可以配置文件复制的粒度，最大可以被复制64份</p>
<p style="FONT-SIZE: 10pt">还原复制：当其中一个Chunckserver出现故障的时候，Metaserver会强制使用其他的chunckserver</p>
<p style="FONT-SIZE: 10pt">负载平衡（系统周期地检查chunkservers的磁盘利用，并重新平衡chunkservers的磁盘利用，HDFS现在还没有支持）</p>
<p style="FONT-SIZE: 10pt">数据完整性（当要读取数据时检查数据的完整性，如果检验出错使用另外的备份覆盖当前的数据）</p>
<p style="FONT-SIZE: 10pt">文件写入：当一个应用程序创建了一个文件，这个文件名会被立刻写入文件系统，但为了性能，写入的数据会被缓存在kfs客户端.并且周期性的从缓存中把数据更新到chunkserver中。当然，应用程序也可以强制把数据更新到服务器上。一旦数据被更新到服务器，就可以被有效的读取了。</p>
<p style="FONT-SIZE: 10pt">契约（使用契约来保证Client缓存的数据和文件系统中的文件保持一致性）</p>
<p style="FONT-SIZE: 10pt">支持FUSE（在linux系统下，可以通过Fuse 映射一个文件夹，从而可以很方便的读取kfs的文件）</p>
<p style="FONT-SIZE: 10pt">支持C++,Java,Python方式的调用</p>
<p style="FONT-SIZE: 10pt">提供了丰富的工具程序，如kfsshell,cp2kfs等</p>
<p style="FONT-SIZE: 10pt">提供了启动和停止服务的脚本</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/boyplayee/archive/2010/02/22/5318092.aspx">http://blog.csdn.net/boyplayee/archive/2010/02/22/5318092.aspx</a></p>
<img src ="http://www.cppblog.com/jack-wang/aggbug/108503.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jack-wang/" target="_blank">小王</a> 2010-02-26 17:17 <a href="http://www.cppblog.com/jack-wang/archive/2010/02/26/108503.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>分布式文件系统MFS(moosefs)实现存储共享</title><link>http://www.cppblog.com/jack-wang/archive/2010/02/08/107471.html</link><dc:creator>小王</dc:creator><author>小王</author><pubDate>Mon, 08 Feb 2010 01:11:00 GMT</pubDate><guid>http://www.cppblog.com/jack-wang/archive/2010/02/08/107471.html</guid><wfw:comment>http://www.cppblog.com/jack-wang/comments/107471.html</wfw:comment><comments>http://www.cppblog.com/jack-wang/archive/2010/02/08/107471.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jack-wang/comments/commentRss/107471.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jack-wang/services/trackbacks/107471.html</trackback:ping><description><![CDATA[<div style="FONT-SIZE: 10pt" align=center>分布式文件系统MFS(moosefs)实现存储共享</div>
<div style="FONT-SIZE: 10pt" align=center>作者:田逸(<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#115;&#101;&#114;&#121;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;"><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#115;&#101;&#114;&#121;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;">sery@163.com</a></a>) from: <a href="http://net.it168.com/a2009/0403/270/000000270867.shtml">[url]http://net.it168.com/a2009/0403/270/000000270867.shtml[/url]</a></div>
<div style="FONT-SIZE: 10pt" align=center>&nbsp;</div>
<div style="FONT-SIZE: 10pt">由于用户数量的不断攀升,我对访问量大的应用实现了可扩展、高可靠的集群部署（即lvs+keepalived的方式），但仍然有用户反馈访问慢的问题。通过排查个服务器的情况，发现问题的根源在于共享存储服务器NFS。在我这个网络环境里，N个服务器通过nfs方式共享一个服务器的存储空间，使得NFS服务器不堪重负。察看系统日志，全是nfs服务超时之类的报错。一般情况下，当nfs客户端数目较小的时候，NFS性能不会出现问题；一旦NFS服务器数目过多，并且是那种读写都比较频繁的操作，所得到的结果就不是我们所期待的。下面是某个集群使用nfs共享的示意图：<img onclick='window.open("http://blog.51cto.com/viewpic.php?refimg=" + this.src)' border=0 alt="" src="http://img1.51cto.com/attachment/200904/200904091239248490014.jpg"></div>
<div style="FONT-SIZE: 10pt">这种架构除了性能问题而外，还存在单点故障，一旦这个NFS服务器发生故障，所有靠共享提供数据的应用就不再可用，尽管用rsync方式同步数据到另外一个服务器上做nfs服务的备份，但这对提高整个系统的性能毫无帮助。基于这样一种需求，我们需要对nfs服务器进行优化或采取别的解决方案，然而优化并不能对应对日益增多的客户端的性能要求，因此唯一的选择只能是采取别的解决方案了；通过调研，分布式文件系统是一个比较合适的选择。采用分布式文件系统后，服务器之间的数据访问不再是一对多的关系（1个NFS服务器，多个NFS客户端），而是多对多的关系，这样一来，性能大幅提升毫无问题。</div>
<div style="FONT-SIZE: 10pt">&nbsp;</div>
<div style="FONT-SIZE: 10pt">到目前为止，有数十种以上的分布式文件系统解决方案可供选择，如lustre,hadoop,Pnfs等等。我尝试了PVFS,hadoop,moosefs这三种应用，参看了lustre、KFS等诸多技术实施方法，最后我选择了moosefs（以下简称MFS）这种分布式文件系统来作为我的共享存储服务器。为什么要选它呢？我来说说我的一些看法：</div>
<div style="FONT-SIZE: 10pt">1、&nbsp; 实施起来简单。MFS的安装、部署、配置相对于其他几种工具来说，要简单和容易得多。看看lustre 700多页的pdf文档，让人头昏吧。</div>
<div style="FONT-SIZE: 10pt">2、&nbsp; 不停服务扩容。MFS框架做好后，随时增加服务器扩充容量；扩充和减少容量皆不会影响现有的服务。注：hadoop也实现了这个功能。</div>
<div style="FONT-SIZE: 10pt">3、&nbsp; 恢复服务容易。除了MFS本身具备高可用特性外，手动恢复服务也是非常快捷的，原因参照第1条。</div>
<div style="FONT-SIZE: 10pt">4、&nbsp; 我在实验过程中得到作者的帮助，这让我很是感激。</div>
<div style="FONT-SIZE: 10pt"><img onclick='window.open("http://blog.51cto.com/viewpic.php?refimg=" + this.src)' border=0 alt="" src="http://img1.51cto.com/attachment/200904/200904091239248559990.jpg"></div>
<div style="FONT-SIZE: 10pt">MFS文件系统的组成</div>
<div style="FONT-SIZE: 10pt">1、&nbsp;元数据服务器。在整个体系中负责管理管理文件系统，目前MFS只支持一个元数据服务器master，这是一个单点故障，需要一个性能稳定的服务器来充当。希望今后MFS能支持多个master服务器，进一步提高系统的可靠性。</div>
<div style="FONT-SIZE: 10pt">2、&nbsp;数据存储服务器chunkserver。真正存储用户数据的服务器。存储文件时，首先把文件分成块，然后这些块在数据服务器chunkserver之间复制（复制份数可以手工指定，建议设置副本数为3）。数据服务器可以是多个，并且数量越多，可使用的&#8220;磁盘空间&#8221;越大，可靠性也越高。</div>
<div style="FONT-SIZE: 10pt">3、&nbsp;客户端。使用MFS文件系统来存储和访问的主机称为MFS的客户端，成功挂接MFS文件系统以后，就可以像以前使用NFS一样共享这个虚拟性的存储了。</div>
<div style="FONT-SIZE: 10pt">&nbsp;</div>
<div style="FONT-SIZE: 10pt">元数据服务器安装和配置</div>
<div style="FONT-SIZE: 10pt">元数据服务器可以是linux,也可以是unix,你可以根据自己的使用习惯选择操作系统,在我的环境里,我是用freebsd做为MFS元数据的运行平台。GNU源码，在各种类unix平台的安装都基本一致。</div>
<div style="FONT-SIZE: 10pt">&nbsp;</div>
<div style="FONT-SIZE: 10pt">（一）&nbsp;&nbsp; 安装元数据服务</div>
<div style="FONT-SIZE: 10pt">1、下载GNU源码 wget <a href="http://www.moosefs.com/files/mfs-1.5.12.tar.gz">[url]http://www.moosefs.com/files/mfs-1.5.12.tar.gz[/url]</a></div>
<div style="FONT-SIZE: 10pt">2、解包 tar zxvf mfs-<st1:chsdate w:st="on" Year="1899" Month="12" Day="30" IsLunarDate="False" IsROCDate="False">1.5.12</st1:chsdate>.tar.gz</div>
<div style="FONT-SIZE: 10pt">3、切换目录 cd mfs-<st1:chsdate w:st="on" Year="1899" Month="12" Day="30" IsLunarDate="False" IsROCDate="False">1.5.12</st1:chsdate></div>
<div style="FONT-SIZE: 10pt">4、创建用户 useradd mfs &#8211;s /sbin/nologin&nbsp;</div>
<div style="FONT-SIZE: 10pt">5、配置 ./configure --prefix=/usr/local/mfs --with-default-user=mfs --with-default-group=mfs</div>
<div style="FONT-SIZE: 10pt">6、编译安装 make ; make install</div>
<div style="FONT-SIZE: 10pt">&nbsp;</div>
<div style="FONT-SIZE: 10pt">（二）&nbsp;&nbsp; 配置元数据服务</div>
<div style="FONT-SIZE: 10pt">元数据服务器的配置文件是mfsmaster.cfg,我在安装MFS时指定了前缀，因此这个文件的位置在/usr/local/mfs/etc/mfsmaster.cfg.我们打开这个配置文件，看看都有哪些内容：<img onclick='window.open("http://blog.51cto.com/viewpic.php?refimg=" + this.src)' border=0 alt="" src="http://img1.51cto.com/attachment/200904/200904091239248623823.jpg"></div>
<div style="FONT-SIZE: 10pt">尽管每行都被注释掉了，但它们却是配置文件的默认值，要改变这些值，需要取消注释，然后明确指定其取值。接下来说明一下其中一些项目的含义。</div>
<div style="FONT-SIZE: 10pt">◆&nbsp;&nbsp;&nbsp;&nbsp; LOCK_FILE = /var/run/mfs/mfsmaster.pid 文件锁所在的位置，它的功能是避免启动多次启动同一个守护进程。由于系统中本来不存在目录 /var/run/mfs，因此需要手动创建 mkdir /var/run/mfs，然后更改其属主 chown &#8211;R mfs:mfs /var/run/mfs 这样MFS 服务就能对这个目录有创建/写入 mfsmaster.pid 文件的权限了。</div>
<div style="FONT-SIZE: 10pt">◆&nbsp;&nbsp;&nbsp;&nbsp; DATA_PATH = /usr/local/mfs/var/mfs 数据存放路径，只元数据的存放路径。那么这些数据都包括哪些呢？进目录看看，大致分3种类型的文件：</div>
<div style="FONT-SIZE: 10pt"><img onclick='window.open("http://blog.51cto.com/viewpic.php?refimg=" + this.src)' border=0 alt="" src="http://img1.51cto.com/attachment/200904/200904091239248673306.jpg"></div>
<div style="FONT-SIZE: 10pt">这些文件也同样要存储在其他数据存储服务器的相关目录。</div>
<div style="FONT-SIZE: 10pt">◆&nbsp;&nbsp;&nbsp;&nbsp; MATOCS_LISTEN_PORT = 9420 MATOCS--master to chunkserver，即元数据服务器使用9420这个监听端口来接受数据存储服务器chunkserver端的连接。</div>
<div style="FONT-SIZE: 10pt">◆&nbsp;&nbsp;&nbsp;&nbsp; MATOCU_LISTEN_PORT = 9421 元数据服务器在9421端口监听，用以接受客户端对MFS进行远程挂接（客户端以mfsmount挂接MFS）</div>
<div style="FONT-SIZE: 10pt">◆&nbsp;&nbsp;&nbsp;&nbsp; 其他部分看字面意思都不难理解。还有几个与时间有关的数值，其单位是秒。</div>
<div style="FONT-SIZE: 10pt">这个配置文件，不必做修改就能工作了。</div>
<div style="FONT-SIZE: 10pt">&nbsp;</div>
<div style="FONT-SIZE: 10pt">（一）&nbsp;&nbsp; 元数据服务器master启动</div>
<div style="FONT-SIZE: 10pt">元数据服务器可以单独启动，即使没有任何数据存储服务器（chunkserver）也是能正常工作的，因此当我们安装配置完MFS后，即可启动它。执行命令 /usr/local/mfs/sbin/mfsmaster start ，如果没有意外，元数据库服务器就应该作为一个守护进程运行起来。现在我们可以通过3个方面来检查一下MFS master的运行状况：</div>
<div style="FONT-SIZE: 10pt"><img onclick='window.open("http://blog.51cto.com/viewpic.php?refimg=" + this.src)' border=0 alt="" src="http://img1.51cto.com/attachment/200904/200904091239248710627.jpg"></div>
<div style="FONT-SIZE: 10pt">（四）、关闭元数据服务器</div>
<div style="FONT-SIZE: 10pt">关闭元数据服务器，务必使用 /usr/local/mfs/sbin/mfsmaster &#8211;s 这种方式，如果直接使用kill杀死进程，将导致下次启动时出现找不到相关文件，而不能正常启动服务器。这个一定要谨慎。当然，如果发生了这个事情，还是可以通过 mfsmetastore 来恢复的。</div>
<div style="FONT-SIZE: 10pt">&nbsp;</div>
<div style="FONT-SIZE: 10pt">数据存储chunkserver服务器的安装配置</div>
<div style="FONT-SIZE: 10pt">数据存储服务器chunkserver也是可以运行在各种类unix平台的，因此不再多说。一个MFS环境到底能集群多少服务器，作者的说法是上PB容量，个人建议，最好3台以上；并且专门用来做存储，不要把它跟master搞到一个机器（理论上没问题，实现也是可以的，但这不是一个好策略）。因为每个数据存储服务器的安装和配置都是相同的，所以只需按照一个服务器的操作就可以了。</div>
<div style="FONT-SIZE: 10pt">&nbsp;</div>
<div style="FONT-SIZE: 10pt">（一）、安装数据存储服务器 chunkserver</div>
<div style="FONT-SIZE: 10pt">1、下载GNU源码 wget <a href="http://www.moosefs.com/files/mfs-1.5.12.tar.gz">[url]http://www.moosefs.com/files/mfs-1.5.12.tar.gz[/url]</a></div>
<div style="FONT-SIZE: 10pt">2、解包 tar zxvf mfs-<st1:chsdate w:st="on" Year="1899" Month="12" Day="30" IsLunarDate="False" IsROCDate="False">1.5.12</st1:chsdate>.tar.gz</div>
<div style="FONT-SIZE: 10pt">3、切换目录 cd mfs-<st1:chsdate w:st="on" Year="1899" Month="12" Day="30" IsLunarDate="False" IsROCDate="False">1.5.12</st1:chsdate></div>
<div style="FONT-SIZE: 10pt">4、创建用户 useradd mfs &#8211;s /sbin/nologin&nbsp;</div>
<div style="FONT-SIZE: 10pt">5、配置 ./configure --prefix=/usr/local/mfs --with-default-user=mfs --with-default-group=mfs</div>
<div style="FONT-SIZE: 10pt">6、编译安装 make ; make install</div>
<div style="FONT-SIZE: 10pt">&nbsp;</div>
<div style="FONT-SIZE: 10pt">（二）配置数据存储服务器chunkserver</div>
<div style="FONT-SIZE: 10pt">数据存储服务器有2个配置服务器需要修改，一个是主配置文件 mfschunkserver.cfg ,另一个配置文件是 mfshdd.cfg。每个服务器用来分配给 MFS使用的空间最好是一个单独的硬盘或者一个raid卷，最低要求是一个分区。作者举的例子是创建一个大文件，然后挂接在本地，这不好，只能用来做实验了。</div>
<p style="FONT-SIZE: 10pt">1、修改配置文件 /usr/local/mfs/etc/mfschunkserver.cfg。下面是修改了的配置文件： </p>
<div style="FONT-SIZE: 10pt">&nbsp;</div>
<div style="FONT-SIZE: 10pt">&nbsp;</div>
<div style="FONT-SIZE: 10pt"><img onclick='window.open("http://blog.51cto.com/viewpic.php?refimg=" + this.src)' border=0 alt="" src="http://img1.51cto.com/attachment/200904/200904091239248762099.jpg"></div>
<div style="FONT-SIZE: 10pt">这个配置文件里，没有注释符号&#8220;#&#8221;就是被修改过的项了，接下来是里面某些项的含义说明：</div>
<div style="FONT-SIZE: 10pt">◆&nbsp;&nbsp;&nbsp;&nbsp; MASTER_HOST = 192.168.0.19 元数据服务器的名称或地址，可以是主机名，也可以是ip地址，只要数据存储服务器能访问到元数据服务器就行。</div>
<div style="FONT-SIZE: 10pt">◆&nbsp;&nbsp;&nbsp;&nbsp; LOCK_FILE = /var/run/mfs/mfschunkserver.pid 与元数据服务器master的处理完全相同.</div>
<div style="FONT-SIZE: 10pt">◆&nbsp;&nbsp;&nbsp;&nbsp; CSSERV_LISTEN_PORT = 9422 CSSERV—chunkserver,这个监听端口用于与其它数据存储服务器间的连接，通常是数据复制。</div>
<div style="FONT-SIZE: 10pt">◆&nbsp;&nbsp;&nbsp;&nbsp; HDD_CONF_FILENAME = <a name=OLE_LINK1>/usr/local/mfs/etc/mfshdd.cfg</a> 分配给MFS使用的磁盘空间配置文件的位置。</div>
<div style="FONT-SIZE: 10pt">2、修改配置文件/usr/local/mfs/etc/mfshdd.cfg。在我的服务器上，只有一个1T的SATA硬盘，分了一个<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="800" UnitName="g">800G</st1:chmetcnv>容量的分区来做为MFS存储服务的组成部分。为了使mfs拥有写目录的权限，需要修改目录的属主。我的服务器的分区挂接点是 /data , 用 chown &#8211;R mfs:mfs /data 把属主改变。因为我的每个服务器只需贡献一个分区做为MFS,因此配置文件只需要如下一行内容就可以了：</div>
<div style="FONT-SIZE: 10pt"><img onclick='window.open("http://blog.51cto.com/viewpic.php?refimg=" + this.src)' border=0 alt="" src="http://img1.51cto.com/attachment/200904/200904091239248804880.jpg"></div>
<div style="FONT-SIZE: 10pt">（四）&nbsp;&nbsp; 关闭数据存储服务器</div>
<div style="FONT-SIZE: 10pt">跟元数据服务器master相似，执行命令 /usr/local/mfs/sbin/mfschunkserver &#8211;s , chunkserver服务就停下来了。为了使系统重启过程能自动启动chunkserver&nbsp;服务，可以通过在/etc/rc.local文件追加行 &nbsp;/usr/local/mfs/sbin/mfschunkserver start 来达到这个目的（master的自动重启处理也可同样处理）。</div>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">本文出自 &#8220;<a href="http://sery.blog.51cto.com/">sery</a>&#8221; 博客，请务必保留此出处<a href="http://sery.blog.51cto.com/10037/147756">http://sery.blog.51cto.com/10037/147756</a></p>
<img src ="http://www.cppblog.com/jack-wang/aggbug/107471.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jack-wang/" target="_blank">小王</a> 2010-02-08 09:11 <a href="http://www.cppblog.com/jack-wang/archive/2010/02/08/107471.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用Hadoop进行分布式并行编程</title><link>http://www.cppblog.com/jack-wang/archive/2010/01/28/106616.html</link><dc:creator>小王</dc:creator><author>小王</author><pubDate>Thu, 28 Jan 2010 05:50:00 GMT</pubDate><guid>http://www.cppblog.com/jack-wang/archive/2010/01/28/106616.html</guid><wfw:comment>http://www.cppblog.com/jack-wang/comments/106616.html</wfw:comment><comments>http://www.cppblog.com/jack-wang/archive/2010/01/28/106616.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jack-wang/comments/commentRss/106616.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jack-wang/services/trackbacks/106616.html</trackback:ping><description><![CDATA[原帖：<a href="http://www.cnblogs.com/phinecos/">http://www.cnblogs.com/phinecos/</a><br><br>Hadoop <span>是一个实现了</span><span> MapReduce </span><span>计算模型的开源分布式并行编程框架，借助于</span><span> Hadoop, </span><span>程序员可以轻松地编写分布式并行程序，将其运行于计算机集群上，完成海量数据的计算。本文将介绍</span><span> MapReduce </span><span>计算模型，分布式并行计算等基本概念，以及</span><span> Hadoop </span><span>的安装部署和基本运行方法。</span><span> </span>
<p align=left><a name=N10059><strong><span>Hadoop </span></strong></a><strong><span>简介</span></strong><strong> </strong></p>
<p align=left><span>Hadoop </span><span>是一个开源的可运行于大规模集群上的分布式并行编程框架，由于分布式存储对于分布式编程来说是必不可少的，这个框架中还包含了一个分布式文件系统</span><span> HDFS( Hadoop Distributed File System )</span><span>。也许到目前为止，</span><span>Hadoop </span><span>还不是那么广为人知，其最新的版本号也仅仅是</span><span> 0.16</span><span>，距离</span><span> 1.0 </span><span>似乎都还有很长的一段距离，但提及</span><span> Hadoop </span><span>一脉相承的另外两个开源项目</span><span> Nutch </span><span>和</span><span> Lucene ( </span><span>三者的创始人都是</span><span> Doug Cutting ),</span><span>那绝对是大名鼎鼎。</span><span>Lucene </span><span>是一个用</span><span> Java </span><span>开发的开源高性能全文检索工具包，它不是一个完整的应用程序，而是一套简单易用的</span><span> API </span><span>。在全世界范围内，已有无数的软件系统，</span><span>Web </span><span>网站基于</span><span> Lucene </span><span>实现了全文检索功能，后来</span><span> Doug Cutting </span><span>又开创了第一个开源的</span><span> Web </span><span>搜索引擎</span><span>(<a href="http://www.nutch.org/">http://www.nutch.org/</a>) Nutch, </span><span>它在</span><span> Lucene </span><span>的基础上增加了网络爬虫和一些和</span><span> Web </span><span>相关的功能，一些解析各类文档格式的插件等，此外，</span><span>Nutch </span><span>中还包含了一个分布式文件系统用于存储数据。从</span><span> Nutch 0.8.0 </span><span>版本之后，</span><span>Doug Cutting </span><span>把</span><span> Nutch </span><span>中的分布式文件系统以及实现</span><span> MapReduce </span><span>算法的代码独立出来形成了一个新的开源项</span><span> Hadoop</span><span>。</span><span>Nutch </span><span>也演化为基于</span><span> Lucene </span><span>全文检索以及</span><span> Hadoop </span><span>分布式计算平台的一个开源搜索引擎。</span></p>
<p align=left><span>基于</span><span> Hadoop,</span><span>你可以轻松地编写可处理海量数据的分布式并行程序，并将其运行于由成百上千个结点组成的大规模计算机集群上。从目前的情况来</span> <span>看，</span><span>Hadoop </span><span>注定会有一个辉煌的未来：</span><span>"</span><span>云计算</span><span>"</span><span>是目前灸手可热的技术名词，全球各大</span><span> IT </span><span>公司都在投资和推广这种新一代的计算模式，而</span><span> Hadoop </span><span>又被其中几家主要的公司用作其</span><span>"</span><span>云计算</span><span>"</span><span>环境中的重要基础软件，如</span><span>:</span><span>雅虎正在借助</span><span> Hadoop </span><span>开源平台的力量对抗</span><span> Google, </span><span>除了资助</span><span> Hadoop </span><span>开发团队外，还在开发基于</span><span> Hadoop </span><span>的开源项目</span><span> Pig, </span><span>这是一个专注于海量数据集分析的分布式计算程序。</span><span>Amazon </span><span>公司基于</span><span> Hadoop </span><span>推出了</span><span> Amazon S3 ( Amazon Simple Storage Service )</span><span>，提供可靠，快速，可扩展的网络存储服务，以及一个商用的云计算平台</span><span> Amazon EC2 ( Amazon Elastic Compute Cloud )</span><span>。在</span><span> IBM </span><span>公司的云计算项目</span><span>--"</span><span>蓝云计划</span><span>"</span><span>中，</span><span>Hadoop </span><span>也是其中重要的基础软件。</span><span>Google </span><span>正在跟</span><span>IBM</span><span>合作，共同推广基于</span><span> Hadoop </span><span>的云计算。</span><span> </span></p>
<p align=left><a name=N1006D><strong><span>迎接编程方式的变革</span></strong></a> </p>
<p align=left><span>在摩尔定律的作用下，以前程序员根本不用考虑计算机的性能会跟不上软件的发展，因为约每隔</span><span> 18 </span><span>个月，</span><span>CPU </span><span>的主频就会增加一倍，性能也将提升一倍，软件根本不用做任何改变，就可以享受免费的性能提升。然而，由于晶体管电路已经逐渐接近其物理上的性能极限，摩尔</span> <span>定律在</span><span> 2005 </span><span>年左右开始失效了，人类再也不能期待单个</span><span> CPU </span><span>的速度每隔</span><span> 18 </span><span>个月就翻一倍，为我们提供越来越快的计算性能。</span><span>Intel, AMD, IBM </span><span>等芯片厂商开始从多核这个角度来挖掘</span><span> CPU </span><span>的性能潜力，多核时代以及互联网时代的到来，将使软件编程方式发生重大变革，基于多核的多线程并发编程以及基于大规模计算机集群的分布式并行编程是将来软</span> <span>件性能提升的主要途径。</span><span> </span></p>
<p align=left><span>许多人认为这种编程方式的重大变化将带来一次软件的并发危机，因为我们传统的软件方式基本上是单指令单数据流的顺序执行，这种顺序执行十分符合人类的思考</span> <span>习惯，却与并发并行编程格格不入。基于集群的分布式并行编程能够让软件与数据同时运行在连成一个网络的许多台计算机上</span><span>,</span><span>这里的每一台计算机均可以是一台普</span> <span>通的</span><span> PC </span><span>机。这样的分布式并行环境的最大优点是可以很容易的通过增加计算机来扩充新的计算结点，并由此获得不可思议的海量计算能力</span><span>, </span><span>同时又具有相当强的容错能力，一批计算结点失效也不会影响计算的正常进行以及结果的正确性。</span><span>Google </span><span>就是这么做的，他们使用了叫做</span><span> MapReduce </span><span>的并行编程模型进行分布式并行编程，运行在叫做</span><span> GFS ( Google File System )</span><span>的分布式文件系统上，为全球亿万用户提供搜索服务。</span><span> </span></p>
<p align=left><span>Hadoop </span><span>实现了</span><span> Google </span><span>的</span><span> MapReduce </span><span>编程模型，提供了简单易用的编程接口，也提供了它自己的分布式文件系统</span><span> HDFS,</span><span>与</span><span> Google </span><span>不同的是，</span><span>Hadoop </span><span>是开源的，任何人都可以使用这个框架来进行并行编程。如果说分布式并行编程的难度足以让普通程序员望而生畏的话，开源的</span><span> Hadoop </span><span>的出现极大的降低了它的门槛，读完本文，你会发现基于</span><span> Hadoop </span><span>编程非常简单，无须任何并行开发经验，你也可以轻松的开发出分布式的并行程序，并让其令人难以置信地同时运行在数百台机器上，然后在短时间内完成海量数据</span> <span>的计算。你可能会觉得你不可能会拥有数百台机器来运行你的并行程序，而事实上，随着</span><span>"</span><span>云计算</span><span>"</span><span>的普及，任何人都可以轻松获得这样的海量计算能力。</span> <span>例如现在</span><span> Amazon </span><span>公司的云计算平台</span><span> Amazon EC2 </span><span>已经提供了这种按需计算的租用服务，有兴趣的读者可以去了解一下，这篇系列文章的第三部分将有所介绍。</span><span> </span></p>
<p align=left><span>掌握一点分布式并行编程的知识对将来的程序员是必不可少的，</span><span>Hadoop </span><span>是如此的简便好用，何不尝试一下呢？也许你已经急不可耐的想试一下基于</span><span> Hadoop </span><span>的编程是怎么回事了，但毕竟这种编程模型与传统的顺序程序大不相同，掌握一点基础知识才能更好地理解基于</span><span> Hadoop </span><span>的分布式并行程序是如何编写和运行的。因此本文会先介绍一下</span><span> MapReduce </span><span>的计算模型，</span><span>Hadoop </span><span>中的分布式文件系统</span><span> HDFS, Hadoop </span><span>是如何实现并行计算的，然后才介绍如何安装和部署</span><span> Hadoop </span><span>框架，以及如何运行</span><span> Hadoop </span><span>程序。</span><span> </span></p>
<p align=left><a name=N10083><strong><span>MapReduce </span></strong></a><strong><span>计算模型</span></strong> </p>
<p align=left><span>MapReduce </span><span>是</span><span> Google </span><span>公司的核心计算模型，它将复杂的运行于大规模集群上的并行计算过程高度的抽象到了两个函数，</span><span>Map </span><span>和</span><span> Reduce, </span><span>这是一个令人惊讶的简单却又威力巨大的模型。适合用</span><span> MapReduce </span><span>来处理的数据集</span><span>(</span><span>或任务</span><span>)</span><span>有一个基本要求</span><span>: </span><span>待处理的数据集可以分解成许多小的数据集，而且每一个小数据集都可以完全并行地进行处理。</span><span> </span><span><br></span><a name=fig1><strong><span>图</span><span> 1. MapReduce </span><span>计算流程</span></strong></a><span><br><br></span></p>
<p><img alt="" src="http://www.ibm.com/developerworks/cn/opensource/os-cn-hadoop1/figure1.jpg">&nbsp;</p>
<p align=left><span>图一说明了用</span><span> MapReduce </span><span>来处理大数据集的过程</span><span>, </span><span>这个</span><span> MapReduce </span><span>的计算过程简而言之，就是将大数据集分解为成百上千的小数据集，每个</span><span>(</span><span>或若干个</span><span>)</span><span>数据集分别由集群中的一个结点</span><span>(</span><span>一般就是一台普通的计算机</span><span>)</span><span>进行处理并生</span> <span>成中间结果，然后这些中间结果又由大量的结点进行合并</span><span>, </span><span>形成最终结果。</span><span> </span></p>
<p align=left><span>计算模型的核心是</span><span> Map </span><span>和</span><span> Reduce </span><span>两个函数，这两个函数由用户负责实现，功能是按一定的映射规则将输入的</span><span> &lt;key, value&gt; </span><span>对转换成另一个或一批</span><span> &lt;key, value&gt; </span><span>对输出。</span><span> <br></span><strong><span>表一</span></strong><strong><span> Map </span></strong><strong><span>和</span></strong><strong><span> Reduce </span></strong><strong><span>函数</span></strong></p>
<p>
<table border=0 cellSpacing=0 cellPadding=0 width="100%">
    <tbody>
        <tr>
            <td>
            <p align=center><strong><span>函数</span></strong><strong></strong></p>
            </td>
            <td>
            <p align=center><strong><span>输入</span></strong><strong></strong></p>
            </td>
            <td>
            <p align=center><strong><span>输出</span></strong><strong></strong></p>
            </td>
            <td>
            <p align=center><strong><span>说明</span></strong><strong></strong></p>
            </td>
        </tr>
        <tr>
            <td>
            <p align=center><strong><span>Map</span></strong></p>
            </td>
            <td>
            <p align=left><span>&lt;k1, v1&gt;</span></p>
            </td>
            <td>
            <p align=left><span>List(&lt;k2,v2&gt;)</span></p>
            </td>
            <td>
            <p align=left><span>1. </span><span>将小数据集进一步解析成一批</span><span> &lt;key,value&gt; </span><span>对，输入</span><span> Map </span><span>函数中进行处理。</span><span><br>2. </span><span>每一个输入的</span><span> &lt;k1,v1&gt; </span><span>会输出一批</span><span> &lt;k2,v2&gt;</span><span>。</span><span> &lt;k2,v2&gt; </span><span>是计算的中间结果。</span> </p>
            </td>
        </tr>
        <tr>
            <td>
            <p align=center><strong><span>Reduce</span></strong></p>
            </td>
            <td>
            <p align=left><span>&lt;k2,List(v2)&gt;</span></p>
            </td>
            <td>
            <p align=left><span>&lt;k3,v3&gt;</span></p>
            </td>
            <td>
            <p align=left><span>输入的中间结果</span><span> &lt;k2,List(v2)&gt; </span><span>中的</span><span> List(v2) </span><span>表示是一批属于同一个</span><span> k2 </span><span>的</span><span> value</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p align=left><span>以一个计算文本文件中每个单词出现的次数的程序为例，</span><span>&lt;k1,v1&gt; </span><span>可以是</span><span> &lt;</span><span>行在文件中的偏移位置</span><span>, </span><span>文件中的一行</span><span>&gt;</span><span>，经</span><span> Map </span><span>函数映射之后，形成一批中间结果</span><span> &lt;</span><span>单词，出现次数</span><span>&gt;, </span><span>而</span><span> Reduce </span><span>函数则可以对中间结果进行处理，将相同单词的出现次数进行累加，得到每个单词的总的出现次数。</span><span> </span></p>
<p align=left><span>基于</span><span> MapReduce </span><span>计算模型编写分布式并行程序非常简单，程序员的主要编码工作就是实现</span><span> Map </span><span>和</span><span> Reduce </span><span>函数，其它的并行编程中的种种复杂问题，如分布式存储，工作调度，负载平衡，容错处理，网络通信等，均由</span><span> MapReduce </span><span>框架</span><span>(</span><span>比如</span><span> Hadoop )</span><span>负责处理，程序员完全不用操心。</span><span> </span></p>
<p align=left><a name=N100F0><strong><span>四</span></strong></a><strong> </strong><strong><span>集群上的并行计算</span></strong> </p>
<p align=left><span>MapReduce </span><span>计算模型非常适合在大量计算机组成的大规模集群上并行运行。图一中的每一个</span><span> Map </span><span>任务和每一个</span><span> Reduce </span><span>任务均可以同时运行于一个单独的计算结点上，可想而知其运算效率是很高的，那么这样的并行计算是如何做到的呢？</span><span> </span></p>
<p align=left><strong><span>数据分布存储</span></strong><strong></strong></p>
<p align=left><span>Hadoop </span><span>中的分布式文件系统</span><span> HDFS </span><span>由一个管理结点</span><span> ( NameNode )</span><span>和</span><span>N</span><span>个数据结点</span><span> ( DataNode )</span><span>组成，每个结点均是一台普通的计算机。在使用上同我们熟悉的单机上的文件系统非常类似，一样可以建目录，创建，复制，删除文件，查看文件内容等。但其底</span> <span>层实现上是把文件切割成</span><span> Block</span><span>，然后这些</span><span> Block </span><span>分散地存储于不同的</span><span> DataNode </span><span>上，每个</span><span> Block </span><span>还可以复制数份存储于不同的</span><span> DataNode </span><span>上，达到容错容灾之目的。</span><span>NameNode </span><span>则是整个</span><span> HDFS </span><span>的核心，它通过维护一些数据结构，记录了每一个文件被切割成了多少个</span><span> Block</span><span>，这些</span><span> Block </span><span>可以从哪些</span><span> DataNode </span><span>中获得，各个</span><span> DataNode </span><span>的状态等重要信息。如果你想了解更多的关于</span><span> HDFS </span><span>的信息，可进一步阅读参考资料：</span><span><a href="http://hadoop.apache.org/core/docs/r0.16.0/hdfs_design.html"> The Hadoop Distributed File System:Architecture and Design</a> </span></p>
<p align=left><strong><span>分布式并行计算</span></strong><strong></strong></p>
<p align=left><span>Hadoop </span><span>中有一个作为主控的</span><span> JobTracker</span><span>，用于调度和管理其它的</span><span> TaskTracker, JobTracker </span><span>可以运行于集群中任一台计算机上。</span><span>TaskTracker </span><span>负责执行任务，必须运行于</span><span> DataNode </span><span>上，即</span><span> DataNode </span><span>既是数据存储结点，也是计算结点。</span><span> JobTracker </span><span>将</span><span> Map </span><span>任务和</span><span> Reduce </span><span>任务分发给空闲的</span><span> TaskTracker, </span><span>让这些任务并行运行，并负责监控任务的运行情况。如果某一个</span><span> TaskTracker </span><span>出故障了，</span><span>JobTracker </span><span>会将其负责的任务转交给另一个空闲的</span><span> TaskTracker </span><span>重新运行。</span><span> </span></p>
<p align=left><strong><span>本地计算</span></strong><strong></strong></p>
<p align=left><span>数据存储在哪一台计算机上，就由这台计算机进行这部分数据的计算，这样可以减少数据在网络上的传输，降低对网络带宽的需求。在</span><span> Hadoop </span><span>这样的基于集群的分布式并行系统中，计算结点可以很方便地扩充，而因它所能够提供的计算能力近乎是无限的，但是由是数据需要在不同的计算机之间流动，故网</span> <span>络带宽变成了瓶颈，是非常宝贵的，</span><span>&#8220;</span><span>本地计算</span><span>&#8221;</span><span>是最有效的一种节约网络带宽的手段，业界把这形容为</span><span>&#8220;</span><span>移动计算比移动数据更经济</span><span>&#8221;</span><span>。</span><span> </span><span><br></span><a name=fig2><strong><span>图</span><span> 2. </span><span>分布存储与并行计算</span></strong></a><span><br><br></span></p>
<p><img alt="" src="http://www.ibm.com/developerworks/cn/opensource/os-cn-hadoop1/figure2.jpg"> </p>
<p><strong><span>任务粒度</span></strong><strong></strong></p>
<p align=left><span>把原始大数据集切割成小数据集时，通常让小数据集小于或等于</span><span> HDFS </span><span>中一个</span><span> Block </span><span>的大小</span><span>(</span><span>缺省是</span><span> 64M)</span><span>，这样能够保证一个小数据集位于一台计算机上，便于本地计算。有</span><span> M </span><span>个小数据集待处理，就启动</span><span> M </span><span>个</span><span> Map </span><span>任务，注意这</span><span> M </span><span>个</span><span> Map </span><span>任务分布于</span><span> N </span><span>台计算机上并行运行，</span><span>Reduce </span><span>任务的数量</span><span> R </span><span>则可由用户指定。</span><span> </span></p>
<p align=left><strong><span>Partition</span></strong></p>
<p align=left><span>把</span><span>Map </span><span>任务输出的中间结果按</span><span> key </span><span>的范围划分成</span><span> R </span><span>份</span><span>( R </span><span>是预先定义的</span><span> Reduce </span><span>任务的个数</span><span>)</span><span>，划分时通常使用</span><span> hash </span><span>函数如</span><span>: hash(key) mod R</span><span>，这样可以保证某一段范围内的</span><span> key</span><span>，一定是由一个</span><span> Reduce </span><span>任务来处理，可以简化</span><span> Reduce </span><span>的过程。</span><span> </span></p>
<p align=left><strong><span>Combine</span></strong></p>
<p align=left><span>在</span><span>partition </span><span>之前，还可以对中间结果先做</span><span> combine</span><span>，即将中间结果中有相同</span><span> key</span><span>的</span><span> &lt;key, value&gt; </span><span>对合并成一对。</span><span>combine </span><span>的过程与</span><span> Reduce </span><span>的过程类似，很多情况下就可以直接使用</span><span> Reduce </span><span>函数，但</span><span> combine </span><span>是作为</span><span> Map </span><span>任务的一部分，在执行完</span><span> Map </span><span>函数后紧接着执行的。</span><span>Combine </span><span>能够减少中间结果中</span><span> &lt;key, value&gt; </span><span>对的数目，从而减少网络流量。</span><span> </span></p>
<p align=left><strong><span>Reduce </span></strong><strong><span>任务从</span></strong><strong><span> Map </span></strong><strong><span>任务结点取中间结果</span></strong><strong></strong></p>
<p align=left><span>Map</span><span>任务的中间结果在做完</span><span> Combine </span><span>和</span><span> Partition </span><span>之后，以文件形式存于本地磁盘。中间结果文件的位置会通知主控</span><span> JobTracker, JobTracker </span><span>再通知</span><span> Reduce </span><span>任务到哪一个</span><span> DataNode </span><span>上去取中间结果。注意所有的</span><span> Map </span><span>任务产生中间结果均按其</span><span> Key </span><span>用同一个</span><span> Hash </span><span>函数划分成了</span><span> R </span><span>份，</span><span>R </span><span>个</span><span> Reduce </span><span>任务各自负责一段</span><span> Key </span><span>区间。每个</span><span> Reduce </span><span>需要向许多个</span><span> Map </span><span>任务结点取得落在其负责的</span><span> Key </span><span>区间内的中间结果，然后执行</span><span> Reduce </span><span>函数，形成一个最终的结果文件。</span><span> </span></p>
<p align=left><strong><span>任务管道</span></strong><strong></strong></p>
<p align=left><span>有</span><span> R </span><span>个</span><span> Reduce </span><span>任务，就会有</span><span> R </span><span>个最终结果，很多情况下这</span><span> R </span><span>个最终结果并不需要合并成一个最终结果。因为这</span><span> R </span><span>个最终结果又可以做为另一个计算任务的输入，开始另一个并行计算任务。</span><span> </span></p>
<p align=left><a name=N10158><strong><span>五</span></strong></a><strong><span> Hadoop </span></strong><strong><span>初体验</span></strong> </p>
<p align=left><span>Hadoop </span><span>支持</span><span> Linux </span><span>及</span><span> Windows </span><span>操作系统</span><span>, </span><span>但其官方网站声明</span><span> Hadoop </span><span>的分布式操作在</span><span> Windows </span><span>上未做严格测试，建议只把</span><span> Windows </span><span>作为</span><span> Hadoop </span><span>的开发平台。在</span><span> Windows </span><span>环境上的安装步骤如下</span><span>( Linux </span><span>平台类似，且更简单一些</span><span>): </span></p>
<p align=left><span>(1)</span><span>在</span><span> Windows </span><span>下，需要先安装</span><span> Cgywin, </span><span>安装</span><span> Cgywin </span><span>时注意一定要选择安装</span><span> openssh (</span><span>在</span><span> Net category )</span><span>。安装完成之后，把</span><span> Cgywin </span><span>的安装目录如</span><span> c:"cygwin"bin </span><span>加到系统环境变量</span><span> PATH </span><span>中，这是因为运行</span><span> Hadoop </span><span>要执行一些</span><span> linux </span><span>环境下的脚本和命令。</span> </p>
<p align=left><span>(2)</span><span>安装</span><span> Java 1.5.x</span><span>，并将</span><span> JAVA_HOME </span><span>环境变量设置为</span><span> Java </span><span>的安装根目录如</span><span> C:"Program Files"Java"jdk1.5.0_01</span><span>。</span> </p>
<p align=left><span>(3)</span><span>到</span><span> Hadoop </span><span>官方网站</span><span> <a href="http://hadoop.apache.org/">http://hadoop.apache.org/</a></span><span>下载</span><span>Hadoop Core, </span><span>最新的稳定版本是</span><span> 0.16.0. </span><span>将下载后的安装包解压到一个目录，本文假定解压到</span><span> c:"hadoop-0.16.0</span><span>。</span> </p>
<p align=left><span>4)</span><span>修改</span><span> conf/hadoop-env.sh </span><span>文件，在其中设置</span><span> JAVA_HOME </span><span>环境变量：</span><span> export JAVA_HOME="C:"Program Files"Java"jdk1.5.0_01&#8221; (</span><span>因为路径中</span><span> Program Files </span><span>中间有空格，一定要用双引号将路径引起来</span><span>) </span></p>
<p align=left><span>至此，一切就绪，可以运行</span><span> Hadoop </span><span>了。以下的运行过程，需要启动</span><span> cygwin, </span><span>进入模拟</span><span> Linux </span><span>环境。在下载的</span><span> Hadoop Core </span><span>包中，带有几个示例程序并且已经打包成了</span><span> hadoop-0.16.0-examples.jar</span><span>。其中有一个</span><span> WordCount </span><span>程序，功能是统计一批文本文件中各个单词出现的次数，我们先来看看怎么运行这个程序。</span><span>Hadoop </span><span>共有三种运行模式</span><span>: </span><span>单机</span><span>(</span><span>非分布式</span><span>)</span><span>模式，伪分布式运行模式，分布式运行模式，其中前两种运行模式体现不了</span><span> Hadoop </span><span>分布式计算的优势，并没有什么实际意义，但对程序的测试及调试很有帮助，我们先从这两种模式入手，了解基于</span><span> Hadoop </span><span>的分布式并行程序是如何编写和运行的。</span><span> </span></p>
<p align=left><strong><span>单机</span></strong><strong><span>(</span></strong><strong><span>非分布式</span></strong><strong><span>)</span></strong><strong><span>模式</span></strong><strong></strong></p>
<p align=left><span>这种模式在一台单机上运行，没有分布式文件系统，而是直接读写本地操作系统的文件系统。</span> <br><strong>代码清单1</strong></p>
<div><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span>$</span>&nbsp;<span>cd</span>&nbsp;<span>/</span><span>cygdrive</span><span>/</span><span>c</span><span>/</span><span>hadoop-</span><span>0.16</span><span>.</span><span>0</span><span><br></span><span>$</span>&nbsp;<span>mkdir</span><span>&nbsp;test-in&nbsp;&nbsp;<br></span><span>$</span>&nbsp;<span>cd</span><span>&nbsp;test-in<br></span><span>#</span><span>在&nbsp;test-in&nbsp;目录下创建两个文本文件</span><span>,</span><span>&nbsp;WordCount&nbsp;程序将统计其中各个单词出现次数<br></span><span>$</span>&nbsp;<span>echo</span>&nbsp;<span>"</span><span>hello&nbsp;world&nbsp;bye&nbsp;world</span><span>"</span>&nbsp;<span>&gt;</span><span>file1</span><span>.</span><span>txt&nbsp;&nbsp;&nbsp;<br></span><span>$</span>&nbsp;<span>echo</span>&nbsp;<span>"</span><span>hello&nbsp;hadoop&nbsp;goodbye&nbsp;hadoop</span><span>"</span>&nbsp;<span>&gt;</span><span>file2</span><span>.</span><span>txt<br></span><span>$</span>&nbsp;<span>cd</span>&nbsp;<span>..</span><span><br></span><span>$</span><span>&nbsp;bin</span><span>/</span><span>hadoop&nbsp;jar&nbsp;hadoop-</span><span>0.16</span><span>.</span><span>0</span><span>-examples</span><span>.</span><span>jar&nbsp;wordcount&nbsp;test-in&nbsp;test-out<br></span><span>#</span><span>执行完毕，下面查看执行结果：<br></span><span>$</span>&nbsp;<span>cd</span><span>&nbsp;test-out<br></span><span>$</span><span>&nbsp;cat&nbsp;part-</span><span>00000</span><span><br>bye&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>1</span><span><br>goodbye&nbsp;&nbsp;</span><span>1</span><span><br>hadoop&nbsp;&nbsp;</span><span>2</span><span><br>hello&nbsp;&nbsp;&nbsp;&nbsp;</span><span>2</span><span><br>world&nbsp;&nbsp;&nbsp;</span><span>2</span><span><br></span></div>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注意事项：运行</span><span> bin/hadoop jar hadoop-0.16.0-examples.jar wordcount test-in test-out </span><span>时，务必注意第一个参数是</span><span> jar, </span><span>不是</span><span> -jar, </span><span>当你用</span><span> -jar </span><span>时，不会告诉你是参数错了，报告出来的错误信息是：</span><span>Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/util/ProgramDriver, </span><span>笔者当时以为是</span><span> classpath </span><span>的设置问题，浪费了不少时间。通过分析</span><span> bin/hadoop </span><span>脚本可知，</span><span>-jar </span><span>并不是</span><span> bin/hadoop </span><span>脚本定义的参数，此脚本会把</span><span> -jar </span><span>作为</span><span> Java </span><span>的参数，</span><span>Java </span><span>的</span><span>-jar </span><span>参数表示执行一个</span><span> Jar </span><span>文件</span><span>(</span><span>这个</span><span> Jar </span><span>文件必须是一个可执行的</span><span> Jar,</span><span>即在</span><span> MANIFEST </span><span>中定义了主类</span><span>), </span><span>此时外部定义的</span><span> classpath </span><span>是不起作用的，因而会抛出</span><span> java.lang.NoClassDefFoundError </span><span>异常。而</span><span> jar </span><span>是</span><span> bin/hadoop </span><span>脚本定义的参数，会调用</span><span> Hadoop </span><span>自己的一个工具类</span><span> RunJar</span><span>，这个工具类也能够执行一个</span><span> Jar </span><span>文件，并且外部定义的</span><span> classpath </span><span>有效。</span><span> </span></p>
<p align=left><strong><span>伪分布式运行模式</span></strong><strong></strong></p>
<p align=left><span>这种模式也是在一台单机上运行，但用不同的</span><span> Java </span><span>进程模仿分布式运行中的各类结点</span><span> ( NameNode, DataNode, JobTracker, TaskTracker, Secondary NameNode )</span><span>，请注意分布式运行中的这几个结点的区别：</span><span> </span></p>
<p align=left><span>从分布式存储的角度来说，集群中的结点由一个</span><span> NameNode </span><span>和若干个</span><span> DataNode </span><span>组成</span><span>, </span><span>另有一个</span><span> Secondary NameNode </span><span>作为</span><span> NameNode </span><span>的备份。</span> <span>从分布式应用的角度来说，集群中的结点由一个</span><span> JobTracker </span><span>和若干个</span><span> TaskTracker </span><span>组成，</span><span>JobTracker </span><span>负责任务的调度，</span><span>TaskTracker </span><span>负责并行执行任务。</span><span>TaskTracker </span><span>必须运行在</span><span> DataNode </span><span>上，这样便于数据的本地计算。</span><span>JobTracker </span><span>和</span><span> NameNode </span><span>则无须在同一台机器上。</span><span> </span></p>
<p align=left><span>(1) </span><span>按代码清单</span><span>2</span><span>修改</span><span> conf/hadoop-site.xml</span><span>。注意</span><span> conf/hadoop-default.xml </span><span>中是</span><span> Hadoop </span><span>缺省的参数，你可以通过读此文件了解</span><span> Hadoop </span><span>中有哪些参数可供配置，但不要修改此文件。可通过修改</span><span> conf/hadoop-site.xml </span><span>改变缺省参数值，此文件中设置的参数值会覆盖</span><span> conf/hadoop-default.xml </span><span>的同名参数。</span><span> <br></span><strong><span>代码清单</span></strong><strong><span> 2</span></strong></p>
<div><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span>&lt;</span><span>configuration</span><span>&gt;</span><span><br>&nbsp;&nbsp;</span><span>&lt;</span><span>property</span><span>&gt;</span><span><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>&lt;</span><span>name</span><span>&gt;</span><span>fs.default.name</span><span>&lt;/</span><span>name</span><span>&gt;</span><span><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>&lt;</span><span>value</span><span>&gt;</span><span>localhost:9000</span><span>&lt;/</span><span>value</span><span>&gt;</span><span><br>&nbsp;&nbsp;</span><span>&lt;/</span><span>property</span><span>&gt;</span><span><br>&nbsp;&nbsp;</span><span>&lt;</span><span>property</span><span>&gt;</span><span><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>&lt;</span><span>name</span><span>&gt;</span><span>mapred.job.tracker</span><span>&lt;/</span><span>name</span><span>&gt;</span><span><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>&lt;</span><span>value</span><span>&gt;</span><span>localhost:9001</span><span>&lt;/</span><span>value</span><span>&gt;</span><span><br>&nbsp;&nbsp;</span><span>&lt;/</span><span>property</span><span>&gt;</span><span><br>&nbsp;&nbsp;</span><span>&lt;</span><span>property</span><span>&gt;</span><span><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>&lt;</span><span>name</span><span>&gt;</span><span>dfs.replication</span><span>&lt;/</span><span>name</span><span>&gt;</span><span><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>&lt;</span><span>value</span><span>&gt;</span><span>1</span><span>&lt;/</span><span>value</span><span>&gt;</span><span><br>&nbsp;&nbsp;</span><span>&lt;/</span><span>property</span><span>&gt;</span><span><br></span><span>&lt;/</span><span>configuration</span><span>&gt;</span><span><br></span></div>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;参数</span><span> fs.default.name </span><span>指定</span><span> NameNode </span><span>的</span><span> IP </span><span>地址和端口号。缺省值是</span><span> file:///, </span><span>表示使用本地文件系统</span><span>, </span><span>用于单机非分布式模式。此处我们指定使用运行于本机</span><span> localhost </span><span>上的</span><span> NameNode</span><span>。</span><span> </span></p>
<p align=left><span>参数</span><span> mapred.job.tracker </span><span>指定</span><span> JobTracker </span><span>的</span><span> IP </span><span>地址和端口号。缺省值是</span><span> local, </span><span>表示在本地同一</span><span> Java </span><span>进程内执行</span><span> JobTracker </span><span>和</span><span> TaskTracker, </span><span>用于单机非分布式模式。此处我们指定使用运行于本机</span><span> localhost </span><span>上的</span><span> JobTracker ( </span><span>用一个单独的</span><span> Java </span><span>进程做</span><span> JobTracker )</span><span>。</span><span> </span></p>
<p align=left><span>参数</span><span> dfs.replication </span><span>指定</span><span> HDFS </span><span>中每个</span><span> Block </span><span>被复制的次数，起数据冗余备份的作用。</span><span> </span><span>在典型的生产系统中，这个数常常设置为</span><span>3</span><span>。</span><span> </span></p>
<p align=left><span>(2)</span><span>配置</span><span> SSH,</span><span>如代码清单</span><span>3</span><span>所示</span><span>: <br></span><strong><span>代码清单</span></strong><strong><span> 3</span></strong></p>
<div><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span>$</span><span>&nbsp;ssh-keygen&nbsp;-t&nbsp;dsa&nbsp;-P&nbsp;''&nbsp;-f&nbsp;~</span><span>/.</span><span>ssh</span><span>/</span><span>id_dsa&nbsp;<br></span><span>$</span><span>&nbsp;cat&nbsp;~</span><span>/.</span><span>ssh</span><span>/</span><span>id_dsa</span><span>.</span><span>pub&nbsp;</span><span>&gt;&gt;</span><span>&nbsp;~</span><span>/.</span><span>ssh</span><span>/</span><span>authorized_keys<br></span></div>
<span>配置完后，执行一下</span><span> ssh localhost, </span><span>确认你的机器可以用</span><span> SSH </span><span>连接，并且连接时不需要手工输入密码。</span>
<p align=left><span>(3)</span><span>格式化一个新的分布式文件系统</span><span>, </span><span>如代码清单</span><span>4</span><span>所示</span><span>:</span></p>
<div><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span>$</span>&nbsp;<span>cd</span>&nbsp;<span>/</span><span>cygdrive</span><span>/</span><span>c</span><span>/</span><span>hadoop-</span><span>0.16</span><span>.</span><span>0</span><span><br></span><span>$</span><span>&nbsp;bin</span><span>/</span><span>hadoop&nbsp;namenode&nbsp;&#8211;</span><span>format</span><span>&nbsp;<br></span></div>
<p><span>(4) </span><span>启动</span><span> hadoop </span><span>进程</span><span>, </span><span>如代码清单</span><span>5</span><span>所示。控制台上的输出信息应该显示启动了</span><span> namenode, datanode, secondary namenode, jobtracker, tasktracker</span><span>。启动完成之后，通过</span><span> ps &#8211;ef </span><span>应该可以看到启动了</span><span>5</span><span>个新的</span><span> java </span><span>进程。</span><br><strong>代码清单 5</strong></p>
<div><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span>$</span><span>&nbsp;bin</span><span>/</span><span>start</span><span>-all</span><span>.</span><span>sh&nbsp;&nbsp;<br></span><span>$</span><span>&nbsp;ps&nbsp;&#8211;ef<br></span></div>
<span>(5) </span><span>运行</span><span> wordcount </span><span>应用</span><span>, </span><span>如代码清单</span><span>6</span><span>所示</span><span>:</span>
<div><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span>$</span><span>&nbsp;bin</span><span>/</span><span>hadoop&nbsp;dfs&nbsp;-put&nbsp;</span><span>./</span><span>test-in&nbsp;input&nbsp;&nbsp;<br></span><span>#</span><span>将本地文件系统上的&nbsp;</span><span>./</span><span>test-in&nbsp;目录拷到&nbsp;HDFS&nbsp;的根目录上，目录名改为&nbsp;input<br></span><span>#</span><span>执行&nbsp;bin</span><span>/</span><span>hadoop&nbsp;dfs&nbsp;&#8211;help&nbsp;可以学习各种&nbsp;HDFS&nbsp;命令的使用。<br></span><span>$</span><span>&nbsp;bin</span><span>/</span><span>hadoop&nbsp;jar&nbsp;hadoop-</span><span>0.16</span><span>.</span><span>0</span><span>-examples</span><span>.</span><span>jar&nbsp;wordcount&nbsp;input&nbsp;output<br></span><span>#</span><span>查看执行结果:<br></span><span>#</span><span>将文件从&nbsp;HDFS&nbsp;拷到本地文件系统中再查看：<br></span><span>$</span><span>&nbsp;bin</span><span>/</span><span>hadoop&nbsp;dfs&nbsp;-get&nbsp;output&nbsp;output&nbsp;<br></span><span>$</span><span>&nbsp;cat&nbsp;output</span><span>/</span><span>*<br></span><span>#</span><span>也可以直接查看<br></span><span>$</span><span>&nbsp;bin</span><span>/</span><span>hadoop&nbsp;dfs&nbsp;-cat&nbsp;output</span><span>/</span><span>*<br></span><span>$</span><span>&nbsp;bin</span><span>/</span><span>stop-all</span><span>.</span><span>sh&nbsp;</span><span>#</span><span>停止&nbsp;hadoop&nbsp;进程<br></span></div>
<p><strong><span>故障诊断</span></strong><strong></strong></p>
<p align=left><span>(1) </span><span>执行</span><span> $ bin/start-all.sh </span><span>启动</span><span> Hadoop </span><span>进程后，会启动</span><span>5</span><span>个</span><span> java </span><span>进程</span><span>, </span><span>同时会在</span><span> /tmp </span><span>目录下创建五个</span><span> pid </span><span>文件记录这些进程</span><span> ID </span><span>号。通过这五个文件，可以得知</span><span> namenode, datanode, secondary namenode, jobtracker, tasktracker </span><span>分别对应于哪一个</span><span> Java </span><span>进程。当你觉得</span><span> Hadoop </span><span>工作不正常时，可以首先查看这</span><span>5</span><span>个</span><span> java </span><span>进程是否在正常运行。</span> </p>
<p align=left><span>(2) </span><span>使用</span><span> web </span><span>接口。访问</span><span> http://localhost:50030 </span><span>可以查看</span><span> JobTracker </span><span>的运行状态。访问</span><span> http://localhost:50060 </span><span>可以查看</span><span> TaskTracker </span><span>的运行状态。访问</span><span> http://localhost:50070 </span><span>可以查看</span><span> NameNode </span><span>以及整个分布式文件系统的状态，浏览分布式文件系统中的文件以及</span><span> log </span><span>等。</span> </p>
<p align=left><span>(3) </span><span>查看</span><span> ${HADOOP_HOME}/logs </span><span>目录下的</span><span> log </span><span>文件，</span><span>namenode, datanode, secondary namenode, jobtracker, tasktracker </span><span>各有一个对应的</span><span> log </span><span>文件，每一次运行的计算任务也有对应用</span><span> log </span><span>文件。分析这些</span><span> log </span><span>文件有助于找到故障原因。</span> </p>
<p align=left><a name=N101F6><strong><span>结束语</span></strong></a> </p>
<p align=left><span>现在，你已经了解了</span><span> MapReduce </span><span>计算模型，分布式文件系统</span><span> HDFS</span><span>，分布式并行计算等的基本原理</span><span>, </span><span>并且有了一个可以运行的</span><span> Hadoop </span><span>环境，运行了一个基于</span><span> Hadoop </span><span>的并行程序。在下一篇文章中，你将了解到如何针对一个具体的计算任务，基于</span><span> Hadoop </span><span>编写自己的分布式并行程序并将其部署运行等内容。</span><span> </span></p>
<p align=left><a name=resources><span>参考资料</span></a> </p>
<p align=left><strong><span>学习</span></strong></p>
<ul type=disc>
    <li><span>访问</span><span> <a href="http://hadoop.apache.org/">Hadoop <span>官方网站</span></a>,</span><span>了解</span><span> Hadoop </span><span>及其子项目</span><span> HBase </span><span>的信息。</span>
    <li><span><a href="http://wiki.apache.org/hadoop/">Hadoop wiki</a> </span><span>上</span><span>, </span><span>有许多</span><span> Hadoop </span><span>的用户文档</span><span>,</span><span>开发文档</span><span>,</span><span>示例程序等。</span>
    <li><span>阅读</span><span> Google Mapreduce </span><span>论文：</span><span> <a href="http://research.google.com/archive/mapreduce-osdi04.pdf">MapReduce: Simplified Data Processing on Large Clusters</a>, </span><span>深入了解</span><span> Mapreduce </span><span>计算模型。</span>
    <li><span>学习</span><span> Hadoop </span><span>分布式文件系统</span><span> HDFS</span><span>：</span><span> <a href="http://hadoop.apache.org/core/docs/r0.16.0/hdfs_design.html">The Hadoop Distributed File System:Architecture and Design</a> </span>
    <li><span>学习</span><span> Google </span><span>文件系统</span><span> GFS: <a href="http://labs.google.com/papers/gfs.html">The Google File System</a>, Hadoop HDFS </span><span>实现了与</span><span> GFS </span><span>类似的功能。</span> </li>
</ul>
<div id=MySignature>&nbsp;</div>
<img src ="http://www.cppblog.com/jack-wang/aggbug/106616.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jack-wang/" target="_blank">小王</a> 2010-01-28 13:50 <a href="http://www.cppblog.com/jack-wang/archive/2010/01/28/106616.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>