SequenceFile(Hadoop序列文件)基础知识与应用

上篇编程实战系列中本人介绍了基本的使用HDFS进行文件读写的方法,这一篇将承接上篇重点整理一下SequenceFile的相关知识及应用

1. SequenceFile简介

SequenceFile是Hadoop自带的一种键值对文件格式,它具有以下几个特点:

1. 由于该文件类型是Hadoop自带的,因此对Hadoop环境具有最强的兼容性

2. 由于Hadoop不适合存储大量小文件,SequenceFile作为容器文件,能够封装大量的小文件为一个大文件,很好地解决了这个问题

3. 该文件类型具有可切割性,因此可实现数据本地化

2. SequenceFile编程实战

首先介绍一下SequenceFile的基本组成部分

1. SequenceFile的版本号,包括3个字节的SEQ,和它的版本号

2. key的类名

3. value的类名

4. 一个用来表示是否压缩的boolean值

5. 一个用来表示是否是块压缩的boolean值

6. 指定一个压缩编解码器

7. 元数据

8. 同步点:用来定位数据的边界

2.1 SequenceFile的基本读写操作

  1. //测试使用SequenceFile进行文件的写出
  2. @Test
  3. public void testWrite() throws Exception{
  4. //进行用户设置
  5. System.setProperty("HADOOP_USER_NAME", "root");
  6. //Configuration对象
  7. Configuration conf = new Configuration();
  8. //FileSystem对象
  9. FileSystem fs = FileSystem.get(conf);
  10. //新建一个写入器
  11. SequenceFile.Writer writer = SequenceFile.createWriter(fs, conf, new Path("/1.seq"), IntWritable.class, Text.class);
  12. //传入1000个hello做测试
  13. for(int i = 1; i <= 1000; i++){
  14. IntWritable key = new IntWritable(i);
  15. Text value = new Text("hello" + i);
  16. writer.append(key,value);
  17. }
  18. //关闭资源
  19. writer.close();
  20. }
  21.  
  22. //测试使用SequenceFile进行文件内容的读取
  23. @Test
  24. public void testRead() throws Exception{
  25. //进行用户设置
  26. System.setProperty("HADOOP_USER_NAME", "root");
  27. //Configuration对象
  28. Configuration conf = new Configuration();
  29. //FileSystem对象
  30. FileSystem fs = FileSystem.get(conf);
  31. //新建一个读取器
  32. SequenceFile.Reader reader = new SequenceFile.Reader(fs, new Path("/1.seq"), conf);
  33. //初始化两个对象作为容器存放读取到的数据
  34. IntWritable key = new IntWritable();
  35. Text value = new Text();
  36. for(int i = 1; i <= 1000; i++){
  37. reader.next(key,value);
  38. System.out.println("key: " + key + "\t" + "value: " + value);
  39. }
  40. //关闭资源
  41. reader.close();
  42. }

2.2 SequenceFile的sort和merge操作

sort操作

由于需要使用到排序方法,因此首先我们需要准备一个乱序的seq文件

  1. //准备一个乱序的seq文件
  2. @Test
  3. public void testWrite2() throws Exception{
  4. //进行用户设置
  5. System.setProperty("HADOOP_USER_NAME", "root");
  6. //Configuration对象
  7. Configuration conf = new Configuration();
  8. //FileSystem对象
  9. FileSystem fs = FileSystem.get(conf);
  10. //新建一个写入器
  11. SequenceFile.Writer writer = SequenceFile.createWriter(fs, conf, new Path("/in1.seq"), IntWritable.class, Text.class);
  12. //传入1000个hello做测试,但是是乱序输出的
  13. Random r = new Random();
  14. for(int i = 1; i <= 1000; i++){
  15. IntWritable key = new IntWritable(r.nextInt(1000));
  16. Text value = new Text("hello" + key);
  17. writer.append(key,value);
  18. }
  19. //关闭资源
  20. writer.close();
  21. }
  22.  
  23. //测试排序方法
  24. @Test
  25. public void testSort() throws Exception{
  26. //进行用户设置
  27. System.setProperty("HADOOP_USER_NAME", "root");
  28. //Configuration对象
  29. Configuration conf = new Configuration();
  30. //FileSystem对象
  31. FileSystem fs = FileSystem.get(conf);
  32. //新建一个排序器
  33. SequenceFile.Sorter sorter = new SequenceFile.Sorter(fs, IntWritable.class, Text.class, conf);
  34. //使用sorter对象的sort方法对key进行排序
  35. sorter.sort(new Path("/in1.seq"),new Path("/out1.seq"));
  36. }

排序前,可用hdfs dfs -text /in1.seq进行SequenceFile的查看,查看结果如下:

