需求:
用BucketingSink进行分桶sink,按照event time每小时一个分桶,即一个文件夹,方便Hive查询
文件分桶说明
- 在每个分桶文件夹内有若干文件,文件名为
_part-8-0.in-progress
或_part-81-0.pending
或part-8-0
,分别代表处于in-progress
、pending
和finish
状态。 - 文件关闭后就由
in-progress
转变到pending
,关闭的条件是多久没有往文件中写入数据了,通过setInactiveBucketThreshold()
设置,默认1分钟,检查这个条件的周期间隔由setInactiveBucketCheckInterval
设置。 part-8-0
中横线分隔的第二个数字由并发度决定,100个并发度的话这个数字就从0到99part-8-0
中横线分隔的第三个数字代表这个并发算子(slot,就是中间的8)写个多少个文件了,切分新文件的条件有两个:- 写入文件尺寸达到一定的量,由
setBatchSize(1024 * 1024 * 500); // this is 500M
设置 - 文件写入了一定时间,由
setBatchRolloverInterval(20 * 60 * 1000); // this is 20 mins
设置
- 写入文件尺寸达到一定的量,由
- 文件由
pending
转变为finish
由checkpoint触发
checkpoint不设置state的保存位置的话默认在JobManager的内存里保存,很快就撑爆,所以要通过配置文件改到hdfs上,新的checkpoint文件生成后会自动删除旧的。
配置 checkpoint
flink-conf
state.backend: filesystem
state.checkpoints.dir: hdfs://hdfs-host/tmp/flink-checkpoints
设置 BucketingSink 的代码
DataStream<Tuple4<String, String, String, String>> input = ...
BucketingSink<Tuple4<String, String, String, String>> bucketingSink
= new BucketingSink<>("hdfs://hdfs-host/sink-location");
bucketingSink.setBucketer(new HourBucketer());
bucketingSink.setWriter(new Tuple4Writer());
bucketingSink.setBatchSize(1024 * 1024 * 500); // 500M 一个文件
sink.setInactiveBucketCheckInterval(1000); // 1秒钟检查一次多久没有写入了,用于判断是否从 in-progress 转变为 pending
sink.setInactiveBucketThreshold(1000); // 多久不写入就从 in-progress 转变为 pending
input.addSink(BucketingSink);