Dstream是spark streaming的一个基本抽象;如同rdd之于spark;只是一个类型的Dstream本质上是一系列连续的RDD,这些RDD只是要计算的数据不同,它们来自不同微批,源源不断。
sparkstreaming 的简单wordcount
|
|
但是上面的程序只能统计一个微批次的结果,如果想要获得指定过去的几个微批的结果或者说要获取到历史总计聚合结果就需要能够进行有状态的编程。sparkstreaming提供了更新状态累加的updateStateBykey方法。
于是,wordcount可以改造成如下代码:
|
|
但是上面程序仍然存在问题,当程序重启之后,不能接着上次消费的地方继续累加历史状态,而是重新以本次运行时间开始去进行累加的计算。
sparkStreaming和kafka整合的2种方式:
Receiver方式
采用高级的api去接收kafka中的数据,然后以自动更新偏移量的方式去提交偏移量。而且是达到固定时间才进行处理。这种方式容易丢数据,原因有:1:receiver可用内存满了,无法继续接收后续数据;2:一旦接收失败,receiver内存中已经接收的数据没有持久化;为了避免丢失,当达到某个阈值后把前面的数据写到磁盘里面,先读的数据写到磁盘里面(也就是WAL机制);
直连方式
直连方式采用更底层的api,将kafka的分区数据直接对接到spark的分区上。来一条处理一条;手动维护偏移量,我理解如果是自动提交偏移量的话有可能出现:先处理完了后提交导致重复消费,先提交还没处理完导致数据丢失。自动提交偏移量的时延不好把握;当然先处理逻辑后手动提交也会有重复消费的问题,这个时候考虑把这两步结合到一个事务里来解决。而直连方式的累积需要结合外部的数据库(redis)去完成。