排序后,使用hdfs dfs -text /out1.seq进行查看,结果如下,排序成功!

merge操作

  1. //准备另一个seq文件用来进行merge操作
  2. @Test
  3. public void testWrite3() throws Exception{
  4. //进行用户设置
  5. System.setProperty("HADOOP_USER_NAME", "root");
  6. //Configuration对象
  7. Configuration conf = new Configuration();
  8. //FileSystem对象
  9. FileSystem fs = FileSystem.get(conf);
  10. //新建一个写入器
  11. SequenceFile.Writer writer = SequenceFile.createWriter(fs, conf, new Path("/in2.seq"), IntWritable.class, Text.class);
  12. //传入1000个hello做测试,但是是乱序输出的
  13. Random r = new Random();
  14. for(int i = 1; i <= 1000; i++){
  15. IntWritable key = new IntWritable(r.nextInt(1000));
  16. Text value = new Text("helloworld" + key);
  17. writer.append(key,value);
  18. }
  19. //关闭资源
  20. writer.close();
  21. }
  22.  
  23. //演示merge方法合并两个seq文件
  24. @Test
  25. public void testMerge() throws Exception{
  26. //进行用户设置
  27. System.setProperty("HADOOP_USER_NAME", "root");
  28. //Configuration对象
  29. Configuration conf = new Configuration();
  30. //FileSystem对象
  31. FileSystem fs = FileSystem.get(conf);
  32. //新建一个排序器,然后调用排序器的merge方法
  33. SequenceFile.Sorter sorter = new SequenceFile.Sorter(fs, IntWritable.class, Text.class, conf);
  34. Path path1 = new Path("/in1.seq");
  35. Path path2 = new Path("/in2.seq");
  36. Path[] paths = {path1,path2};
  37. sorter.merge(paths,new Path("/merge.seq"));
  38. }

2.3 SequenceFile三种压缩方式比较

SequenceFile一共有三种不同的压缩方式:

1. None:不压缩

2. Record:记录压缩,只压缩value

3. Block:块压缩,将多个K-V对聚集在一起,超过指定大小后(1000000字节,近似于1M)将其压缩

  1. package com.seq;
  2.  
  3. import org.apache.hadoop.conf.Configuration;
  4. import org.apache.hadoop.fs.FileSystem;
  5. import org.apache.hadoop.fs.Path;
  6. import org.apache.hadoop.io.IntWritable;
  7. import org.apache.hadoop.io.SequenceFile;
  8. import org.apache.hadoop.io.Text;
  9. import org.junit.Test;
  10.  
  11. /*
  12. 测试几种不同的压缩方式最终产生的文件大小
  13. */
  14. public class TestCompress {
  15.  
  16. @Test
  17. public void testCompression() throws Exception{
  18. System.setProperty("HADOOP_USER_NAME", "root");
  19. Configuration conf = new Configuration();
  20. FileSystem fs = FileSystem.get(conf);
  21. //分别新建三个不同的写出器,之后查看文件大小
  22. SequenceFile.Writer writer1 = SequenceFile.createWriter(fs, conf, new Path("/none.seq"), IntWritable.class, Text.class, SequenceFile.CompressionType.NONE);
  23. SequenceFile.Writer writer2 = SequenceFile.createWriter(fs, conf, new Path("/record.seq"), IntWritable.class, Text.class, SequenceFile.CompressionType.RECORD);
  24. SequenceFile.Writer writer3 = SequenceFile.createWriter(fs, conf, new Path("/block.seq"), IntWritable.class, Text.class, SequenceFile.CompressionType.BLOCK);
  25. //写入10000个hello作比较
  26. for(int i = 1; i <= 10000; i++){
  27. IntWritable key = new IntWritable(i);
  28. Text value = new Text("hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello" + key);
  29. writer1.append(key,value);
  30. writer2.append(key,value);
  31. writer3.append(key,value);
  32. }
  33. //关闭资源
  34. writer1.close();
  35. writer2.close();
  36. writer3.close();
  37. }
  38. }

查看文件大小,可得:不压缩文件大小 > 记录压缩文件大小 > 块压缩文件大小

2.4 压缩编解码器性能对比

目前常用的压缩编解码器主要有这几种:gzip, bzip2, lz4, lzo, Snappy等,关于性能的讨论,主要分为两派,一是追求较高的压缩比,但要付出时间的代价,二是追求较高的速度,但相对的,压缩比会小一些,对于lzo来说,首先需要导入相关依赖,依赖如下:

  1. <dependency>
  2. <groupId>org.anarres.lzo</groupId>
  3. <artifactId>lzo-hadoop</artifactId>
  4. <version>1.0.0</version>
  5. </dependency>

