在流计算中,我们一般会选择 Storm、Spark、Flink 等计算框架,而对消息队列的选则 一般是Rabbitmq、Kafka 等,本片文章我们主要介绍 Kafka + Flink 框架在流计算中所遇到的问题及解决方案。
先聊下一个很古老的问题,Flink 消费Kafka中的数据,Kafka 有好几个分区,而如何保证Flink按顺序消费呢?(说详细一点儿:假设 Kafka topic 的分区为 8 个,生产者向Kakfa 发送数据,这些数据会均匀分布在这 8个分区中,而Flink消费Kafka中的数据时,如何保证消费的顺序就是按照生产者生产的顺序进行消费呢?),这个问题我们很久之前就在讨论,最终的结论是无法在消费者端保证顺序消费(这里Kafka的分区不为1),但我们可以在Kafka的生产端实现让同一特征数据分布在同一个分区里面,从而保证在消费端对这一特征数据顺序消费。而现在我们讨论一下如何在消费端尽量的保证顺序消费。
思路如下:
在Spark 、Flink 等计算框架中的窗口函数可以很好的实现这一问题(但只是让数据更加精确一点儿),我们利用Flink 的窗口函数,让一段时间内的数据落在同一窗口内,然后对这个窗口内的数据按照时间排序,然后在进行计算,但是在实际生产中我们又会遇到迟到的数据,此时我们的窗口时间又不能太长,而对于迟到的数据该如何监控、我们又该如何解决这些迟到的数据呢 ?在 Flink 计算框架中 解决了这一问题,现在我们来看下具体的代码实现 (若有更好的解决方案,希望读者能够留言探讨)。
举一个我在生产中的一个简单的案例:
/**
* @Description 业务逻辑处理
* @param stream
*/
private def businessLogic(stream: DataStream[String]): Unit = {
val dataStream = stream.filter(_.nonEmpty).map(line => {
val record = JSON.parseObject(line)
val time = record.getString("query.$time")
val preEvent = record.getString("query.$event")
val preIp = record.getString("clientIP")
val preProject = record.getString("query.$project")
(time, preEvent, preIp, preProject)
})
val watermarkStream = dataStream.assignTimestampsAndWatermarks(new MyTimestampsAndWatermarks)
val outPutTag = new OutputTag[

本文详细介绍如何在Flink流计算中确保从Kafka有序消费,通过使用窗口函数和定制timestamp/watermarks处理迟到数据。实例展示了如何在业务逻辑中应用这些技术,并探讨了迟到数据的监控与处理策略。
最低0.47元/天 解锁文章
1123

被折叠的 条评论
为什么被折叠?



