Hadoop2.7.3 mapreduce(三)SequenceFile和MapFile 簡介與應用

Hadoop的 hdfs 和 mapreduce 子框架主要是針對大數據文件設計的,在小文件的處理上不但效率低下,而且十分消耗磁盤空間(每一個小文件佔用一個Block , hdfs默認block大小爲128M)。因此,hadoop提供給我們SequenceFile和MapFile兩種容器處理小文件,將這些小文件組織起來統一存儲。

【SequenceFile】

1、SequenceFile概述

(1)SequenceFile文件是Hadoop用來存儲二進制形式的 <key, value> 而設計的一種平面文件(Flat File)

(2)SequenceFile是一種容器,把所有文件打包到SequenceFile類中可以高效的對小文件進行存儲和處理

(3)SequenceFile文件不按照其存儲的Key進行排序,其提供的內部類Writer提供了append功能

(4)SequenceFile中的Key 和 Value 可以使任意類型的Writable或自定義Writable

(5)在存儲結構上,SequenceFile由一個Header 後跟多條Record組成,Header主要包含Key classname,value classname,存儲壓縮算法,用戶自定義元數據等信息,此外,還包含一些同步標識,用於快速定位到記錄的邊界。每條Record以鍵值對的方式進行存儲,用來表示它的字符數組可以一次解析成:記錄的長度、Key的長度、Key值和value值,並且Value值的結構取決於該記錄是否被壓縮。

2、SequenceFile壓縮

(1)SequenceFIle的內部格式取決於是否啓用壓縮,如果是壓縮,則又可以分爲記錄壓縮和塊壓縮。

(2)三種類型的壓縮:

   a.無壓縮類型:如果沒有啓用壓縮(默認設置)那麼每個記錄就由它的記錄長度(字節數)、鍵的長度,鍵和值組成。長度字段爲4字節。

   b.記錄壓縮類型:記錄壓縮格式與無壓縮格式基本相同,不同的是值字節是用定義在頭部的編碼器來壓縮。注意:鍵是不壓縮的。下圖爲記錄壓縮:


   c.塊壓縮類型:塊壓縮一次壓縮多個記錄,因此它比記錄壓縮更緊湊,而且一般優先選擇。當記錄的字節數達到最小大小,纔會添加到塊。該最小值由io.seqfile.compress.blocksize中的屬性定義。默認值是1000000字節。格式爲記錄數、鍵長度、鍵、值長度、值。下圖爲塊壓縮:

3、SequenceFile實例

工具類:

package com.yc.hadoop42_003_mapreduce;

import java.io.IOException;
import java.net.URI;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.SequenceFile;
import org.apache.hadoop.io.SequenceFile.Reader;
import org.apache.hadoop.io.SequenceFile.Writer;
import org.apache.hadoop.io.Text;

public class SequenceFileUtil {

	private static Configuration conf = new Configuration();//創建配置文件
	private static URI uri = URI.create("hdfs://master:9000/");

	public static void doWrite(String[] texts, String strPath) {
		try {
			Writer writer = SequenceFile.createWriter(conf, Writer.file(new Path(strPath)),
					Writer.keyClass(IntWritable.class), Writer.valueClass(Text.class));
			StringBuffer str = new StringBuffer();

			for (String text : texts) {
				writer.append(new IntWritable(str.length()), new Text(text));
				str.append(text);
			}

			IOUtils.closeStream(writer);	//關閉流
		} catch (IllegalArgumentException | IOException e) {
			e.printStackTrace();
		}
	}

	public static void doRead(String strPath) {
		try {
			Reader reader = new Reader(conf, Reader.file(new Path(strPath)));
			IntWritable key = new IntWritable();
			Text value = new Text();

			while (reader.next(key, value)) {
				System.out.println("key:" + key);
				System.out.println("value:" + value);
				System.out.println("position:" + reader.getPosition()); //返回輸入文件中的當前字節位置
			}
			IOUtils.closeStream(reader);
		} catch (IllegalArgumentException | IOException e) {
			e.printStackTrace();
		}
	}
}

測試類:

package com.yc.hadoop42_003_mapreduce;

import org.junit.Test;

public class SequenceFileUtilTest {

	@Test
	public void testDoWrite() {
		String[] texts = {"人生若只如初見", "何事秋風悲畫扇",
				"等閒變卻故人心", "卻道故人心易變",
				"驪山語罷清宵半", "淚雨零鈴終不怨",
				"何如薄倖錦衣郎", "比翼連枝當日願"};
		SequenceFileUtil.doWrite(texts, "hdfs://master:9000/data/test.txt");
	}

