Spark streaming作为spark的一个组件,构建在spark之上的实时流计算框架。Spark streaming启动以后,在运行过程中,依赖的模块包括Driver、woker,其中Driver中运行streaming context和spark context相关的实体,woker一方面承载receiver接收输入流,还需要运行对数据处理的逻辑(spark计算引擎),即以时间片为单位形成的RDD,以调用spark context批处理的方式处理。那么fail的可能模块也就包括Driver、以及其他执行RDD graph的woker,所以就需要一套HA的机制来进行保证整个流处理过程的可用性。
对于spark计算过程中的失效,比如某一work宕机,这个依赖于spark本身的容错性机制,使用lineage以及内存备份两份数据进行备份容错,RDD通过lineage记录之前的操作,可以通过冗余备份数据在其他节点重新计算得到,这种在worker级别的failover在spark中已经做了,worker挂掉,重新换个woker执行即可。
对于Driver的容错性和可用性,也是需要考虑的。在spark1.2发布版本中,spark streaming提供了HA机制,在介绍这块运行的机制架构之前先介绍WriteAheadLog。
WriteAheadLog在很多的可用性的数据库设计中用的比较多,在往内存写数据之前,需要把数据写入到日志中来保证失效时的可恢复性,像关系型数据库的redoLog,分布式数据库HBase的WAL等。Spark streaming的数据可用性也采取了类似的机制。
下图是Spark1.2开始支持HA的sparkstreaming的架构
1、 Spark Streaming把 Receiver包装成RDD,作为一个Task运行在worker中的Executor内,启动流的接收服务
2、 Receiver把接收到的数据按照一定的时间间隔(属性),由BlockGenerator生成block
3、 ReceiverBlockHandler一方面把block存进BlockManager中,并且向BlockManagerMaster报告block的位置信息;另外一方面把block写到Hdfs中返回file segment信息给receiver。
4、 Receiver把元数据(BlockID和file Segment信息)通知给ReceiverTracker; ReceiverTracker把这些元信息写到HDFS中,成功后给Receiver确认。
5、 在完成block写到BlockManager、HDFS Log,以及Driver(ReceiverTracker)成功写元数据信息到HDFSLog中后,Receiver给InputStream一个确认的消息(kafka的offset)
6、 在Driver端,按照batch时间间隔,由block的元数据信息生成RDD,这些RDD数据可以从blockManager中获取,也可以从HDFS中获取。
7、 Batch to block info mapping信息也会定时checkpoint到HDFS中,checkpoint信息还包括用pendingTimes做标记的有哪些job没有被submit,这样JobScheduler重新启动的时候会重新提交这些jobs,这里是at-least once逻辑,因为不知道在cp完多久后crash,所以其中某些job有可能已经被成功执行。
下面看一下sparkstreaming在组件失效后的恢复过程:
1、 StreamingContext在创建的过程中,如果有checkpoint信息,则基于checkpoint信息进行重建,checkpoint主要包括RDD的相关信息(Batch到blockinfo的映射),ReceiverTracker会把元数据信息blockinfo从hdfs中进行读取。
2、 JobScheduler重新构造未完成作业,由于失败而没有处理完成的批处理,使用恢复后的元数据再次产生RDD以及对应的Job
3、 当这些恢复的BlockRDD执行时,work根据需要从HDFS中读取block数据块,并且存储到BlockManager的内存中。
4、 在Receiver端,失败时没有保存到日志中的缓存数据将由数据源再次发送,因为接收器尚未对其确认,接收数据的正确性只在数据被预写到日志以后接收器才会确认,已经缓存但还没有保存的数据可以在driver重新启动之后由数据源再发送一次。
这个在kafka和sparkstreaming对接中,在1.2版本中提供可靠的receiver,ReliableKafkaReceiver,维护topic-partion、offset的信息,只有在把block写到write-ahead-log中后,才更新offset信息。这样下次从该offset位置从kafka的broker中拉取数据。
相比较无HA保证的机制,spark streaming的HA是对性能有影响的,所以在实际的业务场景中,需要综合考虑,对于一致性要求比较高的业务场景,可以采用这套机制,同时为了提高HA的吞吐量,可以采取多个receiver进行接收