测试代码如下:

  1. package com.codec;
  2.  
  3. import com.hadoop.compression.lzo.LzopCodec;
  4. import org.apache.hadoop.conf.Configuration;
  5. import org.apache.hadoop.io.IOUtils;
  6. import org.apache.hadoop.io.compress.*;
  7.  
  8. import org.apache.hadoop.util.ReflectionUtils;
  9.  
  10. import java.io.File;
  11. import java.io.FileInputStream;
  12. import java.io.FileOutputStream;
  13.  
  14. /**
  15. * 综合测试压缩时间 解压时间 压缩大小
  16. */
  17.  
  18. public class TestCodec {
  19.  
  20. public static void main(String[] args) {
  21. Class[] classes = {
  22. GzipCodec.class,
  23. DefaultCodec.class,
  24. Lz4Codec.class,
  25. BZip2Codec.class,
  26. LzopCodec.class,
  27. SnappyCodec.class
  28. };
  29.  
  30. for (Class clazz : classes) {
  31. testCompress(clazz,"d:/test.log");
  32. testDecompress(clazz,"d:/test.log");
  33. }
  34.  
  35. }
  36.  
  37. /**
  38. * 测试压缩
  39. * @throws Exception
  40. */
  41. public static void testCompress(Class clazz, String path) {
  42.  
  43. try {
  44.  
  45. Configuration conf = new Configuration();
  46. //通过hadoop的反射工具类,获取压缩编解码器的实例
  47. CompressionCodec codec = (CompressionCodec)ReflectionUtils.newInstance(clazz, conf);
  48.  
  49. //获取编解码器默认扩展名
  50. String ext = codec.getDefaultExtension();
  51.  
  52. long start = System.currentTimeMillis();
  53.  
  54. //输入流读取本地文件
  55. FileInputStream fis = new FileInputStream(path);
  56. //输出流加压缩
  57. CompressionOutputStream cos = codec.createOutputStream(new FileOutputStream(path + ext));
  58.  
  59. IOUtils.copyBytes(fis,cos,1024);
  60.  
  61. System.out.println(ext + "压缩时间:" + (System.currentTimeMillis() -start));
  62.  
  63. File f = new File(path+ext);
  64. long length = f.length();
  65. System.out.println(ext + "压缩大小:" + length);
  66.  
  67. fis.close();
  68. cos.close();
  69. } catch (Exception e) {
  70. e.printStackTrace();
  71. }
  72. }
  73.  
  74. /**
  75. * 测试解压
  76. * @throws Exception
  77. */
  78. public static void testDecompress(Class clazz, String path){
  79.  
  80. try {
  81. Configuration conf = new Configuration();
  82. //通过hadoop的反射工具类,获取压缩编解码器的实例
  83. CompressionCodec codec = (CompressionCodec)ReflectionUtils.newInstance(clazz, conf);
  84.  
  85. //获取编解码器默认扩展名
  86. String ext = codec.getDefaultExtension();
  87.  
  88. long start = System.currentTimeMillis();
  89.  
  90. //输入流解压文件
  91. CompressionInputStream cis = codec.createInputStream(new FileInputStream(path+ext));
  92. //输出流加压缩
  93. FileOutputStream fos = new FileOutputStream(path + ext + ".log");
  94.  
  95. IOUtils.copyBytes(cis,fos,1024);
  96.  
  97. System.out.println(ext + "解压时间:" + (System.currentTimeMillis() -start));
  98.  
  99. cis.close();
  100. fos.close();
  101. } catch (Exception e) {
  102. e.printStackTrace();
  103. }
  104. }
  105. }

测试结果公布:

压缩大小
bzip2 < gzip < deflate < lz4 < lzo

压缩时间
lz4 < lzo < deflate < gzip < bzip2
328 576 1106 2653 20599

解压时间
lzo < lz4 < deflate < gzip < bzip2
404 427 437 524 4694

优化压缩比可选用:
bzip2
gzip
deflate

优化压缩速度可选用:
lz4
lzo

