我正在开发一个MapReduce程序,在该程序中我需要将实体插入数据库。由于一些性能问题,将实体插入数据库应该在组合器中完成。我的程序没有减速器,所以只有映射器和组合器。由于Hadoop引擎可能不执行合并器(合并器是可选的),我如何强制它运行合并器?
MapReduce框架没有提供支持的强制执行组合器的方法。组合器可以被称为0、1或多次。该框架可以自由地对此做出自己的决定。
当前实现决定基于映射任务执行期间发生的磁盘溢出来运行组合器。mapred-default.xml的Apache Hadoop文档记录了几个可能对溢出活动产生影响的配置属性。
<property>
<name>mapreduce.map.sort.spill.percent</name>
<value>0.80</value>
<description>The soft limit in the serialization buffer. Once reached, a
thread will begin to spill the contents to disk in the background. Note that
collection will not block if this threshold is exceeded while a spill is
already in progress, so spills may be larger than this threshold when it is
set to less than .5</description>
</property>
<property>
<name>mapreduce.task.io.sort.factor</name>
<value>10</value>
<description>The number of streams to merge at once while sorting
files. This determines the number of open file handles.</description>
</property>
<property>
<name>mapreduce.task.io.sort.mb</name>
<value>100</value>
<description>The total amount of buffer memory to use while sorting
files, in megabytes. By default, gives each merge stream 1MB, which
should minimize seeks.</description>
</property>
此外,还有一个未记录的配置属性mapreduce.map.combine.minspills
,它定义了运行组合器之前所需的最小溢出次数。如果未指定,则默认值为3
。
可以对这些配置属性进行适当的调整,以设置触发足够溢出超过mapreduce.map.combine.minspills
的条件,从而保证至少对组合器进行一次调用。然而,我不建议这样做,因为它会很脆。逻辑对外部因素非常敏感,比如输入数据的大小。此外,它还将依赖于当前MapReduce代码库的具体实现细节。内部算法可能会发生变化,这些变化可能会打破你的假设。实际上没有公共的API来强制运行合并器。
此外,请记住,与reducer不同,组合器可能无法获得与特定键相关联的所有值的完整图像。如果多个映射任务处理具有相同键的记录,那么reducer是唯一可以保证看到所有这些值分组在一起的地方。即使在单个映射任务中,组合器也可以使用从其处理的输入拆分中提取的键值的不同子集执行多次。
对于将数据从Hadoop导出到关系数据库的问题,要获得更标准的解决方案,请考虑DBOutputFormat或Sqoop。