这一节,我们将讨论在节点错误事件时Spark Streaming的行为。为了理解这些,让我们先记住一些Spark RDD的基本容错语义。
Spark运行在像HDFS或S3等容错系统的数据上。因此,任何从容错数据而来的RDD都是容错的。然而,这不是在Spark Streaming的情况下,因为Spark Streaming的数据大部分情况下是从网络中得到的。为了获得生成的RDD相同的容错属性,接收的数据需要重复保存在worker node的多个Spark executor上(默认的复制因子是2),这导致了当出现错误事件时,有两类数据需要被恢复
有两种错误我们需要关心
如果所有的输入数据都存在于一个容错的文件系统如HDFS,Spark Streaming总可以从任何错误中恢复并且执行所有数据。这给出了一个恰好一次(exactly-once)语义,即无论发生什么故障,所有的数据都将会恰好处理一次。
对于基于receiver的输入源,容错的语义既依赖于故障的情形也依赖于receiver的类型。正如之前讨论的,有两种类型的receiver
选择哪种类型的receiver依赖于这些语义。如果一个worker节点出现故障,Reliable Receiver不会丢失数据,Unreliable Receiver会丢失接收了但是没有复制的数据。如果driver节点出现故障,除了以上情况下的数据丢失,所有过去接收并复制到内存中的数据都会丢失,这会影响有状态transformation的结果。
为了避免丢失过去接收的数据,Spark 1.2引入了一个实验性的特征write ahead logs
,它保存接收的数据到容错存储系统中。有了write ahead logs
和Reliable Receiver,我们可以做到零数据丢失以及exactly-once语义。
下面的表格总结了错误语义:
Deployment Scenario | Worker Failure | Driver Failure |
---|---|---|
Spark 1.1 或者更早, 没有write ahead log的Spark 1.2 | 在Unreliable Receiver情况下缓冲数据丢失;在Reliable Receiver和文件的情况下,零数据丢失 | 在Unreliable Receiver情况下缓冲数据丢失;在所有receiver情况下,过去的数据丢失;在文件的情况下,零数据丢失 |
带有write ahead log的Spark 1.2 | 在Reliable Receiver和文件的情况下,零数据丢失 | 在Reliable Receiver和文件的情况下,零数据丢失 |
根据其确定操作的谱系,所有数据都被建模成了RDD,所有的重新计算都会产生同样的结果。所有的DStream transformation都有exactly-once语义。那就是说,即使某个worker节点出现故障,最终的转换结果都是一样。然而,输出操作(如foreachRDD
)具有at-least once
语义,那就是说,在有worker事件故障的情况下,变换后的数据可能被写入到一个外部实体不止一次。利用saveAs***Files
将数据保存到HDFS中的情况下,以上写多次是能够被接受的(因为文件会被相同的数据覆盖)。