最近有这样需求,两个topic消息interval-join。
其中一个topic是,展示列表的详细信息(曝光),大约20分钟,有100G大小(主要从服务端发送);
另外一个topic是,用户操作列表(点击、下单),由前端发送,数据很少,大约10分钟几十M,action表示操作,
itemId表示方案的唯一标识符,time表示操作时间,unionId表示用户唯一标识符。
{"action":"click","itemId":"ce1e6cc4f6a09b058df716ff9b21f82b@TT@2","time":"1560272397","unionId":"ohmdTtxmXB0q-2_CuTNQ1v3YVKuo"}
两个topic的kafka
//详细信息,大消息流
DataStream<PlanClickBO> detailStream
//用户点击操作信息流
DataStream<PlanActionBO> clickStream
目的还原当时用户点击的方案详细信息,后续操作先不考虑。
假设服务端给一个用户发送50个展示方案,大约0-8分钟之内,用户会点击操作(超过8分钟的不考虑),根据itemId还原用户当时点击的方案的详细信息。
DataStream< String> joinStream = detailStream.keyBy(PlanClickBO::getItemId)
.intervalJoin(clickStream.keyBy(PlanActionBO::getItemId))
.between(seconds(-10), seconds(60*8))
.process(new ProcessJoinFunction<PlanClickBO, PlanActionBO, PlanClickBO>() {
@Override
public void processElement(PlanClickBO left, PlanActionBO right, Context ctx, Collector<PlanClickBO> out) throws Exception {
out.collect(left+":"+right);
}
});
因为采用窗口,需要配置State Backends
MemoryStateBackend
默认是MemoryStateBackend(内存的),但程序会偶尔task会丢失,造成重启,也会发生JM挂掉,Job平台自动重启,数据会丢失。
物理存储设置checkpoint,有FsStateBackend和RocksDBStateBackend这两方式。
FsStateBackend
FsStateBackend是全量的checkpoint,默认同步的,也支持异步。
设置方法很简单
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
FsStateBackend backend= new FsStateBackend(path, true);
env.setStateBackend((StateBackend)backend);
env.getCheckpointConfig().enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.DELETE_ON_CANCELLATION);
env.enableCheckpointing(1000*60);
但问题来,大消息detailStream数据太大了,而且缓存8分钟数据。每次checkpoint时间越来越长,开始大约10-20S,大约10G文件大小,到后面基本上超过10分钟(我这里集群配置checkpoint超时10分钟),
到后面checkpoint基本失效。
RocksDBStateBackend
异步chekcpoint,而且是增量更新,有compaction自动合并增量文件。
添加maven依赖
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-statebackend-rocksdb_