Google Millwheel
插曲
google millwheel 《MillWheel: Fault-Tolerant Stream Processing at Internet Scale》, 论文应该2012年就推出来了, 以前总是快速扫一遍, 每次阅读都有一些不同的收获, 这次终于仔细拜读一下, 顺便将它翻译了一遍。
设计目标
- 提供一种编程模型,可以满足复杂的计算逻辑而无需使用者是分布式计算专家
- framework能处理任何一条边或一个节点发生故障
- 可以保证数据处理仅被处理一次, 采用冥等的方式
- 用一种合适的粒度进行checkpoint, 从而可以避免外部sender 缓冲数据的buffer在多个checkpoint 之间长时间等待
- 能够同时高效满足scalability和容错性
- 按照论文描述, 可以支持多语言
个人总结:
这篇论文,大篇幅介绍的如何做容错和扩展性, 扩展性很多时候是依赖容错性来做系统伸缩。 整体而言,扩展性和容错性应该非常不错, 但成本比较高,因为对持久化层需求很大, 而且比较偏好mini-batch设计,非常倾向去做window的aggregate, 另外对这个系统时延,感觉会在秒级以上。微软scope streaming 感觉和这个系统有很大的相似性, 不过scope 比较强调确定性(determinacy)。 整个设计里面一些亮点: * 整个dag中,组件(compuation)之间是完全解耦, 因此,可以自由对一个computation做迁移,扩容,合并。不过,这些都依赖底层的exactly-once 框架。 * 系统数据传输都是通过rpc, 而非消息中间件, 并且组件(computation)之间可以自由订阅, 这一点超越了samza和scope。 * 数据结构是(key, bytes[], timestamp), 这个数据结构在后来的dataflow中发生了变化 * key 非常重要, 目前是对key 做group by, 相同的key保证在一个进程中串行执行, 并且每个用户自己写key-extractor 函数。 并且后续的所有操作/context,都是基于对应的key, 比如checkpoint,状态更新, 发送/更新 timer/low wwatermark。 * bytes[], 用户自己选择序列化和反序列化 * timestamp 完全由用户来确定, * exactly-once * 当timer 来到时, 会做checkpoint, 这个checkpoint, 会在一个原子操作中, 把这次checkpoint的输入数据id 和输出数据 和状态更新, timer 全部更新到bigtable 中的一行, 如果有外部状态更新,用户需要自己保证冥等 * 后台存储更新需要一个sequencer, 拥有了sequencer token后,才能做数据库更新操作, 保证一个key,永远只有一个single-writer。 * 接收数据后,需要ack给发送方, 这样发送方可以做 input record id的清理工作。 * 系统会对输入消息进行去重 * low watermark * 通过一个外部全局系统injector来做lower watermark, 会订阅injector 来获取lower watermark。 * 每个worker 从injector处获取输入源的low watermark,然后根据自己的工作状态,计算出自己的low watermark, 然后汇报给injector