【问题标题】:Calculate totals and emit periodically in flink在 flink 中计算总数并定期发出
【发布时间】:2018-04-03 17:18:13
【问题描述】:

我有一个关于资源的事件流,如下所示:

id, type,      count
1,  view,      1
1,  download,  3
2,  view,      1
3,  view,      1
1,  download,  2
3,  view,      1

我正在尝试为每个资源生成统计信息(总计),所以如果我得到一个像上面这样的流,结果应该是:

id, views, downloads
1,  1,     5
2,  1,     0
3,  2,     0

现在我写了一个 ProcessFunction 来计算总数,如下所示:

public class CountTotals extends ProcessFunction<Event, ResourceTotals> {
    private ValueState<ResourceTotals> totalsState;

    @Override
    public void open(Configuration config) throws Exception {
        ValueStateDescriptor<ResourceTotals> totalsDescriptor = new ValueStateDescriptor<>("totals state", ResourceTotals.class);
        totalsDescriptor.setQueryable("resource-totals");
        totalsState = getRuntimeContext().getState(totalsDescriptor);
    }

    @Override
    public void processElement(Event event, Context ctx, Collector<ResourceTotals> out) throws Exception {
        ResourceTotals totals = totalsState.value();
        if (totals == null) {
            totals = new ResourceTotals();
            totals.id = event.id;
        }
        switch (event.type) {
            case "view":
                totals.views += event.count;
                break;
            case "download":
                totals.downloads += event.count;
        }
        totalsState.update(totals);
        out.collect(totals);
    }
}

从代码中可以看出,它会为每个事件发出一个新的 ResourceTotals,但我希望每分钟发出一次每个资源的总数,而不是更频繁。

我尝试使用全局窗口和触发器 (ContinuousProcessingTimeTrigger) 进行试验,但无法使其工作。我遇到的问题是:

  1. 如何表达我想要窗口的最后一个事件?
  2. 如何不最终存储在该全局窗口中生成的所有 ResourceTotals?

任何帮助将不胜感激。

【问题讨论】:

    标签: java apache-flink flink-streaming stream-processing


    【解决方案1】:

    您可以使用计时器每分钟发出一次 totalsState 中的值。由于我在您的数据流中看不到任何时间戳,我想您会使用处理时间计时器。

    另一种方法是将 ProcessFunction 替换为 TimeWindow 以及保留最后一个事件的 ReduceFunction

    在任何一种情况下,您都可以考虑通过 ID 和类型字段来键入流,这应该会稍微简化您的状态管理。

    更新:

    是的,计时器是 Flink 检查点和恢复状态的一部分。

    【讨论】:

    • 与时间窗口一起走,最后减少。似乎比杂耍计时器更简单。就像大多数好东西一样——一旦有人指出它就很明显了。谢谢你。我实际上有可用的活动时间并且正在使用它,但没有提及它。关于使用计时器,您知道注册的计时器是否被视为状态的一部分(在检查/保存点中持久化)?同样在reduce函数中,value1总是早于value2还是没有这样的保证?
    • 感谢您的更新。在我的特定情况下,无序到达的事件并不是真正的问题,因为操作是幂等的(我只是添加到总数中)。所以在我的 reduce 函数中,我只选择组合总数更高的元素。我的整个管道看起来有点像 events -&gt; process(CountTotals) -&gt; timeWindow(1 minute) -&gt; reduce(pick value with highest total) 希望这有点道理。
    猜你喜欢
    • 1970-01-01
    • 2023-01-10
    • 1970-01-01
    • 2011-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-22
    • 2013-02-25
    相关资源
    最近更新 更多