Flink的计数功能探索

探索flink计数功能,欢迎指正!!

使用场景:需要对经过算子处理后的DataStream中不同类型的数据进行全局统计个数(正解见第三种)

1.Metric

参考地址: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数量叠加才是我想要的数据。

2.Accumulators & Counters

参考地址: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")

3.keyBy+sum算子

回想一下入门必备wordcount案例,给出一个word,程序可以在原先count值的基础上进行加1,然后得到最新的count统计值,根据这个思路,也可以实现一个不同类别的计数器

首先我们有上游已经处理完的一个DataStream,其中Object中有一个type属性就是分类的标准,需要实现的就是根据这个分类标准进行实时的统计数值。

DataStream> counts  = yourObject.flatMap(new RichFlatMapFunction>(){
            @Override
            public void flatMap(Object object, Collector> collector) throws Exception {

                collector.collect(new Tuple2(obejct.getType(),1L));
            }
        }).keyBy(0).sum(1);

        counts.addSink(new SinkFunction>() {
         
            @Override
            public void invoke(Tuple2 value) throws Exception {
               
                LOG.info("count, key={}, value={}", value.f0, value.f1);
            }
        }).setParallelism(1);

这样可以在后台log中看到统计值,然后可根据需要从sink中进行存取。这样操作相当于是在原本流程中衍生的一条分支,并不会影响原本数据处理的operator和sink操作。

并发数设置为1是输出的log就是唯一的统计数值,但是如果考虑到数据量过大,单节点处理大量数据可能会比较吃力,可以加大并发数的设置,统计值还是全局的。

举了栗子,我有三个词语,word,word,word,两个并行节点处理,那么节点1收到第一个word1,打印“word,1”;节点二收到第二个打印“word,2”;不论哪个节点收到第三个word,都会打印“word,3”,保证了当前统计值是实时全局增加的。

你可能感兴趣的:(flink)