说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

利用Hadoop Streaming处理二进制格式文件

HTML文档下载 WORD文档下载 PDF文档下载
Hadoop Streaming是Hadoop提供的多语言编程工具,用户可以使用自己擅长的编程语言(比如python、php或C#等)编写Mapper和Reducer处理文本数据。Hadoop Streaming自带了一些配置参数可友好地支持多字段文本数据的处理

编者按:Streaming是Hadoop的一个工具,用来创建和运行一类特殊的Map/Reduce作业。Streaming使用“标准输入”和“标准输出”与我们编写的Map和Reduce进行数据的交换。由此可知,任何能够使用“标准输入”和“标准输出”的编程语言都可以用来编写MapReduce程序。今天给大家分享一篇来自董西成的博文“利用Hadoop Streaming处理二进制格式文件”,文中介绍了如何使用Streaming处理二进制格式的文件。


CSDN推荐:欢迎免费订阅《Hadoop与大数据周刊》获取更多Hadoop技术文献、大数据技术分析、企业实战经验,生态圈发展趋势。


Hadoop Streaming是Hadoop提供的多语言编程工具,用户可以使用自己擅长的编程语言(比如python、php或C#等)编写Mapper和Reducer处理文本数据。Hadoop Streaming自带了一些配置参数可友好地支持多字段文本数据的处理,参与Hadoop Streaming介绍和编程,可参考我的这篇文章:“Hadoop Streaming编程实例”。然而,随着Hadoop应用越来越广泛,用户希望Hadoop Streaming不局限在处理文本数据上,而是具备更加强大的功能,包括能够处理二进制数据;能够支持多语言编写Combiner等组件。随着Hadoop 2.x的发布,这些功能已经基本上得到了完整的实现,本文将介绍如何使用Hadoop Streaming处理二进制格式的文件,包括SequenceFile,HFile等。

注:本文用到的程序实例可在百度云:hadoop-streaming-binary-examples 下载。

在详细介绍操作步骤之前,先介绍本文给出的实例。假设有这样的SequenceFile,它保存了手机通讯录信息,其中,key是好友名,value是描述该好友的一个结构体或者对象,为此,本文使用了google开源的protocol buffer这一序列化/反序列化框架,protocol buffer结构体定义如下:

option java_package = "";
option java_outer_classname="PersonInfo";
message Person {
  optional string name = 1;
  optional int32 age = 2;
  optional int64 phone = 3;
  optional string address = 4;
}

SequenceFile文件中的value便是保存的Person对象序列化后的字符串,这是典型的二进制数据,不能像文本数据那样可通过换行符解析出每条记录,因为二进制数据的每条记录中可能包含任意字符,包括换行符。

一旦有了这样的SequenceFile之后,我们将使用Hadoop Streaming编写这样的MapReduce程序:这个MapReduce程序只有Map Task,任务是解析出文件中的每条好友记录,并以name \t age,phone,address的文本格式保存到HDFS上。

1. 准备数据

首先,我们需要准备上面介绍的SequenceFile数据,生成数据的核心代码如下:

final SequenceFile.Writer out =
        SequenceFile.createWriter(fs, getConf(), new Path(args[0]),
                Text.class, BytesWritable.class);
Text nameWrapper = new Text();
BytesWritable personWrapper = new BytesWritable();
System.out.println("Generating " + num + " Records......");
for(int i = 0; i < num; i++) {
  genOnePerson(nameWrapper, personWrapper);
  System.out.println("Generating " + i + " Records," + nameWrapper.toString() + "......");
  out.append(nameWrapper, personWrapper);
}
out.close();

当然,为了验证我们产生的数据是否正确,需要编写一个解析程序,核心代码如下:

Reader reader = new Reader(fs, new Path(args[0]), getConf());
Text key = new Text();
BytesWritable value = new BytesWritable();
while(reader.next(key, value)) {
  System.out.println("key:" + key.toString());
  value.setCapacity(value.getSize()); // Very important!!! Very Tricky!!!
  PersonInfo.Person person = PersonInfo.Person.parseFrom(value.getBytes());
  System.out.println("age:" + person.getAge()
          + ",address:" + person.getAddress()
          +",phone:" + person.getPhone());
}
reader.close();

需要注意的,Value保存类型为BytesWritable,使用这个类型非常容易犯错误。当你把一堆byte[]数据保存到BytesWritable后,通过BytesWritable.getBytes()再读到的数据并不一定是原数据,可能变长了很多,这是因为BytesWritable采用了自动内存增长算法,你保存的数据长度为size时,它可能将数据保存到了长度为capacity(capacity>size)的buffer中,这时候,你通过BytesWritable.getBytes()得到的数据最后一些字符是多余的,如果里面保存的是protocol buffer序列化后的字符串,则无法反序列化,这时候可以使用BytesWritable.setCapacity (value.getSize())将后面多余空间剔除掉。

2. 使用Hadoop Streaming编写C++程序

为了说明Hadoop Streaming如何处理二进制格式数据,本文仅仅以C++语言为例进行说明,其他语言的设计方法类似。

先简单说一下原理。当输入数据是二进制格式时,Hadoop Streaming会对输入key和value进行编码后,通过标准输入传递给你的Hadoop Streaming程序,目前提供了两种编码格式,分别是rawtypes和  typedbytes,你可以设计你想采用的格式,这两种编码规则如下(具体在文章“Hadoop Streaming高级编程”中已经介绍了):

rawbytes:key和value均用【4个字节的长度+原始字节】表示

typedbytes:key和value均用【1字节类型+4字节长度+原始字节】表示

本文将采用第一种编码格式进行说明。采用这种编码意味着你不能想文本数据那样一次获得一行内容,而是依次获得key和value序列,其中key和value都由两部分组成,第一部分是长度(4个字节),第二部分是字节内容,比如你的key是dongxicheng,value是goodman,则传递给hadoop streaming程序的输入数据格式为11 dongxicheng 7 goodman。为此,我们编写下面的Mapper程序解析这种数据:

int main() {
 string key, value;
 while(!cin.eof()) {
  if(!FileUtil::ReadString(key, cin))
   break;
  FileUtil::ReadString(value, cin);
  Person person;
  ProtoUtil::ParseFromString(value, person);
  cout << person.name() << "\t" << person.age()
       << "," << person.address()
       << "," << person.phone() << endl;
 }
 return 0;
}

其中,辅助函数实现如下:

class ProtoUtil {
 public:
  static bool ParseFromString(const string& str, Person &person) {
   if(person.ParseFromString(str))
    return true;
   return false;
  }
};
class FileUtil {
 public:
  static bool ReadInt(unsigned int *len, istream &stream) {
   if(!stream.read((char *)len, sizeof(unsigned int)))
    return false;
   *len = bswap_32(*len);
   return true;
  }
  static bool ReadString(string &str, istream &stream) {
   unsigned int len;
   if(!ReadInt(&len, stream))
    return false;
   str.resize(len);
   if(!ReadBytes(&str[0], len, stream))
    return false;
   return true;
  }
  static bool ReadBytes(char *ptr, unsigned int len, istream &stream) {
   stream.read(ptr, sizeof(unsigned char) * len);
   if(stream.eof()) return false;
   return true;
  }
};

该程序需要注意以下几点:

(1)注意大小端编码规则,解析key和value长度时,需要对长度进行字节翻转。

(2)注意循环结束条件,仅仅靠!cin.eof()判定是不够的,仅靠这个判定会导致多输出一条重复数据。

(3)本程序只能运行在linux系统下,windows操作系统下将无法运行,因为windows下的标准输入cin并直接支持二进制数据读取,需要将其强制以二进制模式重新打开后再使用。

3. 程序测试与运行

程序写好后,第一步是编译C++程序。由于该程序需要运行在多节点的Hadoop集群上,为了避免部署或者分发动态库带来的麻烦,我们直接采用静态编译方式,这也是编写Hadoop C++程序的基本规则。为了静态编译以上MapReduce程序,安装protocol buffers时,需采用以下流程(强调第一步),

./configure –disable-shared
make –j4
make install

然后使用以下命令编译程序,生成可执行文件ProtoMapper:

g++ -o ProtoMapper ProtoMapper.cpp person.pb.cc `pkg-config –cflags –static –libs protobuf` -lpthread

在正式将程序提交到Hadoop集群之前,需要先在本地进行测试,本地测试运行脚本如下:

#!/bin/bash
HADOOP_HOME=/opt/dong/yarn-client
INPUT_PATH=/tmp/person.seq
OUTPUT_PATH=file:///tmp/output111
echo "Clearing output path: $OUTPUT_PATH"
$HADOOP_HOME/bin/hadoop fs -rmr $OUTPUT_PATH
${HADOOP_HOME}/bin/hadoop jar\
   ${HADOOP_HOME}/share/hadoop/tools/lib/hadoop-streaming-2.2.0.jar\
  -D mapred.reduce.tasks=0\
  -D stream.map.input=rawbytes\
  -files ProtoMapper\
  -jt local\
  -fs local\
  -input $INPUT_PATH\
  -output $OUTPUT_PATH\
  -inputformat SequenceFileInputFormat\
  -mapper ProtoMapper

注意以下几点:

(1)使用stream.map.input指定输入数据解析成rawbytes格式

(2) 使用-jt和-fs两个参数将程序运行模式设置为local模式

(3)使用-inputformat指定输入数据格式为SequenceFileInputFormat

(4)使用mapred.reduce.tasks将Reduce Task数目设置为0

在本地tmp/output111目录下查看测试结果是否正确,如果没问题,可改写该脚本(去掉-fs和-jt两个参数,将输入和输出目录设置成HDFS上的目录),将程序直接运行在Hadoop上。

原文链接:利用Hadoop Streaming处理二进制格式文件       (编辑/刘亚琼  审校/仲浩)

高德LBS智能硬件编程马拉松:硬件复兴,等你挑战! 首届bong线上黑客马拉松:运动数据分析应用bong+获大奖 英特尔推出基于WebRTC的协同通讯方案 凸显本土创新“软”实力 一周消息树:不同设备不同界面的Windows 9正在逼近! 乐卓网络CEO李澄澄:移动游戏IP是把双刃剑 高性能动画!HTML5 Canvas JavaScript框架KineticJS Swift最酷炫的七大功能 微信开发者大会讲师介绍:柳峰与你一起玩转公众平台应用开发 TIOBE 2014年7月编程语言排行榜:仅发布1月,Swift进Top 20! 艾格拉斯CEO王双义:手游自研引擎的荣耀之路 以招行为例,深圳云软黄榕振谈微信公众帐号企业应用高级开发 来自前苹果高管Heidi Roizen的经验之谈 【短讯】Dropbox、微软OneDrive打不开,国内用户该如何应对? 5分钟弄懂Docker! RakNet:被OculusVR收购的跨平台游戏网络引擎 Qualcomm业务拓展副总裁沈劲:智能终端的延伸 苹果发布Xcode 6 Beta 3,Swift迎来重大更新! Linkedln技术高管Jay Kreps:Lambda架构剖析 《近匠》极光推送:聚焦巨头无法快速转身的领域 Babylon.js:拥有微软背景的开源3D游戏引擎 EMC 2014存储布局及十大新技术要点 腾讯推出零流量地图 离线实现公交步行导航 Atmel 1.4亿美元收购Newport Media 巩固物联网产品线 微信大会首批议程出炉 深度解析招行服务号是如何炼成的? 指尖上的阅读:MIT开发盲人专用设备FingerReader 从桌面到移动:异构计算翻天覆地的技术变革 《近匠》Blueware何晓阳,不做中国的New Relic 全球最杰出的14位程序员 Microsoft、RedHat、IBM、Docker等公司加入Kubernetes社区 Intel携手三星、博通等 建立物联网联盟OIC 一周消息树:微软半年内将终止对Win 7、Office 2010 SP1等产品的支持 编辑控件怎样才能显示那些怪字符? 有没有人喜欢郑智化 大家推荐好听的几首歌吧! 请教:怎么学c++? 高手点拨! 各位网络高手.如何在程序里讲ip地址转化为域名 有什么方法,可使表单内的组件背景变成透明的而文字不透明,请看例子: 编辑控件怎样才能显示那些怪字符???? swall(壹心) 你还在深圳特区吗? 如何设置Session的密码?请高手指点迷经^^^^^ 哪位可以解释一下下面的代码? perl 的人气太差。罢了罢了。找本perl自己搞定 MsSQL7.0 当日志文件大小未限制而变得很大时,怎样清日志文件,使其减小? 请教诸位牛兄牛姐牛夫人---有难度哦(着急出活!) 基本问题:如何将一个.txt中的内容读入到内存再从内存中读出并存为另一个文件?谢了先!!!! 高手帮帮忙!!!!!!!!!!!!!! 又有台风了。。。。 在zip包中加入ASP推荐的PAD File有用吗????? PB连接SQL数数库,为什么显示的表会不全 如何把一个文件file.dat里的数据写入软盘0磁道0磁头1扇区. 我要骂人! chris2001(牛虻),不是东西 华为工程师 谁知道 vb 的序列号?????? VS.NET 有开了个新铺子。为什么我的ejb/j2ee还没有开张。气愤。 老大们:我是菜鸟,有问题要问,不过不要笑我。一定给分的 再次发问:关于在SQL SERVER中的某张表上建立触发器...... 没有有这样的病毒,或者文件 各位老大,如果有asp、sql基础学jsp和php是不是比较容易一些呀?言者有分哦! dll中怎样调用主程序中的函数? 新手请教接口聚合!!!!!!!!! 高分求教!有没有谁编写过WEB服务器程序? 微软OfficeXp女孩 请教一个报表问题? 小技巧!!! delphi中调用MessageBox出错,高手指点一下。 大家好,这是我提的第一个问题!我学DELPHI才两周!对您的指点,小弟万分感激! 请问sybase12。0中,游标能不能用动态sql申请 紧急求助:如何调用父对话框的函数 各位好,我在VB下做了一个ACTIVE 控件,但是加不到CBUILDER 上,但能加到VB里,为什么? 婚介所 关于C++打开文件的问题? 请教一下关于多表查询的问题 求助:中文Delhpi帮助 为什么我的rose装好后没有html帮助?还有安装时应该选择client还是administrator? cathy0505;chenkane;zhangshicun;swall;(_2_);riluo;wt13;MonkeyLin;seedundersnow;qancy_chen;cathy0505;acute 一个很简单的问题,怎样把一个php字符串变量转为实型变量 用过2K/NT DDK的大侠:如何在2000的内核里编程向硬盘里写文件,如:写c:\a.txt到C上,给我一段代码? 我急需一个“医院生殖中心病历管理软件”,sbf2000@363.net 怎样在vb中用insert ,updata语句进行数据库操作?????????? ra和rm 及ram格式有何区别呢 用2K/NT DDK的大侠:如何在2000的内核里编程向硬盘里写文件,如:写c:\a.txt到C上,给我一段代码? 管道压力表、真空压力表一般与何种阀门连接?现在有两种阀门Z43F-16C Q41F-16C 压力表一般和哪种阀门连接啊. 0.1mol的铜与足量的浓硫酸反应生成SO2的体积约为22.4 L 氢气为什么在测定1mol气体体积被选为被测气体 φ76的管道,压力0.5Mpa每分钟流多少方水 常温常压下 1mol二氧化硫的体积小于22.4l这句话正确,为什么 用化学反应气体体积测定仪测定1mol氢气的体积,实验数据记录如下:镁带质量为0.120g,注入10ml稀硫酸,液体量瓶的读数为130.0ml.则(1)该温度下,1mol氢气的体积测定值为___ 管道φ219,压力0.4-0.5MPa流量150m3/h需提高压力1.0mpa用多大管道增压泵 在20度温度下,压强为101kpa时1mol的氧气和1mol的二氧化碳为什么所含的分子数相等?不是2和3吗? 用化学反应气体体积测定仪测定1mol H2体积时,向气体发生器加料口注射稀硫酸后,拔出注射器时针头脱落而仍然扎在橡皮塞上,使结果偏大还是偏小?为什么? 给水管道试验压力是如何确定说明其合格标准 1mol氢气和0.5mol氧气在相同状况下混合,求混合气体中氢气的体积分数,物质的量分数和质量分数 测定1mol气体的体积误差分析请给我这个实验所有可能的误差分析,怎样怎样做使结果偏小、怎样怎样做使结果偏大,用这种形式给我写出来.认真回答, 请问进气管道压力5MPa 管子直径10毫米,忽略阻力,求1小时流量是多少?出口0.1MPa,空气,管道长度1米 同温同压下,分别为1mol的氢气和氧气,它们的〔 〕(A)质量相同,体积不同 (B)分子个数相同,质量不同 (C)体积相同,分子数不同 (D)体积相同,分子数也相同 为什么不是D? 求温度为27摄氏度时,一摩尔氧气具有多少内能?R=8.31J.MOL-1.K-1,注-1是次方 差压变送器测流量用的温压补偿公式设计温度和设计压力是怎么来的?有没有通用数值的?我们厂的煤气管道就是露天的,夏天最高有45度,冬天最低-5度吧.另外是不是说不同的管道这2个参数不同 下列物质中所含微粒物质的量最多的是A 3.01×10∧23个镁原子 B 1mol氮气 C 4克氢气 D 36克氧气 一瓶氧气由于被阳光照射,温度由27℃升高到54℃,则瓶内氧气压强增大为原来的几倍? 孔板流量计为什么要加压力补偿和温度补偿 标准状态下,1mol的水体积是多少?存在22.4升的水蒸气吗?化学里面的确是说标准状况下没水蒸气没错,但是物理题目里动不动就来个“标准状况下1mol的水蒸气体积是22.4升,请问此时水分子间的 在2L的的密闭容器中加入1mol氮气(N2),和3mol氢气(H2),发生N2+3H2=2NH3.在2s末时,测得容器中含有0.4mol的NH3,求该反应的化学反应速率,希望能有详解, 孔板流量计上的NM3是什么单位 1mol水的体积和1mol冰的体积哪个大 密闭容器中充入1mol氮气.3mol氢气,当反应达平衡后充入氮气保持压强不变,平横将怎样移动?为什么? 谁讲一下跟孔板流量计相关的知识, 1. 1mol的二氧化碳和1mol的水在相同状态下体积一定相等吗? 1mol的二氧化碳和1mol的水在相同状态下体积一定相等吗?不同的气体,若体积不等,则它们所含的分子数一定不等吗? 三摩尔氢气和一摩尔氮气放入密闭容器中在催化剂存在下反正,理论上放出热量多少氢气分子键能:436kJ/mol氮气:945kJ/mol氨气:391kJ/mol. 请问孔板流量计的测量原理? 1mol的氧气、1mol的水和1mol的铁哪个体积大 密闭容器中有一摩尔氮气和三摩尔氢气发生反应,达到平衡时,冲入氮气保持压强不变,则平衡怎么移动? 孔板流量计安装条件孔板流量计(流量计油表)安装管道在安装的时候有没有什么条件 0.1mol氢气和0.1mol水所含的分子数相同,在标准状况占体积都约是2.24L ;0.1mol任何气体标况下V都是2.24L这两句话 哪句错了啊? 请说下理由 谢谢! 为什么1mol氮气和3mol氢气 反应与 2mol氨气反应 等效? 在标准状况下1mol任何气体的体积都是22.4L那么在标准状况下11.2L氢气中的分子数是多少个 葡萄糖发生加成反应? 写出氨气在一定条件下生成1mol氮气和3mol氢气的热化学方程式 带夹套的不锈钢反应釜是不是需要检测的压力容器?蒸汽加热,需要温度105 容器内为常压,所需蒸汽压力2公斤请提供解释或依据夹套内为水蒸气,容器内为水和肉(猪肉、牛肉或羊肉),它是低压 在标准状况下,1mol任何气体的体积都是22.4L.那么,在标准状况下,11.2L氢气中的分子数是几个 酯和氢气能否发生加成反应,条件是什么 搪瓷反应釜是几类压力容器 在标准状况下1moL水的体积是22. 葡萄糖与氢气反应的化学方程式 半管加热的反应釜是否属于压力容器? 标准状况下1mol的混合气体的体积怎么是22.4L.分子间有较大的间隔.像酒精和水一样混合了不是会体积减少么 1mol苯可以与多少摩尔氢气发生加成反应?还有,氧化铝和氧化铁是不是两性化合物? 甲醇对20号压力容器用钢材有没有腐蚀性? 是不是当1mol气体的体积为22.4L时,它就一定处在标况下麽?1mol水蒸气在标况下的体积是22. 1mol萘最多与几mol氢气发生加成反应 求一反应釜各管道连接图 标准状况下,1mol任何气体所占的体积为22.4L 在标况下,1mol任何体积所占的体积约为22.4L多了一个约,为什么不同的题目上都对 1mol有机物能与1mol氢气发生加成反应,产物是,此有机物的结构简式可能有? 压力表连在管道上,为什么压力表与管道连接处之间管道是弯成一个圆的样子 标况下,1mol三氧化硫的体积为22.4L 1mol苯乙烯与氢气完全发生加成反应需要几mol氢气啊苯环只有5个H啊,为什么还需要3mol, 管道压力表怎样装 1MOL SO2在20度 体积大于22.4L为什么是错的? 1mol维生素A分子最多可跟几mol氢气发生加成反应 请问有没有关于化工设备(比如精馏塔,反应釜,管道等)的国家标准可查? 这种说法对吗?1mol三氧化硫和1mol二氧化硫体积均为22.4L如题 下列测定常温下1mol氢气体积的操作中,使测定结果偏大的是()?A.装置接口处有气体漏出B.称好镁带后用砂皮擦去表面的氧化膜C.硫酸注入量不足10mL,使镁带有剩余D.计算液体体积时,液体量瓶
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn