Flink教程-flink 1.11 流式數據ORC格式寫入file


在flink中,StreamingFileSink是一個很重要的把流式數據寫入文件系統的sink,可以支持寫入行格式(json,csv等)的數據,以及列格式(orc、parquet)的數據。
hive作爲一個廣泛的數據存儲,而ORC作爲hive經過特殊優化的列式存儲格式,在hive的存儲格式中佔有很重要的地位。今天我們主要講一下使用StreamingFileSink將流式數據以ORC的格式寫入文件系統,這個功能是flink 1.11版本開始支持的。

StreamingFileSink簡介

StreamingFileSink提供了兩個靜態方法來構造相應的sink,forRowFormat用來構造寫入行格式數據的sink,forBulkFormat方法用來構造寫入列格式數據的sink,

我們看一下方法forBulkFormat。


	public static <IN> StreamingFileSink.DefaultBulkFormatBuilder<IN> forBulkFormat(
			final Path basePath, final BulkWriter.Factory<IN> writerFactory) {
		return new StreamingFileSink.DefaultBulkFormatBuilder<>(basePath, writerFactory, new DateTimeBucketAssigner<>());
	}

這裏需要兩個參數,第一個是一個寫入的路徑,第二個是一個用於創建writer的實現BulkWriter.Factory接口的工廠類。

寫入orc工廠類

首先我們要引入相應的pom


<dependency>
  <groupId>org.apache.flink</groupId>
  <artifactId>flink-orc_2.11</artifactId>
  <version>1.11.0</version>
</dependency>

flink爲我們提供了寫入orc格式的工廠類OrcBulkWriterFactory,我們簡單看下這個工廠類的一些變量。


@PublicEvolving
public class OrcBulkWriterFactory<T> implements BulkWriter.Factory<T> {

	private static final Path FIXED_PATH = new Path(".");

	private final Vectorizer<T> vectorizer;
	private final Properties writerProperties;
	private final Map<String, String> confMap;
	private OrcFile.WriterOptions writerOptions;
	
	public OrcBulkWriterFactory(Vectorizer<T> vectorizer) {
		this(vectorizer, new Configuration());
	}
	public OrcBulkWriterFactory(Vectorizer<T> vectorizer, Configuration configuration) {
		this(vectorizer, null, configuration);
	}
	public OrcBulkWriterFactory(Vectorizer<T> vectorizer, Properties writerProperties, Configuration configuration) {
        ...................
	}
    .............
}

向量化操作

flink使用了hive的VectorizedRowBatch來寫入ORC格式的數據,所以需要把輸入數據組織成VectorizedRowBatch對象,而這個轉換的功能就是由OrcBulkWriterFactory中的變量—也就是抽象類Vectorizer類完成的,主要實現的方法就是org.apache.flink.orc.vector.Vectorizer#vectorize方法。

  • 在flink中,提供了一個支持RowData輸入格式的RowDataVectorizer,在方法vectorize中,根據不同的類型,將輸入的RowData格式的數據轉成VectorizedRowBatch類型。

	@Override
	public void vectorize(RowData row, VectorizedRowBatch batch) {
		int rowId = batch.size++;
		for (int i = 0; i < row.getArity(); ++i) {
			setColumn(rowId, batch.cols[i], fieldTypes[i], row, i);
		}
	}

  • 如果用戶想將自己的輸入格式以orc格式寫入,那麼需要繼承抽象類Vectorizer,並且實現自己的轉換方法vectorize。

  • 如果用戶在寫入orc文件之後,想添加一些自己的元數據信息,可以覆蓋org.apache.flink.orc.vector.Vectorizer#addUserMetadata方法來添加相應的信息。

構造OrcBulkWriterFactory

工廠類一共提供了三個構造方法,我們看到最全的一個構造方法一共接受三個參數,第一個就是我們上面講到的Vectorizer對象,第二個是一個寫入orc格式的配置屬性,第三個是hadoop的配置文件.

寫入的配置來自https://orc.apache.org/docs/hive-config.html,具體可以是以下的值.

key 缺省值 註釋
orc.compress ZLIB high level compression = {NONE, ZLIB, SNAPPY}
orc.compress.size 262,144 compression chunk size
orc.stripe.size 67,108,864 memory buffer in bytes for writing
orc.row.index.stride 10,000 number of rows between index entries
orc.create.index true create indexes?
orc.bloom.filter.columns ”” comma separated list of column names
orc.bloom.filter.fpp 0.05 bloom filter false positive rate

實例講解

最後,我們通過一個簡單的實例來講解一下具體的使用。

構造source

首先我們自定義一個source,模擬生成RowData數據,我們這個也比較簡單,主要是生成了一個int和double類型的隨機數.


	public static class MySource implements SourceFunction<RowData>{
		@Override
		public void run(SourceContext<RowData> sourceContext) throws Exception{
			while (true){
				GenericRowData rowData = new GenericRowData(2);
				rowData.setField(0, (int) (Math.random() * 100));
				rowData.setField(1, Math.random() * 100);
				sourceContext.collect(rowData);
				Thread.sleep(10);
			}
		}
		@Override
		public void cancel(){

		}
	}

構造OrcBulkWriterFactory

接下來定義構造OrcBulkWriterFactory需要的參數。


		//寫入orc格式的屬性
		final Properties writerProps = new Properties();
		writerProps.setProperty("orc.compress", "LZ4");

		//定義類型和字段名
		LogicalType[] orcTypes = new LogicalType[]{new IntType(), new DoubleType()};
		String[] fields = new String[]{"a1", "b2"};
		TypeDescription typeDescription = OrcSplitReaderUtil.logicalTypeToOrcType(RowType.of(
				orcTypes,
				fields));

		//構造工廠類OrcBulkWriterFactory
		final OrcBulkWriterFactory<RowData> factory = new OrcBulkWriterFactory<>(
				new RowDataVectorizer(typeDescription.toString(), orcTypes),
				writerProps,
				new Configuration());

構造StreamingFileSink


		StreamingFileSink orcSink = StreamingFileSink
				.forBulkFormat(new Path("file:///tmp/aaaa"), factory)
				.build();

完整的代碼請參考:
https://github.com/zhangjun0x01/bigdata-examples/blob/master/flink/src/main/java/connectors/filesystem/StreamingWriteFileOrc.java

更多精彩內容,歡迎關注公衆號:【大數據技術與應用實戰】
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章