Hadoop的I/O操作
HDFS的数据完整性
检验数据是否损坏最常见的措施是:在数据第一次引入系统时计算校验和并在数据通过一个不可靠通道进行传输时再次计算校验和,这样就能发现数据是否被损坏。HDFS会对写入的所有数据计算校验和,并在读取数据时验证校验和。
- 客户端写数据:正在写数据的客户端将数据及其校验和发送到由一系列datanode组成的管线,管线中最后一个datanode负责验证校验和。如果检测到错误,客户端会收到一个ChecksumException异常。(datanode负责在收到数据后存储该数据并验证校验和,它在收到客户端的数据或者复制其他datanode的数据时执行这个操作)
- 客户端从datanode读数据:验证校验和,将它们与datanode中存储的校验和进行比较。每个datanode中持久保存有一个用于验证校验和的校验日志,它知道每个数据块的最后一次验证时间,客户端成功验证一个数据块后,会告诉datanode,由此更新日志。
- 每个datanode也会在后台中运行一个DataBlockScanner,从而定期验证存储在这个datanode上的所有数据块。
- 若datanode读取数据时发现数据损坏,首先向namenode报告,再抛出ChecksumException异常,namenode将这个数据块标记为损坏,之后它安排这个数据块的一个复本复制到另一个datanode,如此一来,数据的复本因子回到期望水平,已损坏的复本会被删除。
压缩
压缩的好处:减少存储文件所需要的磁盘空间;加速数据在网络和磁盘上的传输。
mapreduce中为什么不使用gzip格式
由于map以文件的每个切分作为输入,而gzip格式使用DEFLATE算法来存储压缩后的数据,而DEFLATE算法将数据存储在一系列连续的数据块中,需要从每个块的起始位置进行读取,因此不支持切分,而mapreduce需要从数据列的任意位置开始读取,在这种情况下,mapreduce不会尝试切分gzip压缩文件,会将所有数据块全部输入给一个map节点,而大多数数据块并没有存储在执行该map任务的节点,牺牲了数据的本地性。
如何选择压缩格式
按效率从高到低排序:
- 使用容器文件格式,如顺序文件、Avro数据文件,它们同时支持压缩和切分。
- 使用支持切分的压缩格式,如bzip2(慢)
- 将文件切分成块(合理选择块的大小,确保压缩后接近HDFS块的大小),然后用任意方式压缩。
- 存储未经压缩的文件
在mapreduce中使用压缩
- 对最终输出进行压缩:
FileOutputFormat.setCompressOutput(job, true);
FileOutputFormat.setOutputCompressorClass(job, GzipCodec.class); - 对map任务输出进行压缩:
// vv MaxTemperatureWithMapOutputCompression
Configuration conf = new Configuration();
conf.setBoolean(Job.MAP_OUTPUT_COMPRESS, true);
conf.setClass(Job.MAP_OUTPUT_COMPRESS_CODEC, GzipCodec.class,
CompressionCodec.class);
Job job = new Job(conf);
// ^^ MaxTemperatureWithMapOutputCompression
序列化
序列化在分布式数据处理的两大领域经常出现:进程间通信和永久存储。
通常情况下,序列化格式需要满足:
- 紧凑(紧凑格式能充分利用网络带宽)
- 快速(分布式系统需要尽量减少序列化和反序列化的性能开销)
- 可扩展(能够满足协议变化的需求,在控制客户端和服务器的过程中,可以直接引进相应的协议)
- 支持互操作(可以支持不同语言写的客户端和服务器交互)
hadoop自己的序列化格式-----Writable
定制Writable集合
public class TextPair implements WritableComparable {private Text first;
private Text second;public TextPair() {
set(new Text(), new Text());
}public TextPair(String first, String second) {
set(new Text(first), new Text(second));
}public TextPair(Text first, Text second) {
set(first, second);
}public void set(Text first, Text second) {
this.first = first;
this.second = second;
}public Text getFirst() {
return first;
}public Text getSecond() {
return second;
}public void write(DataOutput out) throws IOException {
first.write(out);
second.write(out);
}public void readFields(DataInput in) throws IOException {
first.readFields(in);
second.readFields(in);
}@Override
public int hashCode() {
return first.hashCode() * 163 + second.hashCode();
}@Override
public boolean equals(Object o) {
if (o instanceof TextPair) {
TextPair tp = (TextPair) o;
return first.equals(tp.first) && second.equals(tp.second);
}
return false;
}@Override
public String toString() {
return first + "\t" + second;
}public int compareTo(TextPair tp) {
int cmp = first.compareTo(tp.first);
if (cmp != 0) {
return cmp;
}
return second.compareTo(tp.second);
}
}定制的comparator-----实现直接比较数据流中的记录
public static class Comparator extends WritableComparator {private static final Text.Comparator TEXT_COMPARATOR = new Text.Comparator();
public Comparator() {
super(TextPair.class);
}@Override
public int compare(byte[] b1, int s1, int l1,
byte[] b2, int s2, int l2) {try {
int firstL1 = WritableUtils.decodeVIntSize(b1[s1]) + readVInt(b1, s1);
int firstL2 = WritableUtils.decodeVIntSize(b2[s2]) + readVInt(b2, s2);
int cmp = TEXT_COMPARATOR.compare(b1, s1, firstL1, b2, s2, firstL2);
if (cmp != 0) {
return cmp;
}
return TEXT_COMPARATOR.compare(b1, s1 + firstL1, l1 - firstL1,
b2, s2 + firstL2, l2 - firstL2);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
}
// vv TextPairFirstComparator
public static class FirstComparator extends WritableComparator {
private static final Text.Comparator TEXT_COMPARATOR = new Text.Comparator();
public FirstComparator() {
super(TextPair.class);
}
@Override
public int compare(byte[] b1, int s1, int l1,
byte[] b2, int s2, int l2) {
try {
int firstL1 = WritableUtils.decodeVIntSize(b1[s1]) + readVInt(b1, s1);
int firstL2 = WritableUtils.decodeVIntSize(b2[s2]) + readVInt(b2, s2);
return TEXT_COMPARATOR.compare(b1, s1, firstL1, b2, s2, firstL2);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
@Override
public int compare(WritableComparable a, WritableComparable b) {
if (a instanceof TextPair && b instanceof TextPair) {
return ((TextPair) a).first.compareTo(((TextPair) b).first);
}
return super.compare(a, b);
}
}
// ^^ TextPairFirstComparator
Avro
Avro是个支持多语言的数据序列化框架,支持c,c++,c#,Python,java,php,ruby,java。
他的诞生主要是为了弥补Writable只支持java语言的缺陷。很多人会问类似的框架还有Thrift和Protocol,那为什么不使用这些框架,而要重新建一个框架呢,
或者说Avro有哪些不同。首先,Avro和其他框架一样,数据是用与语言无关的schema描述的,不
同的是Avro的代码生成是可选的,schema和数据存放在一起,而schema使得整个数据的处理过
程并不生成代码、静态数据类型等,为了实现这些,需要假设读取数据的时候模式是已知的,这样
就会产生紧耦合的编码,不再需要用户指定字段标识。Avro的schema是JSON格式的,而编码后的数据是二进制格式(当然还有其他可选项)的,这样对
于已经拥有JSON库的语言可以容易实现。Avro还支持扩展,写的schema和读的schema不一定要是同一个,也就是说兼容新旧schema和新旧
客户端的读取,比如新的schema增加了一个字段,新旧客户端都能读旧的数据,新客户端按新的sch
ema去写数据,当旧的客户端读到新的数据时可以忽略新增的字段。Avro还支持datafile文件,schema写在文件开头的元数据描述符里,Avro datafile支持压缩和分割,这
就意味着可以做Mapreduce的输入。
Hadoop的I/O操作的更多相关文章
- Hadoop之HDFS文件操作常有两种方式(转载)
摘要:Hadoop之HDFS文件操作常有两种方式,命令行方式和JavaAPI方式.本文介绍如何利用这两种方式对HDFS文件进行操作. 关键词:HDFS文件 命令行 Java API HD ...
- Hadoop HDFS文件常用操作及注意事项
Hadoop HDFS文件常用操作及注意事项 1.Copy a file from the local file system to HDFS The srcFile variable needs t ...
- Hadoop系列007-HDFS客户端操作
title: Hadoop系列007-HDFS客户端操作 date: 2018-12-6 15:52:55 updated: 2018-12-6 15:52:55 categories: Hadoop ...
- Hadoop HDFS的Shell操作实例
本文发表于本人博客. 我们知道HDFS是Hadoop的分布式文件系统,那既然是文件系统那最起码会有管理文件.文件夹之类的功能吧,这个类似我们的Windows操作系统一样的吧,创建.修改.删除.移动.复 ...
- Java接口对Hadoop集群的操作
Java接口对Hadoop集群的操作 首先要有一个配置好的Hadoop集群 这里是我在SSM框架搭建的项目的测试类中实现的 一.windows下配置环境变量 下载文件并解压到C盘或者其他目录. 链接: ...
- Hadoop之HDFS文件操作
摘要:Hadoop之HDFS文件操作常有两种方式.命令行方式和JavaAPI方式.本文介绍怎样利用这两种方式对HDFS文件进行操作. 关键词:HDFS文件 命令行 Java API HD ...
- 初识Hadoop二,文件操作
1.使用hadoop命令查看hdfs下文件 [root@localhost hadoop-2.7.3]# hadoop fs -ls hdfs://192.168.36.134:9000/ 开始在se ...
- hadoop的hdfs文件操作实现上传文件到hdfs
这篇文章主要介绍了使用hadoop的API对HDFS上的文件访问,其中包括上传文件到HDFS上.从HDFS上下载文件和删除HDFS上的文件,需要的朋友可以参考下hdfs文件操作操作示例,包括上传文件到 ...
- Docker 安装Hadoop HDFS命令行操作
网上拉取Docker模板,使用singlarities/hadoop镜像 [root@localhost /]# docker pull singularities/hadoop 查看: [root@ ...
随机推荐
- 常用sql语句总结
一.连接数据库 mysql -h127.0.0.1(连接地址) -P3303(端口号) -uroot(用户名) -p123456(密码) 二.常用语句 show datebases; 查看数据库 cr ...
- iOS下载使用系统字体
iOS下载使用系统字体 通用开发中一般使用系统默认的字体: 另外系统也提供了一些其他字体我们可以选择下载使用 1:在mac上打开 字体册 app 即可查找系统支持的字体,适用于ios上开发使用 从ma ...
- 关于CSS3线型渐变这些事儿
CSS3兼容各浏览器的线型渐变方法: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...
- F2工作流引擎之 工作流运转模型(三)
1流程单起点单终止模型 单起点:一个流程定义必须有且唯一起点 单结束点:一个流程定义必须有且唯一结束点. 约定:提单与结束是每个流程必须有的活动,且唯一只有一个提单和结束. 2串行模型 描述:串行(S ...
- wine install 32bit netframewok
WINEARCH=win32 WINEPREFIX=~/.wine32 winecfg env WINEARCH=win32 WINEPREFIX=~/.wine32 winetricks dotne ...
- 2014年5月份第3周51Aspx源码发布详情
HGM简单连连看游戏源码 2014-5-19 [VS2010]源码描述:这是一款基于WinForm窗体程序的简单水果连连看的小游戏.界面比较美观, 功能如下:该游戏可以显示当前关卡,还有剩余时间.重 ...
- 探索javascript----我对渐变轮播图的理解
对于一个没有编程基础的人来说,我时常希望能有人告诉我,当我们看到一个效果的时候,该怎样有条理地分析出它的行为,而我自己有必要加强这方面的 自省,对于一个轮播图我是这样看的,自动播放必然带有一个定时器, ...
- Objective-C学习笔记-第一天(1)
.h头文件,用于声明一些公开的属性.方法.头文件一般不会放太多的东西,没必要暴露太多接口,私有和封装. .m主文件,用于实现.h文件中的方法,以及一些其它的方法. -(返回值)方法名参数1名称:(参数 ...
- 黑马程序员——【Java基础】——集合框架
---------- android培训.java培训.期待与您交流! ---------- 一.集合框架概述 (一)集合框架中集合类关系简化图 (二)为什么出现集合类? 面向对象语言对事物的体现都是 ...
- HDU 3006
http://acm.hdu.edu.cn/showproblem.php?pid=3006 注意到集合内数字最大只有14,状态压缩一下,然后枚举出所有状态 #include <iostream ...