(1) Receiver 方式
使用 kafka 的高层次 API 进行消费,然而,在默认的配置下,这种方式可能会因为底层的失败而丢失数据。如果要启用高可靠机制,让数据零丢失,就必须启用 Spark Streaming 的预写日志机制(Write Ahead Log,WAL)。该机制会同步地将接收到的 Kafka 数据写入分布式文件系统(比如 HDFS)上的预写日志中。所以,即使底层节点出现了失败,也可以使用预写日志中的数据进行恢复。
需要注意的是:
1、Kafka 中的 topic 的 partition,与 Spark 中的 RDD 的 partition 是没有关系的。所以,在 KafkaUtils.createStream()中,提高 partition 的数量,只会增加一个 Receiver 中,读取 partition 的线程的数量。不会增加 Spark 处理数据的并行度。
2、如果基于容错的文件系统,比如 HDFS,启用了预写日志机制,接收到的数据都会被复制一份到预写日志中。因此,在KafkaUtils.createStream()中,设置的持久化级别是 StorageLevel.MEMORY_AND_DISK_SER。
(2) 基于 Direct 的方式
使用 kafka 更加底层的 api,自己维护偏移量。
这种方式有如下优点:
1、简化并行读取:如果要读取多个 partition,不需要创建多个输入 DStream 然后对它们进行 union 操作。Spark 会创建跟 Kafka partition 一样多的 RDD partition,并且会并行从 Kafka 中读取数据。所以在 Kafka partition 和 RDD partition之间,有一个一对一的映射关系。
3、高性能:receiver 方式为了保证数据不丢失,需要开启 WAL 机制,这样同样的数据会保存两份。而基于 direct的方式,不依赖 Receiver,不需要开启 WAL 机制,只要 Kafka 中作了数据的复制,那么就可以通过 Kafka 的副本进行恢复。