Spark Streaming的一大优势在于它提供了强大的容错性保障。只要输入数据存储在可靠的系统中,Spark Streaming就可以根据输入计算出正确的结果,提供“精确一次”执行的语义。

检查点机制

检查点机制是我们在SparkStreaming中用来保障容错性的主要机制。它可以使SparStreaming阶段性地把应用数据存储到诸如HDFS或AmazonS3这样的可靠存储系统中以供恢复时使用。具体来说,检查点机制主要为以下两个目的服务。
●控制发生失败时需要重算的状态数。
提供驱动器程序容错。如果流计算应用中的驱动器程序崩溃了,你可以重启驱动器程月并让驱动器程序从检查点恢复,这样Spark Streaming就可以读取之前运行的程序处玛数据的进度,并从那里继续 。
        出于这些原因,检查点机制对于任何生产环境中的流计算应用都至关重要。你可以通过后SSC. checkpoint()方法传递一一个路径参数(HDFS、 S3或者本地路径均可)来配置检查点机制。
例:配置检查点
ssc.checkpoint("hdfs://...")
注意,  即便是在本地模式下,如果你尝试运行一个有状态操作而没有打开检查点机制,treaming也会给出提示。此时,你需要使用一个本地文件系统中的路径来打开检查点。

驱动器容错

驱动器程序的容错要求我们以特殊的方式创建StreamingContext.我们需要把检查点目录提供给StreamningConext。与直接调用new StreaningContext不同, 应该使用StreaningContext.getOrCreate()函数。
//用Java配置一个可以从错误中恢复的驱动器程序
JavaStreamingContextFactory fact = new JavaStreamingContextFactory() {
    public JavaStreamingContext call() {
        
        JavaSparkContext sc = new JavaSparkContext(conf);//以1秒作为批次大小创建StreamingContext
        JavaStreamingContext jssc = new JavaStreamingContext(sc, Durations.seconds(1));
        jssc.checkpoint(checkpointDir);
        return jssc;
    }};
JavaStreamingContext jssc = JavaStreamingContext.getOrCreate(checkpointDir, fact);
当这段代码第次运行时,假设检查点目录还不存在,那么StreamingContext会在你调用工厂函数(在Scala中为createStreamingContext(),在Java中为JavaStreaningContextFactory())时把目录创建出来。此处你需要设置检查点目录。在驱动器程序失败之后,如果你重启驱动器程序并再次执行代码,getOrCreate() 会重新从检查点目录中初始化出StreamingContext,然后继续处理。

 工作节点容错

      为了应对工作节点失败的问题,Spark Streaming使用与Spark的容错机制相同的方法。所有从外部数据源中收到的数据都在多个工作节点上备份。所有从备份数据转化操作的过程中创建出来的RDD都能容忍一个工作节点的失败,因为根据RDD谱系图,系统可以把丢失的数据从幸存的输人数据备份中重算出来。

接收器容错

接收器提供以下保证:
      ●所有从可靠文件系统中读取的数据(比如通过StreamingContext.hadopFiles读取的)都是可靠的,因为底层的文件系统是有备份的。Spark Streaming会记住哪些数据存放到了检查点中,并在应用崩溃后从检查点处继续执行
        对于像Kafka、Flume、Twitter 这样的不可靠教据源,Spark会把输入数据复制到其它节点上,但是如果接收器任务崩溃,Spark还是会丢失数据。

处理保证

        由于Spark Streaming工作节点的容错保障,Spark Streaming 可以为所有的转化操作提供“精确一次”执行的语义,即使-一个工作节点在处理部分数据时发生失败,最终的转化结果(即转化操作得到的RDD)仍然与数据只被处理一次得到的结果一样。
        然而,当把转化操作得到的结果使用输出操作推人外部系统中时,写结果的任务可能因故障而执行多次,一些数据可能也就被了 多次。由于这引人了外部系统, 因此我们需要专门针对各系统的代码来处理这样的情况。我们可以使用事务操作来写人外部系统(即原子化地将一个RDD分区一次写人), 或者设计幂等的更新操作(即多次运行同一个更新操作仍生成相同的结果)。比如Spark Streaming的saves...Fie操作会在一个文件写完时自动将其原子化地移动到最终位置上,以此确保每个输出文件只存在一份。

*Spark Streaming性能考量项:

·批次和窗口大小

·并行度

提高并行度方法:    
1、增加接收器项目
2、将接受到的数据显式地重新分区
3、提高聚合计算并行度