hadoop map-reduce中的文件并发操作_数据库其它

这样的操作在map端或者reduce端均可。下面以一个实际业务场景中的例子来简要说明。

问题简要描述:

假如reduce输入的key是Text(String),value是BytesWritable(byte[]),不同key的种类为100万个,value的大小平均为30k左右,每个key大概对应 100个value,要求对每一个key建立两个文件,一个用来不断添加value中的二进制数据,一个用来记录各个value在文件中的位置索引。(大量的小文件会影响HDFS的性能,所以最好对这些小文件进行拼接)

当文件数量较小时,可以考虑使用MultipleOutput来进行key-value的分流,可以按照key的不同,将其输出到不同的文件或者目录中。但是reduce的数量只能为1,不然每个reduce都会生成相同的目录或者文件,不能达到最终的目的。此外最重要的是,操作系统对每个进程打开的文件数量的限制,默认为1024,集群的各个datanode可能会配置更高的值,但最多在几万左右,仍然是一个限制因素。不能满足百万文件的需求。

reduce的主要目的是用来归并key-value并输出到HDFS上,我们当然也可以在reduce中进行其他的操作,比如文件读写。因为默认的partitioner保证同一个key的数据肯定会在同一个reduce中,所以在每个reduce中只用打开两个文件进行读写即可(一个索引文件,一个数据文件)。并发度由reduce数量决定,将reduce数量设为256,那我们就可以同时处理256个key的数据(partioner保证了不同reduce处理的key不同,不会引起文件读写冲突)。这样的并发度的效率是很客观的,可以在较短的时间内完成需求。

思路是这样,但同时由于hdfs的特性以及hadoop的任务调度,在文件读写过程中,仍有可能会出现很多问题,下面简要说些一些常见的会碰到的问题。

1.org.apache.hadoop.hdfs.protocol.AlreadyBeingCreatedException异常

这可能是最经常碰到的一个问题。可能的原因如下:

(1)文件流冲突。

一般创建文件时都会打开一个供写入的文件流。而我们希望是追加,所以如果使用了错误的API ,就有可能引起上述问题。以FileSystem类为例,如果使用create()方法之后再调用append()方法,就会抛出上述异常。所以最好使用createNewFile方法,只创建文件,不打开流。

(2)mapreduce推测执行机制

mapreduce 为了提高效率,会在一个任务启动之后,同时启动一些相同的任务(attempt),其中有一个attempt成功完成之后,视为整个task完成,其结果 作为最终结果,并且杀掉那些较慢的attempt。集群一般会开启此选项以优化性能(以空间换时间)。但在本问题环境下推测执行却不太合适。因为我们一般希望一个task 用来处理一个文件,但如果启动推测执行,会有几个attempt同时试图操作同一个文件,就会引发异常。所以最好关掉此选项,将 mapred.reduce.max.attempts 设为1,或者将mapred.reduce.tasks.speculative.execution设为false.

但此时仍有可能会出现问题。因为如果一个task的唯一attempt出现问题,在被kill掉之后,task仍会另起一个attempt,此时因为前一个attempt异常终止,仍有可能会影响到新起的attempt的文件操作,引发异常。所以最安全的方法是,借鉴推测执行的机制(每个attempt各自生成自己的结果,最终选择一个作为最终结果),以每个attempt的id号为后缀附加到所操作的文件上,同时捕获所有文件操作的异常并处理,这样可避免文件的读写冲突。Context可以用来获取运行时的一些上下文信息,可以很容易得到attempt的id号。注意,此时如果开启推测执行也可以,但是会生成很多相同的文件(每个attempt一份),仍然不是最好的解决方法。

同时,我们可以利用reduce的输出来记录运行“不正常的” key.这些task大多数是attempt_0被杀掉而重启了一个attempt_1,所以下面的文件一般为两份。可以对这些情况的key输出(文件异常或者attemptID > 0),并进行一些后续处理,比如文件重命名,或者紧对这些key重新写入。因为此种情况的key一般只占极少数,所以并不影响总体的效率。

2.文件异常处理

最好能将mapreduce中的所有文件操作都设置好异常处理。不然一个文件异常就有可能会使整个job失败。所以从效率来讲,最好是在文件发生异常时将其key作为reduce的输出以进行记录。因为同时mapreduce会重启一个task attempts重新进行文件读写,可保证我们得到最终的数据,最后所需的只是对那些异常的key进行一些简单的文件重命名操作即可。

3.多目录以及文件拼接

如果我们将key的种类设为1000万,上述方法会生成太多的小文件从而影响hdfs的性能,另外,因为所有文件都在同一个目录下,会导致同一个目录下文件数目过多而影响访问效率。

在创建文件的同时建立多个子目录,一个有用的方法是以reduce的taskid来建立子目录。这样有多少个reduce就可以建立多少个子目录,不会有文件冲突。同一个reduce处理的key都会在同一个目录下。

