对于游戏行业来说,游戏的日活跃玩家数是个很常见的指标,游戏策划或者运营通常可以根据日活跃玩家数的变动来实时地监控某个活动是否收到玩家欢迎的程度,但是游戏可能有海外服务器,数据收集的延迟可能差别较大,造成数据流 event time 乱序比较严重,在这种情况下设计 Watermark 算法是个比较大的挑战 。
假设我们有 A、B、C 共 3 台服务器,其中 A、B 为国内服务器,延迟较低且稳定,而 C 为海外服务器,延迟较高且不稳定,而我们需要计算每分钟内的登录玩家数 。
文章插图
我们现在面临两种可能带来 event time 乱序的因素:一是不同服务器间的延迟不同,比如可能先收到服务器 A 在 t2 的数据,再收到服务 C 在 t1 的数据;二是同一服务器的不同数据的延迟不同,比如可能先收到服务器 C t2 的数据再收到 t1 的数据 。针对第二种因素,我们可以对不同服务器的数据分别计算 Watermark,再取其中的最小值作为 Watermark,而针对第一种因素,我们则需要设计出针对单个服务器数据流的合理 Watermark 算法 。
在算法实现上,Flink 提供两种触发 Watermark 更新的方法,即在收到特殊的消息时触发或者定时触发,我们这里将选用定时触发的方法 。因为窗口是一分钟比较小,我们这里将定时的间隔设为 5 秒,也就是说 Watermark 大约落后真实 Watermark 5 秒,然后这 5 秒内 Watermark 是不会提升的,所以可以容忍局部的 processing lag 。
我们试着取目前为止观察到的最大时间戳作为 Watermark,那么 Watermark 的效果如下(为了在消费端更加直观,我们将坐标系调转,现在 x 轴表示 processing time) 。
文章插图
其中 t0-t3 分别表示 Watermark 提升的时间点,黄虚线表示在一个 Watermark 周期内的最大 event time,红线表示 Watermark 。可以看到在 t0-t1 的 Watermark 周期内出现了轻微的 event time 乱序,但是并不影响计算的准确性 。接下来在 t1-t2 和 t2-t3 两个周期间也发生了相似的乱序,但是这个乱序并不在同一个 Watermark 周期,因此导致正常延迟的数据被误认为是迟到数据 。解决方法是引入一定可容忍的 event time skew,比如说最简单的设置一个 skew 阈值,即每次计算 Watermark 的结果都减去这个值 。根据数据流延迟的不同,我们还可以给不同服务器设置不同的 skew 阈值 。
上述 Watermark 算法代码如下:
public class WatermarkProcessor implements AssignerWithPeriodicWatermarks<UserLogin> {private static final long ALLOWED_EVENT_TIME_SKEW = 1000L;private static final Map<String, Long> maxTimestampPerServer = new HashMap<>(3);@Nullablepublic Watermark getCurrentWatermark() {Optional<Long> maxTimestamp= maxTimestampPerServer.values().stream().min(Comparator.comparingLong(Long::valueOf));if (maxTimestamp.isPresent()) {return new Watermark(maxTimestamp.get() - ALLOWED_EVENT_TIME_SKEW);} else{return null;}}public long extractTimestamp(UserLogin userLogin, long previousElementTimestamp) {String server = userLogin.getServer();long eventTime = userLogin.getEventTime();if (!maxTimestampPerServer.containsKey(server) ||userLogin.getEventTime() > maxTimestampPerServer.get(server)) {maxTimestampPerServer.put(server, eventTime);}return eventTime;}}
总结流计算和批处理谁是表达能力更强的计算模式,这个问题或许还将继续被争论下去,不过根据 The Dataflow Model 我们已经有足够的理论支撑来开发低延迟高准确并且可容错的流计算应用 。其中流计算的准确性很大程度上决定于数据流时间的乱序程度,因此我们在开发实时流计算应用时,比起开发离线批处理应用,很大的一个不同是要考虑数据是以什么顺序到达,并针对性地设计 Watermark 算法来处理数据流时间的乱序 。Watermark 算法需要平衡低延迟和高准确性两者,在引入最低延迟成本的情况下准确判断窗口的计算和输出结果的时机,通常可以从 processing lag 和 event time skew 两者的容忍阈值入手 。【深入理解流计算中的 Watermark】
推荐阅读
- 企业遭到黑客攻击怎么处理,应急响应的整体思路和基本流程
- Fyne - Go语言的跨平台UI工具包
- RTMP/HLS/HTTP-FLV流媒体服务器分析
- Masonry 纯CSS实现瀑布流
- 私域流量的真相
- 更多的主流浏览器支持IPFS,应用生态的不断发展推升Filecoin价值
- 电影|国产科幻神作!电影《流浪地球2》青岛部分杀青 吴京、刘德华主演
- 百度seo流量浮动,网站到底该如何应对?
- Skywalking流程简析及源码调试
- 英格兰|魔兽世界:WLK版本为何25人团本是辅助,10人团本才是主流?