一种基于 Spark SQL 引擎的可扩展且容错的流处理引擎,它最关键的思想是将实时数据流视为一个不断增加的表,从而就可以像操作批静态数据一样来操作流数据。相较于spark streaming,Structured Streaming为事件驱动型, 就是数据真正发生的时间,比如用户浏览了一个页面可能会产生一条用户的该时间点的浏览日志。
Structured Streaming将实时流抽象成一张无边界的表,输入的每一条数据当成输入表的一个新行,同时将流式计算的结果映射为另外一张表,完全以结构化的方式去操作流式数据。
会对输入的查询生成“结果表”,每个触发间隔(例如,每 1 秒)新行将附加到输入表,最终更新结果表,每当结果表更新时,能够将更改后的结果写入外部接收器去。
一共有三种Output模式:
Append模式:只有自上次触发后在Result Table表中附加的新行将被写入外部存储器。重点模式,一般使用它。
Complete模式: 将整个更新表写入到外部存储。每次batch触发计算,整张Result Table的结果都会被写出到外部存储介质。
Update模式:只有自上次触发后在Result Table表中更新的行将被写入外部存储器。注意,这与完全模式不同,因为此模式不输出未更改的行。
事件时间在此模型中非常自然地表示,来自设备的每个事件都是表中的一行,事件时间是该行中的一个列值。这允许基于窗口的聚合(例如每分钟的事件数)仅仅是时间列上的特殊类型的分组和聚合 - 每个时间窗口是一个组,并且每一行可以属于多个窗口/组。因此,可以在静态数据集(例如,来自收集的设备事件日志)以及数据流上一致地定义这种基于事件时间窗的聚合查询。
Structured Streaming基于Event time能自然地处理延迟到达的数据,保留或者丢弃。
由于Spark正在更新Result Table,因此当存在延迟数据时,它可以完全控制更新旧聚合,以及清除旧聚合以限制中间状态数据的大小。
使用Watermark,允许用户指定数据的延期阈值,并允许引擎相应地清除旧的状态。
如果假设正好在process的过程中,系统挂掉了,那么数据就会丢了,但因为 Structured Streaming 如果是complete模式,因为是全量数据,所以其实做好覆盖就行,也就说是幂等的。
如果是append 模式,则可能只能保证at-least once ,而对于其内部,也就是result table 是可以保证exactly-once 的。
容错机制
在故障或故意关闭的情况下,用户可以恢复先前进度和状态,并继续在其停止的地方,简称断点续传。这是通过使用检查点checkpoint和预写日志write ahead logs来完成的。
用户可以指定checkpoint的位置,Spark将保存所有进度信息(如每个触发器中处理的offset偏移范围)和正在运行的聚合到checkpoint中。任务重启后,使用这些信息继续执行。
StructuredStreaming+Kafka使用教程:https://blog.csdn.net/lovechendongxing/article/details/81748553
相较于spark streaming,Flink是事件驱动型,它从一个或多个事件流提取数据,并根据到来的事件触发计算、状态更新或其他外部动作。比较典型的就是以kafka为代表的消息队列几乎都是事件驱动型应用。
流处理的特点是无界、实时, 无需针对整个数据集执行操作,而是对通过系统传输的每个数据项执行操作,一般用于实时统计。
在flink的世界观中,一切都是由流组成的,离线数据是有界限的流,实时数据是一个没有界限的流,这就是所谓的有界流和无界流。
分为三层,最底层级的抽象仅仅提供了有状态流,它将通过过程函数(Process Function)被嵌入到DataStream API中。底层过程函数(Process Function) 与 DataStream API 相集成,使其可以对某些特定的操作进行底层的抽象,它允许用户可以自由地处理来自一个或多个数据流的事件,并使用一致的容错的状态。
大多数应用并不需要上述的底层抽象,而是针对核心API(Core APIs) 进行编程,比如:
使用示例
//定义流处理环境
final StreamExecutionEnvironment env = StreamExecutionEnvironment
.getExecutionEnvironment();
// 非常关键,一定要设置启动检查点!!
env.enableCheckpointing(5000);
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
//配置kafka信息
Properties props = new Properties();
props.setProperty("bootstrap.servers",
"hadoop01:9092,hadoop02:9092");
props.setProperty("zookeeper.connect",
"hadoop01:2181,hadoop02:2181");
props.setProperty("group.id", "kafka_to_hdfs");
//读取数据
FlinkKafkaConsumer010 consumer = new FlinkKafkaConsumer010<>(
"test1", new SimpleStringSchema(), props);
//设置只读取最新数据
consumer.setStartFromLatest();
//添加kafka为数据源
DataStream stream = env.addSource(consumer);
//定义输出sink
BucketingSink hdfs_sink = new BucketingSink(
"hdfs:///data/flink/fromKafka");
hdfs_sink.setBatchSize(1024 * 1024 * 400);
hdfs_sink.setBucketer(new DateTimeBucketer("yyyy-MM-dd"));
hdfs_sink.setBatchRolloverInterval(3600000);
//存到hdfs
stream.addSink(hdfs_sink);
env.execute("Kafka-to-HDFS");
对于Storm来说:
对于Spark Streaming来说:
对于Flink来说:
总结
如果对延迟要求不高的情况下,可以使用 Spark Streaming,它拥有丰富的高级 API,使用简单,并且 Spark 生态也比较成熟,吞吐量大,部署简单,社区活跃度较高,在新版本还引入了 Structured Streaming。
如果对延迟性要求非常高的话,可以使用流处理框架 Flink,采用原生的流处理系统,保证了低延迟性,在 API 和容错性方面做的也比较完善,使用和部署相对来说也是比较简单。