HDFS分为文件格式和压缩格式
文件格式分为两大类:面向行和面向列两大类文件格式.
面向行/列 | 类型名称 | 是否可切分 | 优点 | 缺点 | 适用场景 |
面向行 | 文本文件格式(.txt) | 是 | 查看方便编辑简单 | 无压缩占空间大、传输压力大、数据解析开销大 | 学习练习使用 |
面向行 | sequenceFile序列文件格式(.seq) | 是 | 原生支持、二进制kv存储、支持行和块压缩 | 本地查看不方便:小文件合并成kv结构后不易查看内部数据 | 生产环境使用、map输出的默认文件格式 |
面向列 | rcfile文件格式(.rc) | 是 | 数据加载快、查询快、空间利用率高、高负载能力 | 每一项都不是最高 | 学习生产均可 |
面向列 | orcfile文件格式(.orc) | 是 | 兼具了rcfile优点,进一步提高了读取、存储效率、新数据类型的支持 | 每一项都不是最高 | 学习生产均可 |
压缩格式分为可切分计算和不可切分计算两种
可切分性 | 类型名称 | 是否原生 | 优点 | 缺点 | 适用场景 |
可切分 | lzo(.lzo) | 否 | 压缩/解压速度快,合理的压缩率 | 压缩率比gzip低,非原生、需要native安装 | 单个文件越大,lzo优点越明显,压缩完成后>=200M为宜 |
可切分 | bzip2(.bz2) | 是 | 高压缩率超过gzip,原生支持、不需要native安装,用linux bzip可解压操作 | 压缩/解压速率慢 | 处理速度要求不高、压缩率要求高的情况 |
不可切分 | gzip(.gz) | 是 | 压缩/解压速度快,原生/native都支持,使用方便 | 不可切分,对cpu要求较高 | 压缩完成后<=128M的文件适宜 |
不可切分 | snappy(.snappy) | 否 | 高压缩/解压速度,合理的压缩率 | 压缩率比gzip低,非原生、需要native安装 | 适合作为map->reduce或是job数据流中间的数据传输格式 |
文件格式的使用
MR输出结果的默认文件格式为txt文件格式
设置输出格式为gzip
通过shell命令改动,添加参数设置模板:
yarn jar jar_path main_class_path -Dk1=v1参数列表 <in> <out>
具体应用:
yarn jar TlHadoopCore-jar-with-dependencies.jar \
com.tianliangedu.examples.WordCountV2 \
-Dmapred.output.compress=true \
-Dmapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec \
/tmp/tianliangedu/input /tmp/tianliangedu/output19
WordCount第二版-WorCountV2.java源码:
//启动mr的driver类
public class WordCountV2 {
//map类,实现map函数
public static class TokenizerMapper extends
Mapper<Object, Text, Text, IntWritable> {
//暂存每个传过来的词频计数,均为1,省掉重复申请空间
private final static IntWritable one = new IntWritable(1);
//暂存每个传过来的词的值,省掉重复申请空间
private Text word = new Text();
//核心map方法的具体实现,逐个<key,value>对去处理
public void map(Object key, Text value, Context context)
throws IOException, InterruptedException {
//用每行的字符串值初始化StringTokenizer
StringTokenizer itr = new StringTokenizer(value.toString());
//循环取得每个空白符分隔出来的每个元素
while (itr.hasMoreTokens()) {
//将取得出的每个元素放到word Text对象中
word.set(itr.nextToken());
//通过context对象,将map的输出逐个输出
context.write(word, one);
}
}
}
//reduce类,实现reduce函数
public static class IntSumReducer extends
Reducer<Text, IntWritable, Text, IntWritable> {
private IntWritable result = new IntWritable();
//核心reduce方法的具体实现,逐个<key,List(v1,v2)>去处理
public void reduce(Text key, Iterable<IntWritable> values,
Context context) throws IOException, InterruptedException {
//暂存每个key组中计算总和
int sum = 0;
//加强型for,依次获取迭代器中的每个元素值,即为一个一个的词频数值
for (IntWritable val : values) {
//将key组中的每个词频数值sum到一起
sum += val.get();
}
//将该key组sum完成的值放到result IntWritable中,使可以序列化输出
result.set(sum);
//将计算结果逐条输出
context.write(key, result);
}
结果样例:
设置输出格式为lzo格式:
lzo非原生支持,需要先安装lzo
先安装lzo再安装lzop lzo应用
安装lzo命令:
yum -y install lzo lzo-devel hadooplzo hadooplzo-native
安装lzop命令:
yum install lzop
yarn jar TlHadoopCore-jar-with-dependencies.jar \
com.tianliangedu.core.WordCountV2 \
-Dmapred.output.compress=true \
-Dmapred.output.compression.codec=com.hadoop.compression.lzo.LzopCodec \
/tmp/tianliangedu/input /tmp/tianliangedu/output37
查看结果
//从hdfs中下载lzo文件
hdfs dfs -get /tmp/tianliangedu/output41/part-r-00000.lzo
//通过安装了lzo包的lzop命令解压后查看
lzop -cd part-r-00000.lzo | more
//查看效果
MR应用--自定义Partition
Partition默认实现-HashPartition
//source code:
package org.apache.hadoop.mapreduce.lib.partition;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.mapreduce.Partitioner;
/** Partition keys by their {@link Object#hashCode()}. */
@InterfaceAudience.Public
@InterfaceStability.Stable
public class HashPartitioner<K, V> extends Partitioner<K, V> {
/** Use {@link Object#hashCode()} to partition. */
public int getPartition(K key, V value, int numReduceTasks) {
return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
}
}
MapReduce个数的确定时机
提交job后,任务开始正式计算之间即已经确定
Map数量的 确定:由输入数据文件的总大小、数据格式 块大小综合确定
Reduce数量确定:系统根据输入数据量的大小自动确定,有固定的计算公式,待冲刺环节详解。另外,用户可以自定义设置,通过参数配置,由用户决定。
自定义reduce数量
yarn jar TlHadoopCore-jar-with-dependencies.jar \
com.tianliangedu.examples.WordCountV2 \
-Dmapred.output.compress=true \
-Dmapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec \
-Dmapred.reduce.tasks=2 \
/tmp/tianliangedu/input /tmp/tianliangedu/output38
最终效果图
自定义Partition实现
继承Partitioner类,自定义实现Partition
通过继承Partitioner类,自定义实现Partition
/**
自定义Partition的定义
*/
public static class MyHashPartitioner<K, V> extends Partitioner<K, V> {
/** Use {@link Object#hashCode()} to partition. */
public int getPartition(K key, V value, int numReduceTasks) {
return (key.toString().charAt(0) < 'q' ? 0 : 1) % numReduceTasks;
// return key.toString().charAt(0);
}
}