大数据学习笔记——Hadoop编程之SequenceFile的更多相关文章

  1. 大数据学习笔记——Hadoop编程实战之HDFS

    HDFS基本API的应用(包含IDEA的基本设置) 在上一篇博客中,本人详细地整理了如何从0搭建一个HA模式下的分布式Hadoop平台,那么,在上一篇的基础上,我们终于可以进行编程实操了,同样,在编程 ...

  2. 大数据学习笔记——Hadoop编程实战之Mapreduce

    Hadoop编程实战——Mapreduce基本功能实现 此篇博客承接上一篇总结的HDFS编程实战,将会详细地对mapreduce的各种数据分析功能进行一个整理,由于实际工作中并不会过多地涉及原理,因此 ...

  3. 大数据学习笔记——Hadoop高可用完全分布式模式完整部署教程(包含zookeeper)

    高可用模式下的Hadoop集群搭建 本篇博客将会在之前写过的Linux的完整部署的基础上进行,暂时不会涉及到伪分布式或者完全分布式模式搭建,由于HA模式涉及到的配置文件较多,维护起来也较为复杂,相信学 ...

  4. 大数据学习之Hadoop快速入门

    1.Hadoop生态概况 Hadoop是一个由Apache基金会所开发的分布式系统集成架构,用户可以在不了解分布式底层细节情况下,开发分布式程序,充分利用集群的威力来进行高速运算与存储,具有可靠.高效 ...

  5. 大数据学习笔记——Java篇之集合框架(ArrayList)

    Java集合框架学习笔记 1. Java集合框架中各接口或子类的继承以及实现关系图: 2. 数组和集合类的区别整理: 数组: 1. 长度是固定的 2. 既可以存放基本数据类型又可以存放引用数据类型 3 ...

  6. 大数据学习笔记——Linux完整部署篇(实操部分)

    Linux环境搭建完整操作流程(包含mysql的安装步骤) 从现在开始,就正式进入到大数据学习的前置工作了,即Linux的学习以及安装,作为运行大数据框架的基础环境,Linux操作系统的重要性自然不言 ...

  7. 大数据学习笔记之初识Hadoop

    1.Hadoop概述 1.1 Hadoop名字的由来 Hadoop项目作者的孩子给一个棕黄色的大象样子的填充玩具的命名 Hadoop的官网:http://hadoop.apache.org . 1.2 ...

  8. 大数据学习笔记之Hadoop(二):HDFS文件系统

    文章目录 一 HDFS概念 1.1 概念 1.2 组成 1.3 HDFS 文件块大小 二 HFDS命令行操作 三 HDFS客户端操作 3.1 eclipse环境准备 3.1.1 jar包准备 3.2 ...

  9. 大数据学习笔记之Hadoop(一):Hadoop入门

    文章目录 大数据概论 一.大数据概念 二.大数据的特点 三.大数据能干啥? 四.大数据发展前景 五.企业数据部的业务流程分析 六.企业数据部的一般组织结构 Hadoop(入门) 一 从Hadoop框架 ...

随机推荐

  1. nyoj 122-Triangular Sums (数学之读懂求和公式的迭代)

    122-Triangular Sums 内存限制:64MB 时间限制:3000ms 特判: No 通过数:5 提交数:7 难度:2 题目描述: The nth Triangular number, T ...

  2. shell脚本2——控制语句

    1.顺序结构体 命令从上往下顺序执行 2.分支结构体 1)判断真假 test 表达式 或者 [ 表达式 ](必须有空格) 真返回0,假返回1 test的别名是[, 参数是] 判断表达式 记忆 解释 ! ...

  3. PHP的global和$GLOBALS的区别

    global是关键字,通常添加在变量前,可以使变量的作用域为全局. $GLOBALS预定义的超全局变量,把变量扔到里面一样可以变成全局变量. $GLOBALS 是一个关联数组,每一个变量为一个元素,键 ...

  4. SpringBoot系列之i18n集成教程

    目录 1.环境搭建 2.resource bundle资源配置 3.LocaleResolver类 4.I18n配置类 5.Thymeleaf集成 SpringBoot系统之i18n国际化语言集成教程 ...

  5. Oracle10g安装步骤(一)

    本例使用安装程序:10201_database_win32 首先将所有文件提取解压出来后,执行setup.exe 安装步骤如下:

  6. 20191019-3 alpha week 2/2 Scrum立会报告+燃尽图 03

    此作业要求参见https://edu.cnblogs.com/campus/nenu/2019fall/homework/9799 一.小组情况 队名:扛把子 组长:迟俊文 组员:宋晓丽 梁梦瑶 韩昊 ...

  7. 如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题

    缓存雪崩 数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机. 比如一个雪崩的简单过程: 1.redis集群大面积故障 2.缓存失 ...

  8. vue 父子组件传值,兄弟组件传值

    父子组件中的传值 父向子    v-bind props <!-- 组件使用v-bind传值 --> <router :msg="msg"></rou ...

  9. RAM、ROM和fFLASH相关概念整理

    一:ROM ROM:Read Only Memory.只读存储器    是一种半导体内存,又叫做非挥发性内存.其特性是一旦数据被存储就无法再将之改变或删除.存储的数据不会因为电源关闭而消失.   二: ...

  10. Scrapy中的反反爬、logging设置、Request参数及POST请求

    常用的反反爬策略 通常防止爬虫被反主要有以下几策略: 动态设置User-Agent(随机切换User-Agent,模拟不同用户的浏览器信息.) 禁用cookies(也就是不启用cookies midd ...