sparkStreaming连接kafak的receiver方式和direct方式

sparkStreaming连接kafak的receiver方式和direct方式

Receiver方式(已废弃)

从kafka的中获取的数据都是储存在sparkexecutor的内存中,然后sparkStreaming启动的job回去处理那些数据
然而,在默认的配置下,这种方式可能会因为底层的失败而丢失数据.
如果要启用高可靠的机制,让数据零丢失,就必须启用sparkStreaming预写日志机制(write ahead log,wal)
该机制会同步地将接收到的kafka数据写入到分布式文件系统中,(比如hdfs)上的预写日志中.
所以,即使底层节点出现了失败,也可能使用预写日志机制中的数据进行恢复,但是效率会下降.

def getReceiver(): Receiver[(K, V)] = {
    if (!useReliableReceiver) {
      //< 不启用 WAL
      new KafkaReceiver[K, V, U, T](kafkaParams, topics, storageLevel)
    } else {
      //< 启用 WAL
      new ReliableKafkaReceiver[K, V, U, T](kafkaParams, topics, storageLevel)
    }
  }

direct方式

direct这种方式会周期性的查询kafka,来获得每个topic+partition的最新的offset,从而定义每个batch的offter的范围
当处理数据的job启动时,就会使用kafka的简单consumer api来获取kafka指定offer范围的数据.

def main(args: Array[String]): Unit = {
//定义一个appName
    val appName = "wordcount"
    val groupId = "g10"
//创建一个spark环境,在套一层StreamingContext
    val conf = new SparkConf()
      .setAppName(appName)
      .setMaster("local[*]")
    val ssc = new StreamingContext(conf, Milliseconds(5000))
    //设置运行时的日志级别
    ssc.sparkContext.setLogLevel("WARN")
//创建一个直连的数据流设置主机名,连接方式,和各种参数
    val kafkaParams = Map[String, Object](
      "bootstrap.servers" -> "doit01:9092,doit02:9092,doit03:9092",
      "key.deserializer" -> classOf[StringDeserializer],
      "value.deserializer" -> classOf[StringDeserializer],
      "group.id" -> "gwc02",
      "auto.offset.reset" -> "earliest",//从头开始读
      "enable.auto.commit" -> (false: java.lang.Boolean) //不自动提交偏移量,如果不设置,默认为true
    )
//这只topics的名字
    val topics = Array("wordcount")
    val histroyOffsets: Map[TopicPartition, Long] = OffsetUtils.queryHistoryOffsetFromMySQL(appName, groupId)
//创建Kafka数据流
    val kafkaDStream: InputDStream[ConsumerRecord[String, String]] = KafkaUtils.createDirectStream[String, String](
      ssc,
      LocationStrategies.PreferConsistent, //位置策略
      ConsumerStrategies.Subscribe[String, String](topics, kafkaParams, histroyOffsets) //订阅策略
    )

使用direct这种方式有以下的优点

1.简化并行读取

如果kafka中有多个partition,我们不需要创建多个DStream然后union
spark会自动创建跟kafka partition一样多的RDD partition,并且会并行的从kafka中读取数据.
所以kafka partition和RDD partition之间,有一个对一个的映射关系.

2.高性能

如果要保证数据零丢失,在基于receiver的方式中,需要开启WAL(预写日志机制).
这种机制其实效率低下,因为数据实际上被复制了两份,kafka自己本身就有高可靠的机制,会自己对数据复制一份,而这里又会复制一份到WAL中去.
而基于direct直连的方式,不依赖receiver,不需要开启WAL机制,只要kafka中做了数据的复制,那么就可以通过kafka的副本进行恢复.

3.一次且仅一次事物机制

receiver方式,是使用kafka高阶的api来在zookeeper中保存消费过的offset的,这是消费kafka数据的传统的方式
这种机制可以保证数据零丢失的高可靠性,但是却无法保证数据被处理一次且仅一次,可能会处理两次,因为spark和zookeeper之间是不可能同步的,浪费资源.
基于direct的方式,使用kafka的简单的api,sparkStreaming自己就负责追踪消费offset,并保存在checkpoint中,
因为spark自己一定是同步的,因为可以保证数据是消费一次且仅消费一次的,节省资源.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值