sparkstreaming整合kafka的两种方式
sparkstreaming整合旧版本的kafka有两种方式,一般称为Receiver方式和Direct方式。
Receiver方式
Receiver-based方式是基于kafka high level api来实现的。在executor节点会单独启动一个receiver线程,去持续消费kafka数据,消费到的数据放在executor内存中,当执行batch计算时,executor会去计算这些数据。这种方式有很多缺点:
-
由于宕机或者程序失败等其他因素,存放在内存中未处理的数据可能会丢失。
-
为了防止数据丢失,程序需要配置
spark.streaming.receiver.writeAheadLog.enable
参数,这是启用了预写日志,一般将日志写入HDFS。这样每次处理之前会将数据备份到HDFS,但是这样又会降低数据处理效率,增加节点的压力。 -
由于消费数据与计算数据分别是由两个线程完成的,所以增加topic的分区数并不会增加程序的并行度。
-
当程序计算耗时较久甚至卡住,receiver接收的数据会把内存撑爆。
Direct方式
在较新版本的kafka中,只支持这一种与sparkstreaming的整合方式。该方式采用了kafka low level api的方式去消费数据,无需经由Zookeeper,需要开发者手动去处理偏移量。(请见我的另一篇文章SparkStreaming(Java)-管理kafka偏移量)。这种方式也是业内推荐的方式,它有很多优点:
- 可以保证exactly-once。由于开发者手动维护偏移量,所以当程序故障或者宕机,只需读取上次记录的offset作为起始偏移量开始消费数据就可以了。
- topic分区和RDD分区有一一映射的关系,适量增加topic的分区数,可以增加计算的并行度。
- 不需单独启动一个线程去消费数据,也不需配置额外内存去存放数据。节省资源,降低节点的压力。