kafka版本,kafka0.8支持Receiver和Direct
Kafka版本大于等于0.10.0,且Spark版本大于等于Spark 2.3.0,应使用spark-streaming-kafka-0-10,
Kafka 0.9版本之前,consumer默认将offset保存在Zookeeper中,从0.9版本开始,consumer默认将offset保存在Kafka一个内置的topic中,该topic为__consumer_offsets
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_2.11</artifactId>
<version>2.2.2</version>
</dependency>
<!--spark-streaming-kafka-plugin-->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming-kafka-0-8_2.11</artifactId>
<version>2.2.2</version>
</dependency>
// 1、Kafka配置
// 配置zookeeper集群、消费者组
val kafkaParams = Map(
"zookeeper.connect" -> "localhost:2181",
"group.id" -> groupID)
// 2、topic_name与numThreads的映射
// topic有几个partition,就写几个numThreads。
// 每个partition对应一个单独线程从kafka取数据到Spark Streaming
val topics = Map(topicName -> numThreads)
// 3、ReceiverInputDStream
// 注意:应先import kafka.serializer.StringDecoder再import org.apache.spark.streaming._
val kafkaStream= KafkaUtils.createStream[String, String, StringDecoder, StringDecoder](
ssc,
kafkaParams,
topics,
StorageLevel.MEMORY_AND_DISK_SER_2)
Spark Streaming启动时,会在Executor中同时启动Receiver异步线程用于从Kafka持续获取数据,数据保存在Executor中,Executor挂了会导致数据丢失
- Spark Streaming启动时,会在Executor中同时启动Receiver异步线程用于从Kafka持续获取数据
- 获取的数据先持久化在Receiver中(存储方式由StorageLevel决定,一般是内存+磁盘)
- 当Batch Job触发后,这些数据会被转移到剩下的Executor中被处理
- 处理完毕后,Receiver会自动更新Zookeeper中的Offset
这个是以前记笔记写的,我现在感觉这个需要验证,到底是什么时候提交的offset
接受数据不会立即更更新offset,而是等到持久化结束后更新offset
但是,如何节点挂了,持久化到内存的数据就丢失了
生产下,为保证数据完全不丢失,一般需要启用WAL(Write Ahead Log)预写日志机制,需要配置WAL,spark.streaming.receiver.writeAheadLog.enable,将Receiver收到的数据再备份一份到更可靠的系统如HDFS分布式文件中,以冗余的数据来换取数据不丢失
虽然WAL可以确保数据不丢失,它并不能对所有的数据源保证exactly-once语义,这就是数据重复问题
虽然WAL可以确保数据不丢失,它并不能对所有的数据源保证exactly-once语义
// 1、Kafka配置
// auto.offset.reset=latest 无提交的offset时,从最新的开始消费
// enable.auto.commit=false 禁用后台自动提交offset,自己手动管理
val kafkaParams = Map[String, Object](
"bootstrap.servers" -> "localhost:9092",
"key.deserializer" -> classOf[StringDeserializer],
"value.deserializer" -> classOf[StringDeserializer],
"auto.offset.reset" -> "latest",
"enable.auto.commit" -> (false: java.lang.Boolean),
"group.id" -> groupID)
// 2、DirectKafkaInputDStream
// LocationStrategies:本地策略。为提升性能,可指定Kafka Topic Partition的消费者所在的Executor。
// LocationStrategies.PreferConsistent:一致性策略。一般情况下用这个策略就OK。将分区尽可能分配给所有可用Executor。
// LocationStrategies.PreferBrokers:特殊情况,如果Executor和Kafka Broker在同一主机,则可使用此策略。
// LocationStrategies.PreferFixed:特殊情况,当Kafka Topic Partition负荷倾斜,可用此策略,手动指定Executor来消费特定的Partition.
// ConsumerStrategies:消费策略。
// ConsumerStrategies.Subscribe/SubscribePattern:可订阅一类Topic,且当新Topic加入时,会自动订阅。一般情况下,用这个就OK。
// ConsumerStrategies.Assign:可指定要消费的Topic-Partition,以及从指定Offset开始消费。
val kafkaStream=KafkaUtils.createDirectStream[String,String](
ssc,
LocationStrategies.PreferConsistent,
ConsumerStrategies.Subscribe[String,String](List(topicName),kafkaParams)
)