Oeljeklaus 2020-04-20
1】Receiver是使用高层次的consumer Api来实现的。
receiver 接收的消息都是存储在spark Executor中的,然后spark启动jobq去处理那些消息
然而,默认情况下,这种方式会因为底层的失败丢失数据。
如果要启用高可靠机制,让数据零丢失,就必须启用spark streaming的预写日志机制,(Write Ahead Log,WAL)。
该机制会同步的将kafka数据写入到分布式文件系统(如hdfs上)上的预写日志中。所以,即使底层节点出现问题,也可以使用预写日志中的数据进行恢复,但是效率会下降。
2】direct这种方式会周期性的查询kafka,来获取每个topic+partition的每个offset,从而定义每个batch的offset的范围。
当处理数据job启动时,就会使用简单的api来获取指定的offset范围的数据。
direct方式的优点:
1)简化并行读取
如果要读取多个partition,不需要创建多个输入Dstream然后对他们进行union操作,spark会创建跟kafka partition一样多的rdd partition,并行的从kafka读取数据。所以在kafka partition跟rdd partition之间,有一个一对一的映射。
2)高性能
如果要保证零数据丢失,在基于receiver的方式中需要开启WAL机制,这种方式效率低下,因为要保存两份数据,kafka本身就有高可靠的机制,会对数据复制一份,而这里又会复制一份到WAL中。而direct方式只要kafka中复制一份,就可以通过kafka的副本进行恢复。
3)一次且仅一次的事务机制
基于receiver的方式,是使用高层次api在zk中保存消费过的offset这是传统的消费方式。这种方式配合WAL实现数据零丢失,但是却无法保证数据消费仅一次,可能会处理两次。因为spark和zk之间可能是不同步的。direct方式自己追踪消费的offset,并保存在checkpoint中,spark自己一定是同步的,消息仅消费一次。