之前文章所说的 MapReduce 和 Spark ,都是在解决海量数据计算问题,这里说的海量数据有一个特点就是:已经存在的,例如历史数据。
对于 MapReduce 和 Spark 来讲,这些数据是一大批数据,也称之为有界数据,对这些数据的计算就称为批计算。
随着移动互联网、物联网的兴起,每分每秒都在产生大量的数据,例如传感器产生的数据、订单交易数据、用户行为记录等。这些无时不刻都在产生的数据,我们称之为无界数据或流数据。通常被用于用户行为分析进行实时推荐、销售数据实时分析进行营销策略调整等场景。
MapReduce 和 Spark 这样的批计算系统就满足不了实时计算的需求。所以就诞生了 Storm、Spark Streaming、Flink这些流计算系统。
批计算和流计算整体工作流程大体一致,都有任务调度、计算结果聚合等过程。只不过因为数据源的原因,执行细节上会有所不同。这里有几个概念需要进行区分,避免混淆:
- 资源(计算节点)分配:
- 批计算是对一批数据进行一次计算,所以在每次调度计算任务时分配资源,计算完成后,对应的资源就会被释放,下次在执行时重新分配资源。
- 流计算是对实时流进系统的数据进行不间断的计算,所以计算资源会一次分配完成,后续的计算任务会一直运行,直到程序异常任务停止才会释放资源。
- 任务调度:
- 批计算是因为历史数据量过大,数据源是分布在各个节点的数据块,所以会根据数据所在地进行任务调度(数据、计算本地化)。
- 流计算数据源通常是Socket、Kafka中的一条条数据,所有的计算任务在这之前已经根据并行度调度到各个节点,数据来临时根据某个策略分配给某个计算任务。
由于 Spark Streaming 是建立在 Spark 基础上,所以任务执行还是 Spark 的逻辑,所以 Spark Streaming 算是一个“伪”流计算系统,属于批计算这一波。
简单来说 Spark Streaming 通过很小的时间间隔(例如1秒)将实时数据收集为“微批”数据,然后然后交给 Spark 处理。
因为是间隔一段时间再去计算,所以在实时性方面,Spark Streaming 就不如 Flink,现在说起流计算基本上就是在讨论 Flink 了。不过两者的架构和概念有很多相似的地方,也都是函数式编程。如果掌握了 Spark ,学习 Flink 也就非常简单轻松了。
至于 Storm ,作为早期的实时计算引擎并不支持有状态计算和exactly-once的语义,以及编码相对复杂,所以现在也慢慢被大家遗忘。
如果有“Spark Streaming 收集的数据是怎么分区的?”、“什么是有状态计算和exactly-once语义?”、“Flink 是如何做到数据、计算本地化?”等疑问的,请关注我,欢迎大家一起交流。