<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Recent changes to MapReduce</title><link>https://sourceforge.net/p/arcomem/wiki/MapReduce/</link><description>Recent changes to MapReduce</description><atom:link href="https://sourceforge.net/p/arcomem/wiki/MapReduce/feed" rel="self"/><language>en</language><lastBuildDate>Wed, 19 Feb 2014 00:31:09 -0000</lastBuildDate><atom:link href="https://sourceforge.net/p/arcomem/wiki/MapReduce/feed" rel="self" type="application/rss+xml"/><item><title>MapReduce modified by John Arcoman</title><link>https://sourceforge.net/p/arcomem/wiki/MapReduce/</link><description>&lt;div class="markdown_content"&gt;&lt;h1 id="processing-using-mapreduce"&gt;Processing Using MapReduce&lt;/h1&gt;
&lt;p&gt;MapReduce is a software framework for distributed computation. MapReduce was introduced by Google in 2004 to support distributed processing of massive datasets on commodity server clusters. In a MapReduce system, the data being processed is distributed across the disks of the cluster nodes and the processing task is pushed to the nodes where the data is stored. This is in contrast to more traditional distributed frameworks where the data is pushed to the computation nodes.&lt;/p&gt;
&lt;p&gt;Logically, the MapReduce computational model consists of two steps, Map and Reduce, which are both defined in terms of &lt;code&gt;&amp;lt;key, value&amp;gt;&lt;/code&gt; pairs. The dataset being processed is also considered to consist of &lt;code&gt;&amp;lt;key, value&amp;gt;&lt;/code&gt; pairs. For example, the keys could be filenames and the values could be the actual contents of the files; or the keys could be the line number of a text file and the value could be the text on the respective line. In some cases, the key or value isn\'t important and could be &lt;code&gt;Null&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The Map function takes a &lt;code&gt;&amp;lt;key, value&amp;gt;&lt;/code&gt; pair as input and emits a list of &lt;code&gt;&amp;lt;key, value&amp;gt;&lt;/code&gt; pairs:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key_in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value_in&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;key_out&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;value_out&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;key_out&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;value_out&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Keys emitted by the Map function do not have to be unique; the same key may be emitted multiple times with the same or different values. The Map function is applied to every item in the input dataset. The Map function only considers the current item being processed and is independent of the other items. This means that it is potentially possible to apply the Map function to all the data items in parallel. The output from all the parallel Maps is sorted and grouped (combined) by key, creating a &lt;code&gt;&amp;lt;key(i), [value(1), ..., value(n)]&amp;gt;&lt;/code&gt; pair for each unique key.&lt;/p&gt;
&lt;p&gt;Each grouped &lt;code&gt;&amp;lt;key(i), [value(1), ..., value(n)]&amp;gt;&lt;/code&gt; is then processed by a Reduce function. In the original MapReduce paper, the Reduce function returned a list of values:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;Reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;...,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;value_out&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;...,&lt;/span&gt; &lt;span class="n"&gt;value_out&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Modern interpretations of MapReduce, such as the Hadoop framework used in ARCOMEM, are more flexible and allow the reduce function to emit multiple &lt;code&gt;&amp;lt;key, value&amp;gt;&lt;/code&gt; pairs (allowing for the same key to be emitted multiple times):&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;Reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;...,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;key_out&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;value_out&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;key_out&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;value_out&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For both cases, the number of reduce functions that can be performed in parallel is limited by the number of unique keys output by the map functions. Modern frameworks, such as Hadoop, also allow the possibility to specify an extra task called a &lt;code&gt;Combine&lt;/code&gt; that occurs after the &lt;code&gt;Map&lt;/code&gt; function but before the keys are sorted, merged and passed to &lt;code&gt;Reduce&lt;/code&gt;. Functionally, &lt;code&gt;Combine&lt;/code&gt; has the same semantics as &lt;code&gt;Reduce&lt;/code&gt; but it is run directly on data emitted from a number of &lt;code&gt;Map&lt;/code&gt; calls before it is written to disk. A common principle use of &lt;code&gt;Combine&lt;/code&gt; is to reduce the amount of data that needs to be passed to &lt;code&gt;Reduce&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The MapReduce computational model is coupled with a distributed filesystem and worker processes spread across cluster nodes in order to complete the framework. This arrangement has a number of desirable features:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Fault tolerance:&lt;/strong&gt; File system blocks are replicated across nodes in the cluster. If the disk of a node fails then the data is still intact. If a Map or Reduce function suffers a failure it can be re-run on a different machine without having to restart the entire job. The framework is completely resilient to nodes becoming unavailable and re-available, for example due to maintenance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data locality:&lt;/strong&gt; The framework tracks where each block of data is stored and uses this information to intelligently minimise network traffic by performing tasks on nodes where the input data is stored. Modern implementations can be `rack aware\' and will attempt to minimise the traffic between nodes in different racks in preference to minimising between nodes in the same rack.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Job scheduling:&lt;/strong&gt; Jobs are submitted through a master node which tracks which workers are available and which are busy. The scheduler ensures that the cluster is utilised efficiently by balancing data locality and node utilisation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scalability:&lt;/strong&gt; The framework is massively scalable; processing can potentially be performed on as many machines as there are data records. The practical limitation is the cost of building and running the cluster. The framework allows new nodes to be added to the cluster.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="mapreduce-in-arcomem"&gt;MapReduce in ARCOMEM&lt;/h2&gt;
&lt;p&gt;In the ARCOMEM offline processing phase, modules (with the exception of &lt;em&gt;local&lt;/em&gt; modules) are all implemented as MapReduce jobs. Most of the modules involve applying some processing to documents crawled by the web-crawler, and are implemented as &lt;em&gt;standard modules&lt;/em&gt;. &lt;em&gt;Standard modules&lt;/em&gt; are run directly over the HBase table populated by the crawler. In a &lt;em&gt;standard module&lt;/em&gt;, the input key of each &lt;code&gt;Map&lt;/code&gt; function is the URL of a document, and the input value is a &lt;a class="" href="../apidocs/eu/arcomem/framework/offline/ResultResourceWrapper"&gt;ResultResourceWrapper&lt;/a&gt; that represents the data and metadata of the web object belonging to the URL.&lt;/p&gt;
&lt;p&gt;Some of the modules, such as the image processing module, only need to process one individual document at a time. Such a process is described as being &lt;em&gt;Map-heavy&lt;/em&gt; because it doesn\'t use a reducer at all (in terms of implementation they actually use a &lt;a class="" href="../apidocs/eu/arcomem/framework/offline/util/NullReducer"&gt;NullReducer&lt;/a&gt;). Most &lt;em&gt;Map-heavy&lt;/em&gt; ARCOMEM modules won\'t even emit anything to the MapReduce framework from within the &lt;code&gt;Map&lt;/code&gt; function but will instead rely on writing directly to the knowledge base.&lt;/p&gt;
&lt;p&gt;Other modules, such as the GATE NLP module, need to run on collections on documents. These modules are termed &lt;em&gt;Reduce-heavy&lt;/em&gt; as they perform most of the analysis in the &lt;code&gt;Reduce&lt;/code&gt; function. &lt;em&gt;Reduce-heavy&lt;/em&gt; modules typically use a very lightweight &lt;code&gt;Map&lt;/code&gt; function implementation to group-together collections of documents by emitting multiple documents with the same key.&lt;/p&gt;
&lt;p&gt;Finally, there are also &lt;em&gt;balanced&lt;/em&gt; modules which take advantage of both the &lt;code&gt;Map&lt;/code&gt; and &lt;code&gt;Reduce&lt;/code&gt; functions to perform their computation. An example of this is the module which is responsible for computing the distribution of mime-types across all the documents in a crawl. The mime-type module also demonstrates the use of a &lt;code&gt;Combine&lt;/code&gt; function for efficiency. More details are described in the &lt;a class="" href="../OfflineModuleImpl"&gt;module implementation page&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">John Arcoman</dc:creator><pubDate>Wed, 19 Feb 2014 00:31:09 -0000</pubDate><guid>https://sourceforge.net384f8e702b5794f93ca10d547f5e642cba18e659</guid></item></channel></rss>