	@Test
	public void testDoRead() {
		SequenceFileUtil.doRead("hdfs://master:9000/data/test.txt");
	}

}
測試結果:
key:0
value:人生若只如初見
position:173
key:7
value:何事秋風悲畫扇
position:218
key:14
value:等閒變卻故人心
position:263
key:21
value:卻道故人心易變
position:308
key:28
value:驪山語罷清宵半
position:353
key:35
value:淚雨零鈴終不怨
position:398
key:42
value:何如薄倖錦衣郎
position:443
key:49
value:比翼連枝當日願
position:488

4、SequenceFile總結

【優點】

a、支持基於記錄(Record)或塊(Block)的數據壓縮。

b、支持splitable,能夠作爲MapReduce的輸入分片。

c、修改簡單:主要負責修改相應的業務邏輯,而不用考慮具體的存儲格式。

【缺點】

a、需要一個合併文件的過程,且合併後的文件不方便查看。


【MapFile】

1、MapFile概述

(1)MapFile是排序後的SequenceFile,通過觀察其目錄結構可以看到MapFile由兩部分組成分別是data和index。

(2)index作爲文件的數據索引,主要記錄了每個Record的Key值,以及該Record在文件中的偏移位置。在MapFile被訪問的時候,索引文件會被加載到內存,通過索引映射關係可以迅速定位到指定Record所在文件位置,因此,相對SequenceFile而言,MapFile的檢索效率是最高的,缺點是會消耗一部分內存來存儲index數據。

(3)需要注意的是,MapFile並不不會把所有的Record都記錄到index中去,默認情況下每隔128條記錄會存儲一個索引映射。當然,記錄間隔可認爲修改,通過MapFile.Writer的setIndexInterval()方法,或修改io.map.index.interval屬性。

(4)與SequenceFile不同的是,MapFile的KeyClass一定要實現WritableComparable接口,即Key值是可比較的。


2、MapFile實例

工具類:

package com.yc.hadoop42_003_mapreduce;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.MapFile;
import org.apache.hadoop.io.Text;

public class MapFileUtil {

	private static Configuration conf = new Configuration();

	public static void doWriter(String[] texts, String dirPath) {
		try {
			MapFile.Writer writer = new MapFile.Writer(conf, new Path(dirPath),
					MapFile.Writer.keyClass(LongWritable.class), MapFile.Writer.valueClass(Text.class));
			LongWritable key = new LongWritable();
			for (String text : texts) {
				writer.append(key, new Text(text));
				key.set(key.get()+text.getBytes().length);
			}
			IOUtils.closeStream(writer);
		} catch (IllegalArgumentException | IOException e) {
			e.printStackTrace();
		}
	}

	public static void doReader(String dirPath) {
		try {
			MapFile.Reader reader = new MapFile.Reader(new Path(dirPath), conf);
			LongWritable key = new LongWritable();
			Text value = new Text();

			while (reader.next(key, value)) {
				System.out.println("key:" + key + ", value:" + value);
			}
			IOUtils.closeStream(reader);
		} catch (IllegalArgumentException | IOException e) {
			e.printStackTrace();
		}
	}

}

測試類:

package com.yc.hadoop42_003_mapreduce;

import org.junit.Test;

public class MapFileUtilTest {

	@Test
	public void testDoWriter() {
		String[] texts = { "人生若只如初見", "何事秋風悲畫扇", "等閒變卻故人心", "卻道故人心易變", "驪山語罷清宵半", "淚雨零鈴終不怨", "何如薄倖錦衣郎", "比翼連枝當日願" };
		MapFileUtil.doWriter(texts, "hdfs://master:9000/data/test01.txt");
	}

	@Test
	public void testDoReader() {
		MapFileUtil.doReader("hdfs://master:9000/data/test01.txt");
	}

}

測試結果:

key:0, value:人生若只如初見
key:21, value:何事秋風悲畫扇
key:42, value:等閒變卻故人心
key:63, value:卻道故人心易變
key:84, value:驪山語罷清宵半
key:105, value:淚雨零鈴終不怨
key:126, value:何如薄倖錦衣郎
key:147, value:比翼連枝當日願


Hadoop中的SequenceFile和MapFile

發佈了27 篇原創文章 · 獲贊 11 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章