HDFS中常用的压缩算法和区别
HDFS中常用的压缩算法和区别
首先我们要明确一点,为什么要进行数据压缩?
Cloudera 提出过数据压缩的基本准则:
- 是否压缩数据以及使用何种压缩格式对性能具有重要的影响。
- 需要平衡压缩和解压缩数据所需的能力、读写数据所需的磁盘 IO,以及在网络中发送数据所需的网络带宽。
此外,用到哪些压缩格式,为什么使用这些压缩格式而不是其他的压缩格式?主要考虑到:
- 文件和压缩算法的组合是否支持可分片, MapReduce 在读取数据的时候需要并行, 这就要求压缩后的文件可以分片读取。
- io 读取性能, 读取相同信息量的信息, 压缩后的文件不仅占用的存储空间低, 而且还会提高磁盘 io 的读取效率。 提高程序的运行速度
- CPU 资源也是启用何种压缩算法不得不考虑的因素, 一般来说压缩效率越高的算法对 io 效率和存储利用率的提升越有促进作用, 但另一方面也会更高的消耗 CPU 资源。 所以我们需要在这中间寻求一个平衡点。
- 共通性, 文件格式是否支持多种语言, 服务的读取。 比如 Hadoop 主要的序列化格式为 Writables, 但是 Writables 只支持 Java, 所以后面衍生出了 Avro, Thrift 等格式。 还如 OrcFile 是对 Hive 设计的一种列式存储格式, 但是他不支持 Impala, 数据的共用性受到了制约。
- 错误处理能力, 有的文件的某一部分坏掉之后会影响整个表, 有的只会影响其后的数据, 有的只会影响坏掉数据块本身(Avro)。
- 读取和载入效率, RCFile 的载入速度慢, 但是查询相应速度快, 相对更适合数据仓库一次插入多次读取的特性。
HDFS 中的文件类型
- 基于文件存储
- 序列化和列式存储,例如:Avro、RCFile 和 Parquet
- 压缩存储,例如 Snappy、LZO 等
下面我们依次来介绍。
基于文件[K:V]的 SequenceFile
sequenceFile 文件是 Hadoop 用来存储**二进制形式的[Key,Value]**对而设计的一种平面文件(Flat File)。可以把 SequenceFile 当做是一个容器,把所有的文件打包到 SequenceFile 类中可以高效的对小文件进行存储和处理。SequenceFile 文件并不按照其存储的 Key 进行排序存储,SequenceFile 的内部类 Writer 提供了 append 功能。SequenceFile 中的 Key 和 Value 可以是任意类型 Writable 或者是自定义 Writable。
在存储结构上,SequenceFile 主要由一个 Header 后跟多条 Record 组成,Header 主要包含了 Key classname,value classname,存储压缩算法,用户自定义元数据等信息,此外,还包含了一些同步标识,用于快速定位到记录的边界。每条 Record 以键值对的方式进行存储,用来表示它的字符数组可以一次解析成:记录的长度、Key 的长度、Key 值和 value 值,并且 Value 值的结构取决于该记录是否被压缩。
SequenceFile 支持三种记录存储方式:
- 无压缩, io 效率较差. 相比压缩, 不压缩的情况下没有什么优势.
- 记录级压缩, 对每条记录都压缩. 这种压缩效率比较一般.
- 块级压缩, 这里的块不同于 hdfs 中的块的概念. 这种方式会将达到指定块大小的二进制数据压缩为一个块. 相对记录级压缩, 块级压缩拥有更高的压缩效率. 一般来说使用 SequenceFile 都会使用块级压缩.
但是 SequenceFile 只支持 Java, SequenceFile 一般用来作为小文件的容器使用, 防止小文件占用过多的 NameNode 内存空间来存储其在 DataNode 位置的元数据。
序列化存储格式和列式存储
序列化指的是数据格式转化为字节流的过程, 主要用于远程传输或存储. hadoop 采用的序列化格式主要是 Writables. 但是它只能支持 Java 语言, 所以后来就出现了 Thrift, Avro 等格式。
1、Thrift
Thrift 是 Facebook 开发的框架,用于实现跨语言提供服务和接口,满足跨平台通信。但是 Thrift 不支持分片,且缺少 MapReduce 的原生支持。所以我们可以忽略这个压缩算法。
2、Avro
Avro 是 Hadoop 中的一个子项目,也是 Apache 中一个独立的项目,Avro 是一个基于二进制数据传输高性能的中间件。在 Hadoop 的其他项目中,例如 HBase 和 Hive 的 Client 端与服务端的数据传输也采用了这个工具。
Avro 是一个语言无关的数据序列化的系统,它的出现主要是为了解决 Writables 缺少跨语言移植的缺陷。Avro 将模式存储在文件头中,所以每个文件都是自描述的,而且 Avro 还支持模式演进(schema evolution),也就是说,读取文件的模式不需要与写入文件的模式严格匹配,当有新需求时,可以在模式中加入新的字段。
Avro 将数据定义(描述)和数据一起存储在一条消息中,其中数据定义以JSON格式存储,数据以二进制格式存储。Avro标记数据用于将大型数据集分割成适合MapReduce处理的子集。
- Avro 支持分片, 即使是进行 Gzip 压缩之后
- 支持跨语言的支持
3、 RCFile
RCFile是Hive推出的一种专门面向列的数据格式。 它遵循“先按列划分,再垂直划分”的设计理念。当查询过程中,针对它并不关心的列时,它会在IO上跳过这些列。需要说明的是,RCFile在map阶段从 远端拷贝仍然是拷贝整个数据块,并且拷贝到本地目录后RCFile并不是真正直接跳过不需要的列,并跳到需要读取的列, 而是通过扫描每一个row group的头部定义来实现的,但是在整个HDFS Block 级别的头部并没有定义每个列从哪个row group起始到哪个row group结束。所以在读取所有列的情况下,RCFile的性能反而没有SequenceFile高。
Hive的Record Columnar File,这种类型的文件先将数据按行划分成Row Group,在Row Group内部,再将数据按列划分存储。
4、ORCFile
ORC 的全称是(Optimized Row Columnar)提供了一种比RCFile更加高效的文件格式。其内部将数据划分为默认大小为250M的Stripe。每个Stripe包括索引、数据和Footer。索引存储每一列的最大最小值,以及列中每一行的位置。
ORC 文件格式是一种 Hadoop 生态圈中的列式存储格式,它的产生早在 2013 年初,最初产生自 Apache Hive,用于降低 Hadoop 数据存储空间和加速 Hive 查询速度。和 Parquet 类似,它并不是一个单纯的列式存储格式,仍然是首先根据行组分割整个表,在每一个行组内进行按列存储【存储所有行上的第一列,然后是所有行上的第二列,以此类推】。ORC 文件是自描述的,它的元数据使用 Protocol Buffers 序列化,并且文件中的数据尽可能的压缩以降低存储空间的消耗,目前也被 Spark SQL、Presto 等查询引擎支持。2015 年 ORC 项目被 Apache 项目基金会提升为 Apache 顶级项目。ORC 具有以下一些优势:
- ORC 是列式存储,有多种文件压缩方式,并且有着很高的压缩比
- 文件是可切分(Split)的。因此,在 Hive 中使用 ORC 作为表的文件存储格式,不仅节省 HDFS 存储资源,查询任务的输入数据量减少,使用的 MapTask 也就减少了
- 提供了多种索引,row group index、bloom filter index
- ORC 可以支持复杂的数据结构(比如 Map 等)
- 支持所有的 hive 类型, 包括复合类型: structs, lists, maps 和 unions
- 支持分片
- 可以仅返回查询的列, 减少 io 消耗, 提升性能
- 可以与 Zlib, LZO 和 Snappy 结合进一步压缩
5、Parquet
是Hadoop的一种列存储格式,基于Google的Dremel。特别擅长处理深度嵌套的数据。提供了有效的编码和压缩方案
压缩算法
gzip 压缩
优点:压缩率比较高,而且压缩/解压速度也比较快;hadoop 本身支持,在应用中处理 gzip 格式的文件就和直接处理文本一样;有 hadoop native 库;大部分 linux 系统都自带 gzip 命令,使用方便。
缺点:不支持 split。
应用场景:当每个文件压缩之后在 130M 以内的(1 个块大小内),都可以考虑用 gzip 压缩格式。譬如说一天或者一个小时的日志压缩成一个 gzip 文件,运行 mapreduce 程序的时候通过多个 gzip 文件达到并发。hive 程序,streaming 程序,和 java 写的 mapreduce 程序完全和文本处理一样,压缩之后原来的程序不需要做任何修改。
lzo 压缩
优点:压缩/解压速度也比较快,合理的压缩率;支持 split,是 hadoop 中最流行的压缩格式;支持 hadoop native 库;可以在 linux 系统下安装 lzop 命令,使用方便。
缺点:压缩率比 gzip 要低一些;hadoop 本身不支持,需要安装;在应用中对 lzo 格式的文件需要做一些特殊处理(为了支持 split 需要建索引,还需要指定 inputformat 为 lzo 格式)。
应用场景:一个很大的文本文件,压缩之后还大于 200M 以上的可以考虑,而且单个文件越大,lzo 优点越明显。
snappy 压缩
优点:高速压缩速度和合理的压缩率;支持 hadoop native 库。
缺点:不支持 split;压缩率比 gzip 要低;hadoop 本身不支持,需要安装;linux 系统下没有对应的命令。
应用场景:当 mapreduce 作业的 map 输出的数据比较大的时候,作为 map 到 reduce 的中间数据的压缩格式;或者作为一个 mapreduce 作业的输出和另外一个 mapreduce 作业的输入。
bzip2 压缩
优点:支持 split;具有很高的压缩率,比 gzip 压缩率都高;hadoop 本身支持,但不支持 native;在 linux 系统下自带 bzip2 命令,使用方便。
缺点:压缩/解压速度慢;不支持 native。
应用场景:适合对速度要求不高,但需要较高的压缩率的时候,可以作为 mapreduce 作业的输出格式;或者输出之后的数据比较大,处理之后的数据需要压缩存档减少磁盘空间并且以后数据用得比较少的情况;或者对单个很大的文本文件想压缩减少存储空间,同时又需要支持 split,而且兼容之前的应用程序(即应用程序不需要修改)的情况。
最后,我们用一张图来对这 4 种压缩格式进行比较:
4 种压缩格式进行比较:
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!