Spark Streaming 是 Spark 提供的对实时数据(其实是微批次,没Storm那么实时,但Storm走下坡路)进行流式计算的组件。比如生产环境中的网页服务器日志,或是网络服务中用户提交的状态更新组成的消息队列,都是数据流。Spark Streaming 提供了用来操作数据流的 API,并且与 Spark Core 中的 RDD API 高度对应。操作内存或硬盘中的数据和操作实时数据流都可。从底层设计来看,Spark Streaming 支持与Spark Core 同级别的容错性、吞吐量以及可伸缩性。
SparkStreaming在Driver中另起一个线程(local模式无法启动,因为只有一个线程,local模式只有一个进程,该进程又当爹又当妈,Driver、Executor进程共用这一个)叫接收器,负责接收数据(90%都来自于Kafka),接收到的数据分成一个一个批次发到Executor去执行,执行完Executor输出。数据处理过程如下:
- 数据输入:来自Kafka、Flume、Twitter、HDFS等。
- 数据的转换:包括有状态(cache算子)的和无状态的(checkpoint算子)。
- 数据输出:写入到Database、Dashboard等。
SparkStreaming一般的数据来源都是Kafka(有分区和消费者,一般消费者数量小于等于分区),Kafka和Spark对接有高阶API(使用Receiver获取数据,有丢数据的可能)和低阶API,一般都用低阶API,也就是直接读取。直接读取有如下优点:
- 简化并行读取:如果要读取多个partition,不需要创建多个输入DStream然后对它们进行union操作。Spark会创建跟Kafka partition一样多的RDD partition,并且会并行从Kafka中读取数据。所以在Kafka partition和RDD partition之间,有一个一对一的映射关系。
- 高性能:如果要保证零数据丢失,在基于receiver的方式中,需要开启WAL机制。这种方式其实效率低下,因为数据实际上被复制了两份,Kafka自己本身就有高可靠的机制,会对数据复制一份,而这里又会复制一份到WAL中。而基于direct的方式,不依赖Receiver,不需要开启WAL机制,只要Kafka中作了数据的复制,那么就可以通过Kafka的副本进行恢复。
- 一次且仅一次的事务机制:基于receiver的方式,是使用Kafka的高阶API来在ZooKeeper中保存消费过的offset的。这是消费Kafka数据的传统方式。这种方式配合着WAL机制可以保证数据零丢失的高可靠性,但是却无法保证数据被处理一次且仅一次,可能会处理两次。因为Spark和ZooKeeper之间可能是不同步的。
基于direct的方式,使用kafka的简单api,Spark Streaming自己就负责追踪消费的offset,并保存在checkpoint中。Spark自己一定是同步的,因此可以保证数据是消费一次且仅消费一次。
Spark Streaming访问Kafka时,针对Kafka-0.10+版本出了spark-streaming-kafka-0-10(原来叫spark-streaming-kafka)。以后都使用新版。