文件拼接要考虑的一个索引的问题。为了将文件索引建立的尽量简单,应该尽量保证同一个key的所有数据都在同一个大文件中。这可以利用key的hashCode来实现。如果我们想在每个目录下建立1000个文件,只需将hashCode对1000取余即可。

时间: 2024-10-31 07:11:16

hadoop map-reduce中的文件并发操作_数据库其它的相关文章

Hadoop Map/Reduce教程

目的 这篇教程从用户的角度出发,全面地介绍了Hadoop Map/Reduce框架的各个方面. 先决条件 请先确认Hadoop被正确安装.配置和正常运行中.更多信息见: Hadoop快速入门对初次使用者. Hadoop集群搭建对大规模分布式集群. 概述 Hadoop Map/Reduce是一个使用简易的软件框架,基于它写出来的应用程序能够运行在由上千个商用机器组成的大型集群上,并以一种可靠容错的方式并行处理上T级别的数据集. 一个Map/Reduce 作业(job) 通常会把输入的数据集切分为若

Java中对文件的操作

Java中对文件的操作 java中提供了io类库,可以轻松的用java实现对文件的各种操作.下面就来说一下如何用java来实现这些操作. 1.新建目录 <%@ page contentType="text/html;charset=gb2312"%> <% String filePath="c:/aaa/"; filePath=filePath.toString();//中文转换 java.io.File myFilePath=new java.i

Hadoop集群中hosts文件配置问题

最近一直在做hadoop的应用,但是无奈于并行加速比一直不理想,两台机器运行的时间和一台机器运行的时间差不多,老师还一直要这个数据,并行计算比至少应该为1.5,这样的并行程序才有意义. 加了个qq群,发现了问题所在,再说我解决方法之前,先说一下我hadoop集群的配置: 2台笔记本,其中1台为lenovo z460,CPU为Core i3,主机名为:liujiacai-Ideapad-Z460:另一台是Acer  Aspire 4743 CPU为奔腾P6200,主机名为:liujiacai-As

PHP中dat文件读写操作实例详解

以下是一篇关于文件基本读写操作的文章,我曾经就是看了这篇文章后学会文件基本操作的,在这里发出来与大家共享: 复制内容到剪贴板  代码如下 复制代码 $file_name = "data.dat"; // 要读取的文件的绝对路径: homedata.dat $file_pointer = fopen($file_name, "r"); // 打开文件,"r" 是一种模式,或者说我们要进行的操作方法,详见本文后面的介绍 $file_read = fr

VC++中使用ADO方式操作ACCESS数据库

ADO(ActiveX Data Object)是Microsoft数据库应用程序开发的新接口,是建立在OLE DB之上的高层数据库访问技术,即使你对OLE DB,COM不了解也能轻松对付ADO,因为它非常简单易用,甚至比你以往所接触的ODBC API.DAO.RDO都要容易使用,并不失灵活性.本文详细地介绍在Visual C++开发环境下如何使用ADO来进行数据库应用程序开发,并给出示例代码.为了使读者朋友都能测试本例提供的代码,我们采用Access数据库,您可以直接在我们提供的示例代码中找到

[Hadoop系列]Hadoop的MapReduce中多文件输出

inkfish原创,请勿商业性质转载,转载请注明来源(http://blog.csdn.net/inkfish ). Hadoop默认的输出是TextOutputFormat,输出文件名不可定制.hadoop 0.19.X中有一个org.apache.hadoop.mapred.lib.MultipleOutputFormat,可以输出多份文件且可以自定义文件名,但是从hadoop 0.20.x中MultipleOutputFormat所在包的所有类被标记为"已过时",当前如果再使用M

c#中对文件的操作小结

1.建立一个文本文件public class FileClass{    public static void Main()    {    WriteToFile();    }    static void WriteToFile()    {    StreamWriter SW;    SW=File.CreateText("c:\MyTextFile.txt");    SW.WriteLine("God is greatest of them all")

在.NET2.0中使用自定义事务操作_实用技巧

.net 2.0 framework 中新增了 System.Transactions 命名空间,其中提供的一系列接口和类使得在.net 2.0 中使用事务比起从前要方便了许多.有关在 .net 2.0 下操作数据库事务的文章已经有了很多,这里只提一下如何设计自定义事务操作. 一.事务使用基础 先看一段使用事务的代码: 1using (TransactionScope ts= new TransactionScope())2{3 //自定义操作4 ts.Complete();5} 这里使用 us

用asp实现的数据库中存取文件的代码_应用技巧

************************************************************************* '** '** 使用 ADODB.Stream 保存/读取文件到数据库 '** 引用 Microsoft ActiveX Data Objects 2.5 Library 及以上版本 '** '** ----- 数据库连接字符串模板 --------------------------------------- '** ACCESS数据库 '** i