定义上的区别
block(块)
定义:block(块)是从一个大规模文件上分出来,存储在每个数据节点(DataNode)(默认3个)上,并由HDFS文件系统默认的存储最小单位(64MB或者128MB),是物理块。
split(切片)
定义:split(切片)是mapreduce中的map task开始之前,将文件按指定大小切割后的若干部分,默认大小与block(块)一样,同为64MB(128MB),是逻辑上的分片。
可以看出来,两者是从不同的角度来定义的:
block是hdfs中切块的大小,block是物理上的分割,HDFS以固定大小的block(块)为基本单位存储数据(分布式文件系统,实际存储角度,物理存储单位)。而split(切片)是MapReduce里的概念,是切片的概念,split是逻辑上的分割,MapReduce以split(切片)作为处理单位(逻辑单位)。
HDFS block(块)
假设我们有一个文件,大小为434MB,很明显因为这个文件大于一个 HDFS 块大小,所有如果我们将这个文件存放到 HDFS 上,会生成 4 个 HDFS 块,如下图
(可以看出文件被切成 4 个块了,前三个块大小正好是 128MB,剩下的数据存放到第 4 个 HDFS 块中)
说明:
- 图中的蓝色块代表一个文件
- 中间的紫色矩形块代表一个 HDFS 块,矩形里面的数字代表 HDFS 块的编号,读整个文件的时候是从编号为0的 HDFS 块开始读,然后依次是1,2,3…
- 最下面的一行矩形代表文件里面存储的内容,每个小矩形代表一行数据,里面的数字代表数据的编号。
从上图我们可以清晰地看出,当我们往 HDFS 写文件时,HDFS 会将文件切割成大小为 128MB 的块,切割的时候不会判断文件里面存储的到底是什么东西,所以逻辑上属于一行的数据会被切割成两部分,这两部分的数据被物理的存放在两个不同的 HDFS 块中。
FLile split(切片)
每个 FileSplit 的起始偏移量和上面 HDFS 每个文件块一致。在将文件存储在 HDFS 的时候,文件被切割成一个一个 HDFS Block(块),其中会导致一些逻辑上属于一行的数据会被切割成两部分, 同理 TextInputFormat 遇到这样的数据有俩种操作:
- 在初始化 LineRecordReader 的时候,如果 File Split (切片)的起始位置 start 不等于0, 说明这个 Block (块)不是第一个 Block(块),这时候一律丢掉这个 Block (块)的第一行数据。
- 在读取每个 Block(块) 的时候,都会额外地多读取一行,如果出现数据被切割到另外一个 Block (块)里面,这些数据能够被这个任务读取。
说明:
- 图中的上方的黑色线代表 HDFS 块边界(block boundary);
- 下方的黑色线代表Split 读数的边界。
从图中可以清晰地看出:
- 当程序读取 Block 0 的时候,虽然第五行数据被分割并被存储在 Block 0 和 Block 1 中,但是,当前程序能够完整的读取到第五行的完整数据。
- 当程序读取 Block 1 的时候,由于其 FileSplit (切片)的起始位置 start 不等于0,这时候会丢掉第一行的数据,也就是说 Block 1 中的第四行部分数据会被丢弃,而直接从第五行数据读取。这样做的原因是,Block 1 中的第四行部分数据在程序读取前一个 Block 的时候已经被读取了,所以可以直接丢弃。
- 其他剩下的 Block 读取逻辑和这个一致。
总结
从上面的分析可以得出以下的总结
- Split 和 HDFS Block 是一对多的关系;
- HDFS block 是数据的物理表示,而 Split 是 block 中数据的逻辑表示;
- 满足数据本地性的情况下,程序也会从远程节点上读取少量的数据,因为存在行被切割到不同的 Block 上。