探索flink计数功能,欢迎指正!!
使用场景:需要对经过算子处理后的DataStream中不同类型的数据进行全局统计个数(正解见第三种)
参考地址:https://ci.apache.org/projects/flink/flink-docs-stable/monitoring/metrics.html#datadog-orgapacheflinkmetricsdatadogdatadoghttpreporter
flink提供了一套指标,既可以定义自己的,也可以获取官方的,获取官方的指标(需要配置report以log的方式输出,怎么在程序中获取没有研究明白)。定义自己指标的方式:
public class MyMapper extends RichMapFunction {
private transient Counter counter;
@Override
public void open(Configuration config) {
this.counter = getRuntimeContext()
.getMetricGroup()
.counter("myCounter");
}
@Override
public String map(String value) throws Exception {
this.counter.inc();
return value;
}
}
inc代表增1,dec代表减1,但是这里的统计值是针对一个task的,也就是说统计值并不是全局的数值,不满足场景需求。换句话说如果我的一个job开启了3个task,那么这三个task的counter数量叠加才是我想要的数据。
参考地址:https://ci.apache.org/projects/flink/flink-docs-release-1.2/dev/api_concepts.html#accumulators–counters
Accumulators are simple constructs with an add operation and a final accumulated result, which is available after the job ended.
官方文档里面说,累加器只有在job结束以后才可以访问到,我们需要的是实时的数据统计,也不符合场景,但还是看一下是怎么实现的:
//首先定义一个counter
private IntCounter numLines = new IntCounter();
//然后将counter注册到系统累加器对象中,通常在open方法中实现
getRuntimeContext().addAccumulator("num-lines", this.numLines);
//然后数量加1
this.numLines.add(1);
//等到作业执行结束后,execute方法会返回一个JobExecutionResult对象,可以获取最终统计值
myJobExecutionResult.getAccumulatorResult("num-lines")
回想一下入门必备wordcount案例,给出一个word,程序可以在原先count值的基础上进行加1,然后得到最新的count统计值,根据这个思路,也可以实现一个不同类别的计数器
首先我们有上游已经处理完的一个DataStream,其中Object中有一个type属性就是分类的标准,需要实现的就是根据这个分类标准进行实时的统计数值。
DataStream> counts = yourObject.flatMap(new RichFlatMapFunction
这样可以在后台log中看到统计值,然后可根据需要从sink中进行存取。这样操作相当于是在原本流程中衍生的一条分支,并不会影响原本数据处理的operator和sink操作。
并发数设置为1是输出的log就是唯一的统计数值,但是如果考虑到数据量过大,单节点处理大量数据可能会比较吃力,可以加大并发数的设置,统计值还是全局的。
举了栗子,我有三个词语,word,word,word,两个并行节点处理,那么节点1收到第一个word1,打印“word,1”;节点二收到第二个打印“word,2”;不论哪个节点收到第三个word,都会打印“word,3”,保证了当前统计值是实时全局增加的。