flink理论干货笔记(1)
8. 通过批处理来模拟流处理,会导致开发和运维相互交错,而且这种技术的潜在问题是,时间由系统中生成小批量作业的那一部分全权控制,spark streaming也不能完全避免,而且有糟糕的用户体验,说到底还是无法做到真实时,代码之外还需要大量性能调优。94. 阿里对flink的贡献(一): 重构了flink的分布式架构,将job调度和资源管理做了清晰的分层和解耦,使的flink可以跑在不同的资源管理
1. flink用同一种底层技术实现流处理和批处理
2. 除了低延迟和高吞吐,优秀的流处理技术还应该能在系统崩溃后重新启动,并且产生准确的结果。即可以容错以及保证exactly-once
3. 好的容错应该在没有数据错误的情况下没有太大的开销
4. 思考:flink能处理乱序事件流?怎么处理?还能够准确替换流数据?那不就是篡改数据?
5. 对比storm,尽管storm能低延迟,但难以实现高吞吐,且正确性无法满足需求,即不能保证exactly-once,开销也很大
6. 对比spark streaming,spark streaming将连续事件的流数据分割成一系列微小的批量作业(微批处理),能实现准实时(仅有几秒或几亚秒的延迟),且能实现exactly-once,以及失败重新运行
7. 注意,Strom Trident是对storm的延伸,它的底层引擎基于微批处理方法,也实现了exactly-once,但无法满足低延迟
8. 通过批处理来模拟流处理,会导致开发和运维相互交错,而且这种技术的潜在问题是,时间由系统中生成小批量作业的那一部分全权控制,spark streaming也不能完全避免,而且有糟糕的用户体验,说到底还是无法做到真实时,代码之外还需要大量性能调优。微批处理的灵活性和表现力都缺乏,开发速度慢,运维成本高
9. flink能解决微批处理的各种弊端,能按照连续事件高效处理数据。能同时满足高吞吐、低延迟、在压力下保持正确(即exactly-once)、操作简单/表现力好、时间正确/语义化窗口
10. lambda架构既保证了低延迟,又保证了正确性,它同时使用了mapreduce和storm,前者用于批处理,后者用于流处理。总体上说它还不够好,因为它有一个数小时的时间窗口,在这个窗口内,由于实时任务失败产生的不准确结果会一直存在。同时,需要两套API切换,难以维护。
11. flink将批处理(即处理有限的静态数据)看做一种特殊的流处理
12. flink runtime执行引擎是容错性数据流,是flink的核心构造。它是一个分布式系统,能够接受数据流程序并在一台或多台机器上以容错的方式执行。flink runtime可以跑在yarn或mesos上,当然单机也行,特别是调试的时候。
13. flink runtime之上是datastream api和dataset api,它们是面向用户的api,分别用于流处理和批处理。
14. datastream api之上是table api和cep api,分别用于处理结构化流数据,和复杂事件数据
15. dataset api之上是flinkml和gelly,分别用于机器学习和图计算
16. 问题:dataset api上能处理结构化流数据吗?或者说,table api是否也基于dataset api?
17. dataset api先于datastream api被开发出来,因为工业界一开始对无限流处理的需求不大
18. flink项目的架构一般包含两部分,消息传输层和流处理层,前者是kafka等,后者就是flink
19. 消息传输层是作为流处理层上游的安全队列,相当于缓冲区,能防止数据处理发生中断。kafka具有持久性、高性能,以及支持消息重播。这就允许flink对事件流的某一部分进行重播和再计算。
20. 消息传输层还支持从多个源(生产者)收集数据,并使这些数据给多个应用程序(消费者)使用。消费者订阅感兴趣的主题,意味着消息立即到达,但不需要立即处理。这种解耦的消息系统很有意义,添加生产者和消费者都很容易
21. flink可看成消息传输层(如kafka)的消费者
22. 流处理架构不需要集中式数据库,有消息队列就够了。流处理器(如flink)可以保障数据一致性
23. 欺诈监测可以从基于流处理的微服务架构中获益。我们仅仅通过分析刷卡速度这一特征就能理解很多问题,而不需要几百个特征。整个过程不需要访问传统数据库,因而更加高效且安全。
24. 流处理器(如flink)的正确性体现在计算窗口的定义符合数据产生的自然规律
25. 思考:处理框架能够将访问者行为分析的计算窗口和实际的访问时间段吻合到什么程度?或者说,计算窗口和会话窗口吻合吗?
26. 微批处理的计算窗口是人为设定的,很难与会话窗口吻合。而flink的流处理可以灵活定义计算窗口,能够使计算窗口和会话窗口吻合。比如开发者可以设置非活动阈值,若超过该值(如5分钟),就判断活动结束。这叫做开窗方式
27. 注意,时间的指定方式不止一种。将事件指定给某个窗口,可以采用事件时间或处理时间。
28. 一般不采用事件时间,最好两个时间都能找到,才能得到最佳的计算结果。与其他流处理系统相比,flink的一个优势是能区分不同类型的时间。
29. 若想计算保持准确,必须跟踪计算状态,哪怕是没有终点的计算过程,哪怕在故障发生之后。flink用检查点实现,记录中间计算状态,从而准确地重置。检查点技术使系统以低开销的方式拥有了容错能力。当一切正常,检查点对系统的影响也非常小。
30. 检查点也允许flink按需重新处理数据,而不一定要等系统发生故障。比如在修bug时,可能需要重算一遍来调试
31. flink的低延迟也间接可看成是一种正确性。因为有时候5秒钟延迟计算的结果也就没有意义了
32. 流处理和批处理最关键的区别是对时间的处理
33. 包括flink在内的所有现代流处理器,内部都使用了某种形式的微批处理技术,在shuffle阶段将含有多个事件的缓冲容器通过网络发送,而不是发送单个事件
34. 流处理中的批处理必须符合以下两点要求:
1). 批处理只作为提高系统性能的机制。批量越大,系统吞吐量越大。
2). 为提高性能而使用的批处理必须完全独立于定义窗口时所用的缓冲,或者为了保证容错性而提交的代码,且不能作为api的一部分。否则,系统将受限,且变得脆弱以及难以使用。
35. 应用开发者不需要考虑系统是否可以执行微批处理或如何执行,而只需要考虑系统是否能处理乱序事件流,以及不一致的窗口,是否在提供准确的聚合结果之外还能提供预警,是否可以重播历史数据,是否满足低延迟和高吞吐,是否能在发生故障时保证系统持续运行
36. 事件时间顺序和处理时间顺序可能不一致,这种也叫做乱序事件流
37. 摄取时间,也叫做进入时间,是事件进入流处理框架的时间,它是第三个时间概念。缺乏真实事件时间的数据一般会被附上时间戳,即流处理器第一次看到它的时间(该操作由source函数完成,是程序的第一个处理节点)
38. 事件时间和处理时间的偏差,也叫做事件时间偏差,通常由网络延迟、分布式系统时钟不同步、物理原因等因素导致。
39. 预警程序能容忍小误差,因此适合采用处理时间,而欺诈监测系统则对准确性有较高要求,因此适合采用事件时间
40. 时间窗口分为滚动和滑动。其中滑动是有部分重合的,比如每半分钟计算一次最近一分钟的数值总和。滚动是没有重合的,比如每分钟计算一次最近一分钟的总和。
41. 可见滚动比较简单,例如stream.timeWindow(Time.minutes(1));而滑动需要多个参数,例如stream.timeWindow(Time.minutes(1),Time.seconds(30))
42. 计数窗口的分组依据不再是时间戳,而是元素的数量。比如由4个元素组成的计数窗口,且每两个元素滑动一次。
43. 滚动和滑动的计数窗口定义可以是:stream.countWindow(4)和stream.countWindow(4,2)
44. 计数窗口不如时间窗口严谨,要谨慎使用。时间窗口总会关闭,但计数窗口可能永远不会关闭,比如某个key对应的元素永远到不了100,会导致内存浪费,可以用时间窗口触发超时
45. flink还支持会话窗口,通常没有固定的持续时间,也没有固定的交互次数。目前spark也支持会话窗口。
46. 会话窗口由超时时间设定,例如stream.window(SessionWindows.withGap(Time.minutes(5)))
47. 除了窗口,触发器也能控制生成结果的时间,即何时聚合窗口内容并将结果返回给用户。每个窗口都有一个触发器。比如时间窗口可以在收到水印时被触发。也可以自定义触发器,比如每秒提供一次近似结果
48. flink的所有窗口都由同一种机制实现。开窗机制和检查点机制完全分离。即窗口时长不依赖于检查点间隔。当然窗口也可以完全没有时长,比如计数和会话窗口。甚至可以基于基本的开窗机制来定义更加复杂的窗口形式
49. 流处理架构拥有时空穿梭的能力(即重新处理数据),用同一组数据重新运行同样的程序,会得到同样的结果
50. 为了追踪事件时间,需要依靠由数据驱动的时钟,而不是系统时钟
51. flink通过水印来推进事件时间。水印是嵌在流中的常规记录,程序通过水印获知某个时间点的到达。
52. 水印使事件时间和处理时间完全无关。迟到的水印(迟到是从处理时间而言)并不会影响结果的正确性,而只会影响收到结果的速度。
53. 思考:水印就是事件时间?水印就是记录的时间戳?
54. flink的水印由开发人员生成,且需要对领域有了解。完美的水印永远不会错。启发式水印只估计时间,因此可能出错,即时间戳小于水印时间的事件可能晚于水印出现。针对启发式水印,flink有相关处理机制。
55. 可以采用一个flink作业监控事件流,学习事件的迟到规律,并以此构建水印生成模型
56. 如果水印迟到太久,可以在到达之前输出近似结果(flink支持)。如果水印到达太早,flink也能解决。
57. 水印是唯一让我们直面乱序事件流并保证正确性的机制
58. kappa架构即流处理架构,数据流是设计核心,数据源不可变更。
59. 流计算分为无状态和有状态两种情况。计算过去一小时的平均温度就是有状态。一分钟内收到两个相差20度以上的温度则发出警告,也是有状态。流与流之间的所有关联操作,流与静态表或动态表的关联操作,也是有状态。
60. 无状态每次只根据最新输入来得到输出。而有状态需要维护所有已处理记录的状态,再根据每条新输入记录来更新状态,因此输出是综合考虑多个事件的结果
61. 有状态比无状态难很多,新一代流处理系统主要处理有状态。
62. 分布式系统引入有状态,要考虑一致性问题,分为3个级别,at-most-once、at-least-once、exactly-once
63. storm Trident和spark streaming为了保证exactly-once,付出了很大的代价,它们无法对每条记录单独应用逻辑,而只能应用于批,即一批要么全部成功或全部失败,导致等待时间过长,然后要么忍受高延迟,要么使用两个流处理框架,以至于构造复杂,效率低下。而flink就不需要,它既保证了exactly-once,又具有低延迟和高吞吐
64. flink利用检查点来保证exactly-once,检查点就像数项链上的珠子时系上的皮筋。检查点是flink最重要的创新之一,它既保证了exactly-once,又没有牺牲性能。
65. flink中有状态的map算子是mapWithState,它有两个参数,当前输入in和历史总和count
66. 检查点屏障和普通记录类似,它们由算子处理,但不参与计算,而是会触发和检查点相关的行为。
67. 当读到检查点屏障时,比如由keyBy算子读到,会将其在输入流中的位置保存到稳定存储中,比如将kafka的偏移量保存起来,具体保存到hdfs或s3等等。
68. 注意,检查点屏障和检查点是不一样的概念,前者类似记录,后者是更全局的概念。一个检查点包括了检查点屏障的位置备份和其他所有算子的状态备份。检查点屏障是检查点这个快照的发生时间点。
69. 检查点操作的速度由稳定存储的可用带宽决定。未来flink甚至可以只保存状态的变化,而不保存状态的值,这样能使开销更小。
70. 如果检查点操作失败,flink会丢弃该检查点并继续正常执行,因为后续的检查点可能会成功。虽然恢复时间可能更长,但对于状态的保证依旧很有力。只有一系列连续的检查点失败后,flink才会抛出错误,因为这通常意味着发生了严重且持久的错误。
71. 当故障发生在检查点之后,flink会重建拓扑,可能获取新的资源,将输入流倒回到上一个检查点,然后恢复状态值并从该处继续计算。
72. flink的检查点算法叫做异步屏障快照。该算法大致基于Chandy-Lamport分布式快照算法。
73. 检查点由flink自动生成,而保存点是flink用户有意识地管理状态版本,由命令行或web控制台手动触发,而不是自动触发。
74. 保存点也被保存在稳定存储中,与检查点工作方式完全相同。
75. 可以从保存点重启作业,保存点可看成作业在某一时刻的快照,该时刻即为保存点被触发的时刻
76. 保存点保存应用程序状态的版本,和版本控制系统保存应用程序的版本很相似
77. 从保存点重启,可以使用被修改过的程序版本,且两个版本可以同时运行,相当于有了多个分支。
78. 保存点主要作用:
1) 应用程序代码升级,如修复bug 2) flink版本更新 3) 集群维护和迁移 4) 假设模拟和恢复 5) A/B测试
79. flink检查点本质上是一个可持续升级状态版本的可编程机制
80. flink内部的检查点机制以保存点的形式呈现给用户
81. 如何保证端到端一致性,即exactly-once,有两种方法:
1) 在sink环节缓存所有输出,在sink收到检查点记录时,将输出“原子提交”到存储系统。从而保证不会出现重复数据。事实上,输出存储系统会参与flink的检查点操作。
2) 急切地将数据写入输出存储系统,同时牢记数据可能是脏的,且需要在发生故障时回滚。若回滚,就会将脏数据覆盖或者删除。这种方式会导致脏数据短暂存在。
82. 以上两个方案正好对应关系数据库中为人所知的事务隔离级别:已提交读和未提交读。
83. 对于输出存储系统的不同类别,flink可以选择不同隔离级别,与对应的连接器配合,来一起保证端到端的一致性
84. 批处理可看成一种特殊的流处理。有限流可看成无限流的一种特殊情况。
85. 批处理中,只有一个全局窗口,所有记录都属于同一个窗口。
86. 以下是流处理
val counts=visit
.keyBy("region")
.timeWindow(Time.hours(1))
.sum("visits")
87. 以下是批处理
val counts=visit
. keyBy("region")
. window(GlobalWindows.create)
. trigger(EndOfTimeTrigger.create)
. sum("visits")
88. 以下用dataset api实现批处理
val counts=visits
. groupBy("region")
. sum("visits")
比上一段代码更友好
89. flink的流处理引擎之上有以下机制:检查点机制和状态机制、水印机制、窗口和触发器
90. flink还有另一套用于批处理的机制:用于调度和恢复的回溯法、用于散列和排序的特殊内存数据结构、优化器
91. 即便是批处理器所擅长的任务,流处理器(flink)在适当优化后也仍旧表现得一样好,甚至更好
92. 阿里的搜索、推荐,甚至所有业务,包括子公司,都基于flink搭建实时计算平台。当然还通过阿里云的云平台api,向开发者提供云产品支持。
93. Chandy-Lamport算法的核心思想是,把流计算看成一个流式的拓扑,定期在这个拓扑的头部插入特殊的barriers,从上游不断往下游广播这个barriers,每个节点会收到所有的barriers,这时将所有状态做一次快照,每个节点都完成后,就得到了一个checkpoint(思考:为啥是广播,为啥是定期? )
94. 阿里对flink的贡献(一): 重构了flink的分布式架构,将job调度和资源管理做了清晰的分层和解耦,使的flink可以跑在不同的资源管理器上,如yarn和k8s,并将任务调度从集中式改为分布式,可以支持更大规模的集群,和更好的资源隔离。
95. 阿里对flink的贡献(二): 实现了增量checkpoint机制,只将修改的数据进行持久化,不会随着时间的推移而越来越大,或越来越难做,性能也更加平稳
96. 阿里对flink的贡献(三): flink的api stack统一,即不再区分datastream和dataset。目前没解决?
97. 阿里对flink的贡献(四): flink的上层sql方案统一,可以将流批的数据源都看成数据表,其中流的源是不断更新的表,而批的源是相对静止的表,即没有更新。整个数据处理可看成sql的一个query,结果也可以模拟成结果表。目前解决了?
98. flink未来的发展方向是多语言支持如python、go等,以及完善flink的ML库、集成深度学习,如tf on flink等
99. 在滴滴,轨迹数据、订单数据、交易数据、埋点数据、日志数据,都选择flink作为流计算统一入口
100. 滴滴内部对flink做了以下改进:
1) 流计算平台化和服务化
2) 限制每个yarn session只能提交一个job
3) 提供支持动态扩容的新特性,即flink application在重启的时候,资源不被释放,而是重新利用,避免了业务延迟
4) 解决了zk抖动导致获取不到检查点id的问题,修复了该bug
更多推荐
所有评论(0)