流处理的容错

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情

本系列主要是《数据密集型应用系统设计》阅读笔记,本文记录流处理主题的笔记心得。

流处理的容错

批处理任务失败的时候可以直接重启并丢弃失败的输出。

批处理容错方法要确保批处理作业的输出和没有出错时的最终结果相同,即使中间某些情况失败了,看起来好像每个输入记录都恰好被记录了一次,没有记录被遗漏,也没有记录被处理两次。

这个被称为恰好一次语义。

但流处理也会出现同样的问题,但处理起来并不是那么简单:在输出结果可见之前等待某个任务完成是不可行的,由于流是有限的,因此几乎永远无法完成这个任务

微批处理

一种解决方案是将流分成许多小块,并像小型批处理一样处理每个块,每个小块的结果在处理完之前是可见的。已经用于Spark Streaming,批处理大小通常为1s,较小的批处理会导致更大的调度和协调开销,较大的意味着流处理器的结果需要更长的延迟也能可见。 微批处理隐含的设置了与批处理大小相等的轮转窗口,Flink使用了该方法的一个变体,定期生成状态滚动检查点并将其写入持久化存储,如果流操作发生奔溃,它可以从最近的检查点重新启动,并丢弃在上一个检查点和奔溃之间生成的所有输出。检查点是由消息流中的barrier触发,类似于微批处理之间的边界,但并不强制特定的窗口大小。

在流处理框架的范围内,微批处理和检查点点方法提供了与批处理一样的恰好一次语义。但是一旦脱离了流处理系统,比如写入数据库、发送电子邮件等,框架则无法丢弃失败处理等输出了。因为重试会导致外部的副作用。

原子提交

对于上面的问题,也是分布式事务中的传统问题,比如XA。 然而,在更受限制的环境中,有可能有效的实现这样的原子提交方法。Google Cloud Dataflow和VoltDB中使用了这种方法,Kafa也计划添加类似的功能。与XA不同,这些实现不会尝试在异构技术提供事务,而是通过在流处理框架中管理状态更改和消息传递来保持内部事务

幂等性

我们的目标是丢弃任何失败任务的部分输出,以便他们可以安全的重试而不会两次生效。分布式事务是实现这一目标的一种方法,而另一种方式则是依赖幂等性

幂等操作是可以多次执行的操作。并且它和只执行一次操作具有相同的效果,例如,将某个键的设置为某个固定值是幂等的,递增计数器则不受幂等的。 即使操作天生不是幂等的,往往也可以使用一些额外的元数据使其变得幂等。例如处理kafka的消息时,每条消息都有一个持久的、单调递增的偏移量。将值写入外部数据库的时候,可以在该值中写入这个偏移量。

故障后重建状态

基于窗口的聚合以及表和索引的join操作,都必须确保在故障发生后状态可恢复。

可以将状态数据保存在本地并定期进行复制。之后,当流处理从故障中恢复时,新任务可以读取副本的状态并进行恢复处理。

例如,Flink定期对操作状态执行快照,并写入HDFS。 Kafka Streams将状态变更发送到具有日志压缩功能的专用Kafka主题来保存状态的副本,这类似于变更数据捕获

猜你喜欢

转载自juejin.im/post/7110600708411359245