目录
Hadoop 序列化
Hadoop序列化定义步骤
示例
Hadoop 压缩
为什么要在Hadoop中引入压缩
Hadoop 支持的压缩类别
各种压缩方式详解
Gzip压缩
lzo压缩
snappy压缩
bzip2压缩
压缩参数配置
存储文件类型
SequenceFile
SequenceFile简介
SequenceFile 文件的结构
SequenceFile的压缩
MapFile
使用示例
Hadoop 序列化
为什么要序列化
一般来说,“活的”对象只生存在内存里,关机断电就没有了。而且“活的”对象只能由本地的进程使用,不能被发送到网络上的另外一台计算机。 然而序列化可以存储“活的”对象,可以将“活的”对象发送到远程计算机。
什么是序列化
序列化就是把内存中的对象,转换成字节序列(或其他数据传输协议)以便于存储(持久化)和网络传输。 反序列化就是将收到字节序列(或其他数据传输协议)或者是硬盘的持久化数据,转换成内存中的对象。
为什么不用Java的序列化?
Java的序列化是一个重量级序列化框架(Serializable),一个对象被序列化后,会附带很多额外的信息(各种校验信息,header,继承体系等),不便于在网络中高效传输。所以,hadoop自己开发了一套序列化机制(Writable),精简、高效。
为什么序列化对Hadoop很重要?
因为Hadoop在集群之间进行通讯或者RPC调用的时候,需要序列化,而且要求序列化要快,且体积要小,占用带宽要小。所以必须理解Hadoop的序列化机制。序列化和反序列化在分布式数据处理领域经常出现:进程通信和永久存储。
Hadoop中各个节点的通信是通过远程调用(RPC)实现的,那么RPC序列化要求具有以下特点:
1.紧凑:紧凑的格式能让我们充分利用网络带宽,而带宽是数据中心最稀缺的资
2.快速:进程通信形成了分布式系统的骨架,所以需要尽量减少序列化和反序列化的性能开销,
这是基本的;
3.可扩展:协议为了满足新的需求变化,所以控制客户端和服务器过程中,需要直接引进相应的协议,
这些是新协议,原序列化方式能支持新的协议报文;
4.互操作:能支持不同语言写的客户端和服务端进行交互;
5.常用数据序列化类型
常用的数据类型对应的hadoop数据序列化类型
Java类型 Hadoop Writable类型
boolean BooleanWritable
byte ByteWritable
int IntWritable
float FloatWritable
long LongWritable
double DoubleWritable
string Text
map MapWritable
array ArrayWritable
Hadoop序列化定义步骤
自定义bean对象实现序列化接口(Writable)
自定义bean对象要想序列化传输,必须实现序列化接口,需要注意以下7项。
(1)必须实现Writable接口
(2)反序列化时,需要反射调用空参构造函数,所以必须有空参构造
public FlowBean() {
super();
}
(3)重写序列化方法
@Override
public void write(DataOutput out) throws IOException {
out.writeLong(upFlow);
out.writeLong(downFlow);
out.writeLong(sumFlow);
}
(4)重写反序列化方法
@Override
public void readFields(DataInput in) throws IOException {
upFlow = in.readLong();
downFlow = in.readLong();
sumFlow = in.readLong();
}
(5)注意反序列化的顺序和序列化的顺序完全一致
(6)要想把结果显示在文件中,需要重写toString(),可用”\t”分开,方便后续用。
(7)如果需要将自定义的bean放在key中传输,则还需要实现comparable接口,
因为mapreduce框中的shuffle过程一定会对key进行排序。
@Override
public int compareTo(FlowBean o) {
// 倒序排列,从大到小
return this.sumFlow > o.getSumFlow() ? -1 : 1;
}
示例
import org.apache.hadoop.io.Writable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class PersonWritable implements Writable {
private Person person;
public PersonWritable() {
this.person = new Person();
}
public void setPerson(Person person) {
this.person = person;
}
public Person getPerson() {
return person;
}
// 重写序列化接口
public void write(DataOutput dataOutput) throws IOException {
dataOutput.writeUTF(person.getName());
dataOutput.writeInt(person.getAge());
dataOutput.writeUTF(person.getSex());
}
// 重写反序列化接口,这里的顺序要与序列化的顺序一致
public void readFields(DataInput dataInput) throws IOException {
person.setName(dataInput.readUTF());
person.setAge(dataInput.readInt());
person.setSex(dataInput.readUTF());
}
}
Hadoop 压缩
为什么要在Hadoop中引入压缩
Hadoop是一个分布式的计算框架,内部的HDFS是一个分布式存储文件系统,Mapreduce是分布式的计算框架。
既然是分布式系统,在运行中不可避免的各个结点之间需要通过网络进行通信。以Mapreduce计算过程为例,在整个计算过程中
有两次输入文件,两次输出文件。
MapInput->MapTask->Output MapResult ->ReduceInput->ReduceTask->Output ReduceResult
假设现在有一个2PB大小的文件需要计算,在不使用压缩算法时,按文件块256M进行split,
那么会产生split=1024*1024*2/256=8192,就是8192个map任务,假设hadoop所在物理机是8核, 16G内存。
现在设置每个map任务使用1核,2G内存,每两个map任务使用一个jvm,那么就需要物理机512台,但是现在机房只有300台
机器,这时我们就需要将输入的文件变小但数据又不能变,那么就需要使用压缩来完成这个任务。
可以在MapInput, Output MapResult, Output ReduceResult时使用压缩算法,不但可以减少I/O的压力,还能减少Reduce在拉取
MapResult的网络传输数据流量。
注意:只有在需要时,才使用压缩,否则反而会造成效率低下
运算密集型的job,少用压缩
IO密集型的job,多用压缩
Hadoop 支持的压缩类别
压缩算法 | Linux | haoop 自带 | 算法 | 文件扩展名 | 是否可切割 | 设置压缩后原来的程序是否需要修改 | 对应编解码器 |
DEFLATE | 支持 | 支持 | DEFLATE | .deflate | 否 | 与文本处理类似不需要修改 | org.apache.hadoop.io.compress.DefaultCodec |
Gzip | 支持 | 支持 | DEFLATE | .gz | 否 | 与文本处理类似不需要修改 | org.apache.hadoop.io.compress.GzipCodec |
Bzip2 | 支持 | 支持 | bzip2 | .bz2 | 是 | 与文本处理类似不需要修改 | org.apache.hadoop.io.compress.Bzip2Codec |
Lzo | 需要安装 | 需要安装 | lzo | .lzo | 是 | 需要创建索引,需要指定输入格式 | com.hadoop.compression.lzo.LzopCodec |
Snappy | 需要安装 | 需要安装 | snappy | .snappy | 否 | 与文本处理类似不需要修改 | org.apache.hadoop.io.compress.SnappyCodec |
各种压缩方式详解
Gzip压缩
优点:压缩率比较高,而且压缩/解压速度也比较快;hadoop本身支持,在应用中处理gzip格式的文件就和直接处理文本一样;大部分linux系统都自带gzip命令,使用方便。
缺点:不支持split。
应用场景:当每个文件压缩之后在130M以内的(1个块大小内),都可以考虑用gzip压缩格式。譬如说一天或者一个小时的日志压缩成一个gzip文件,运行mapreduce程序的时候通过多个gzip文件达到并发。hive程序,streaming程序,和java写的mapreduce程序完全和文本处理一样,压缩之后原来的程序不需要做任何修改。
lzo压缩
优点:压缩/解压速度也比较快,合理的压缩率;支持split,是hadoop中最流行的压缩格式;可以在linux系统下安装lzop命令,使用方便。
缺点:压缩率比gzip要低一些;hadoop本身不支持,需要安装;在应用中对lzo格式的文件需要做一些特殊处理(为了支持split需要建索引,还需要指定inputformat为lzo格式)。
应用场景:一个很大的文本文件,压缩之后还大于200M以上的可以考虑,而且单个文件越大,lzo优点越越明显。
使用需要安装:
lzo的使用注意事项
1.LzoCodec比LzopCodec更快, LzopCodec为了兼容LZOP程序添加了如 bytes signature, header等信息
2.如果使用 LzoCodec作为Reduce输出,则输出文件扩展名为".lzo_deflate",它无法被lzop读取;如果使用LzopCodec作为
Reduce输出,则扩展名为".lzo",它可以被lzop读取
3.生成lzo index job的”DistributedLzoIndexer“无法为 LzoCodec,即 ".lzo_deflate"扩展名的文件创建index
4.”.lzo_deflate“文件无法作为MapReduce输入,”.LZO"文件则可以。
snappy压缩
优点:高速压缩速度和合理的压缩率。
缺点:不支持split;压缩率比gzip要低;hadoop本身不支持,需要安装;
应用场景:当mapreduce作业的map输出的数据比较大的时候,作为map到reduce的中间数据的压缩格式;或者作为一个mapreduce作业的输出和另外一个mapreduce作业的输入。
使用需要安装:
bzip2压缩
优点:支持split;具有很高的压缩率,比gzip压缩率都高;hadoop本身支持,但不支持native;在linux系统下自带bzip2命令,使用方便。
缺点:压缩/解压速度慢;不支持native。
应用场景:适合对速度要求不高,但需要较高的压缩率的时候,可以作为mapreduce作业的输出格式;或者输出之后的数据比较大,处理之后的数据需要压缩存档减少磁盘空间并且以后数据用得比较少的情况;或者对单个很大的文本文件想压缩减少存储空间,同时又需要支持split,而且兼容之前的应用程序(即应用程序不需要修改)的情况。
压缩参数配置
core-site.sml
输入压缩
<property>
<name>io.compression.codecs</name>
<value>
org.apache.hadoop.io.compress.GzipCodec,
org.apache.hadoop.io.compress.DefaultCodec, #zlib->Default
org.apache.hadoop.io.compress.BZip2Codec,
com.hadoop.compression.lzo.LzoCodec,
com.hadoop.compression.lzo.LzopCodec,
org.apache.hadoop.io.compress.Lz4Codec,
org.apache.hadoop.io.compress.SnappyCodec,
</value>
</property>
mapred-site.xml
<property>
启用mapper输出压缩
<name>mapreduce.map.output.compress</name>
<value>true</value> 默认false
</property>
<property>
设置压缩的类型
<name>mapreduce.map.output.compress.codec</name>
<value>org.apache.hadoop.io.compress.BZip2Codec</value>
</property>
<property>
启用reduce输出压缩
<name>mapreduce.output.fileoutputformat.compress</name>
<value>true</value> 默认false
</property>
<property>
设置压缩的类型
<name>mapreduce.output.fileoutputformat.compress.codec</name>
<value>org.apache.hadoop.io.compress.BZip2Codec</value>
</property>
<property>
SequenceFile输出使用的压缩类型:NONE和BLOCK
<name>mapreduce.output.fileoutputformat.compress.type</name>
<value>BLOCK</value> 默认RECORD
</property>
存储文件类型
HDFS是一个文件系统,理论上是可以存放任何类型的文件。比如我们一般见到的.txt类型的文本文件等,但是做为一个大数据
框架为了提高效率,也有推荐文件存储类型。
SequenceFile
SequenceFile简介
1.sequenceFile文件是Hadoop用来存储二进制形式的[Key,Value]对而设计的一种平面文件(Flat File)。
2.可以把SequenceFile当做是一个容器,把所有的文件打包到SequenceFile类中可以高效的对小文件进行存储和处理。
3.SequenceFile文件并不按照其存储的Key进行排序存储,SequenceFile的内部类Writer提供了append功能。
4.SequenceFile中的Key和Value可以是任意类型Writable或者是自定义Writable。
5.在存储结构上,SequenceFile主要由一个Header后跟多条Record组成,
Header主要包含了Key classname,value classname,存储压缩算法,用户自定义元数据等信息,
此外,还包含了一些同步标识,用于快速定位到记录的边界。每条Record以键值对的方式进行存储,用来表示它的字符数组可以一次解析成:记录的长度、Key的长度、Key值和value值,并且Value值的结构取决于该记录是否被压缩。
SequenceFile 文件的结构
版本:包括3个字节的SEQ,和真实版本号(e.g. SEQ4 or SEQ6)
key的类名 //e.g. org.apache.hadoop.io.IntWritabe
value的类名 //
是否压缩 //boolean
是否是块压缩 //boolean
压缩编解码器 //compression codec
元数据 //真实数据
同步点 //定位数据,判断数据的结尾和起始
SequenceFile的压缩
SeqFile内部提供压缩机制,包含以下三种压缩:
不压缩:不压缩
记录压缩:只压缩value
块压缩:多个Key和Value聚集成block,以block为单位进行压缩,block的大小可以配置
注:压缩算法可通过CompressionCodec指定
MapFile
MapFile是个文件夹,包含index和data文件,是一种比较特殊的自带排序的SeqFile。
Index是索引文件,存放少量Key,在读取时会将其加载到内存,用于提高检索速度
Data文件是真实数据文件 两者均为SequenceFile类型
使用示例