Apache Flink 学习:实时场景下的应用
用户需求场景
用户想要查看 版本,机型,国家,城市 等等维度下按照分钟的时间粒度的设备活跃,新增设备数,首次活跃设备数
用户需求->架构方案设计
数据所处阶段 | 功能描述 |
---|---|
数据source | 各种各样的打到kafka的用户行为数据的日志 |
数据process | 实时引擎消费kafka,根据数据服务化提供的接口判断当前用户是否是新增,活跃,首次活跃,将用户的相关数据打到下游kafka |
数据sink | 结果kafka |
olap引擎 | 消费sink kafka |
数据产品 | 通过BI等的产品呈现给用户 |
架构设计->选择实时计算引擎
为什么使用flink:
A.保证消费一次:checkpoint和savepoint 容错
B.时间属性:事件,注入,处理时间
优点:事件时间的属性可以被广泛应用,比如一般的分析场景都是分析用户某个时间段的用户相关指标,而不是事件处理某个时间段的用户相关指标
flink实现方案
第一种方案
方案
新增场景下,每消费一条source kafka用户数据就判断一次是否为新增,判断方式可以选择自己维护历史全量数据,或者使用数据服务化提供的接口,最后将结果写入sink kafka
存在的问题
数据处理阶段 | 问题 | 结果(仅仅指当前问题会产生的结果) | 是否可解决 |
---|---|---|---|
数据source | 同一个用户的行为数据到达时间间隔很小,几秒内就可能会产生几十条行为日志,判断是否为新增,活跃用户时可能会被重复判断 | 最终数据结果>真实结果 | 可部分解决 |
数据process | 自己维护全量数据 1.每判断一条就更新历史全量数据就不存在问题 2.如果历史全量数据更新有问题就会产生和数据服务化一样的下面两种问题 |
可部分解决 | |
数据process | 数据服务化维护全量数据且更新不及时 在新增的场景下,一个新增用户使用app可能会在短时间内上报成百上千条行为日志,如果第一条数据判断出来这个用户是新增,下一条数据判断时,数据服务化提供的全量用户里还没有及时将这条新增用户数据添加进去,则这条数据也会被判断为新增,就会导致最终结果重复 |
最终数据结果>真实结果 | 可部分解决 |
数据process | 数据服务化维护全量数据且更新过快 数据服务化更新速度快于flink消费source kafka的速度:就会导致本来是新增的设备被判断不是新增,导致最终结果漏判 |
最终数据结果<真实结果 | 暂时无法解决 |
解决方案
后续解决方法只讨论上述可部分解决的问题
数据处理阶段 | 问题 | 解决方案 |
---|---|---|
数据source | 同一个用户的行为数据到达时间间隔很小,可能会被重复判断 | 使用flink窗口解决部分问题 使用滚动窗口解决,将一段时间内的用户行为收集,然后到达窗口结束时间处理后再进行上报。假设设置一小时的窗口,则将这一小时的用户行为数据只取一条进行判断是否为新增,则可以极大的保证当前用户判断为新增时,下一小时窗口中这个用户不太可能被判断为新增了,因为数据服务化没有那么慢 |
数据process | 数据服务化维护全量数据且更新不及时,最终结果重复 |
第一种方案->第二种方案
方案
使用窗口可以部分解决在新增活跃等场景下用户行为数据重复的问题
但是使用了窗口也会引入问题,就是虽然大窗口可以保证尽可能去重,但是数据的实时性大大降低,所以窗口设置不能大也不能小,窗口大保证不了数据产出及时性,窗口小去重效果差,所以最大窗口就为一分钟,和用户期望看板中结果一致
存在的问题
数据处理阶段 | 问题 | 结果(仅仅指当前问题会产生的结果) | 是否可解决 |
---|---|---|---|
数据source | 由于用户行为数据到达source,或者从source到达process阶段,由于网络延迟等的问题,会导致处理用户数据时有乱序情况 比如计算实时活跃设备,上一分钟的数据如果下一分钟才到达,则该条数据就会被上一分钟漏算 |
最终数据结果<真实结果 | 可部分解决 |
数据process |
解决方案
数据处理阶段 | 问题 | 解决方案 |
---|---|---|
数据source | 数据乱序延迟漏算 | 在flink窗口计算中,通过timestamp和watermark特性来尽可能解决 |
数据process |
第二种方案->第三种方案
方案
设置一分钟的窗口,然后设置一分钟的最大延迟等待时间,其语义是保证数据最多延迟一分钟到达,只要可以保证这个语义可以保证最后数据的正确性