Hadoop序列化机制
当程序在向磁盘中写数据和读取数据时会进行序列化和反序列化,磁盘IO的这些步骤无法省略,我们可以从这些地方着手优化。
- 当我们想把内存数据写到文件时,写序列化后再写入,将对象信息转为二进制存储,默认Java的序列化会把整个继承体系下的信息都保存,这就比较大了,会额外消耗性能。
- 反序列化也是一样的,如果文件很大,加载数据进内存也需要耗费很多资源。
鉴于上述问题,Hadoop提供了常用类型的序列化
Java基本类型 | Writable | 序列化大小(字节) |
布尔型 | BooleanWritable | 1 |
字节型 | ByteWritable | 1 |
整型 | IntWritable | 4 |
VIntWritable | 1-5 | |
浮点型 | FloatWritable | 4 |
长整型 | LongWritable | 8 |
VLongWritable | 1-9 | |
双精度浮点型 | DoubleWritable | 8 |
Text等价于java.lang.String的Writable,针对UTF-8序列 NullWritable是单例,获取实例使用NullWritable.get()。
优化后的特点:
- 紧凑: 高效使用存储空间
- 快速: 读写数据的额外开销小
- 可扩展: 可透明地读取老格式的数据
- 互操作: 支持多语言的交互
Java序列化的不足:
- 不精简,附加信息多,不太适合随机访问
- 存储空间大,递归地输出类的超类描述直到不再有超类
InputFormat分析
Hadoop中有一个抽象类是InputFormat,InputFormat抽象类是MapReduce输入数据的顶层基类,这个 抽象类中只定义了两个方法。
一个是getSplits方法
另一个是createRecordReader方法
这个抽象类下面有三个子继承类,
DBInputFormat是操作数据库的,
FileInputFormat是操作文件类型数据的,
DelegatingInputFormat是用在处理多个输入时使用的
这里面比较常见的也就是 FileInputFormat 了,
FileInputFormat 是所有以文件作为数据源的基类, FileInputFormat保存job输入的所有文件,并实现了对输入文件计算splits的方法,至于获得文件中数据 的方法是由子类实现的。 FileInputFormat下面还有一些子类:
- CombineFileInputFormat:处理小文件问题的,后面我们再详细分析 TextInputFormat:是默认的处理类,处理普通文本文件,他会把文件中每一行作为一个记录,将每 一行的起始偏移量作为key,每一行的内容作为value,这里的key和value就是我们之前所说的k1,v1 它默认以换行符或回车键作为一行记录
- NLineInputFormat:可以动态指定一次读取多少行数据
参考:
hadoop的源码: https://archive.apache.org/dist/hadoop/common/hadoop-3.2.0/hadoop-3.2.0-src.tar.gz