流式计算
大多数的流式计算引擎(比如storm、spark streaming等)都仅仅关注流数据的计算方面:比如使用一个map函数对一个流中每条数据都进行转换,或者是用reduce函数对一批数据进行聚合。但是,实际上在大部分的流式计算应用中,远远不只是需要一个流式计算引擎那么简单。相反的,流式计算仅仅在流式应用中占据一个部分而已。因此现在出现了一个新的名词,叫做持续计算/应用,continuous application。比如以下一些持续应用的例子:
- 更新需要以服务形式实时提供出去的数据:例如,我们可能需要更新一份数据,然后其他用户会通过web应用来实时查询这些数据。这种情况下,一个技术难题就是实时计算应用如何与实时数据服务进行交互,比如说,当实时计算应用在更新数据的时候,如果用户通过实时数据服务来进行查询,此时该如何处理?因此为了处理这种场景下的技术难题,就必须以一个完整的持续计算应用的方式来构建整个系统,而不是站在实时计算的角度,仅仅考虑实时更新数据。
- 实时ETL(Extract、Transform和Load):实时计算领域一个常见的应用就是,将一个存储系统中的数据转换后迁移至另外一个存储系统。例如说,将JSON格式的日志数据迁移到Hive表中。这种场景下的技术难题就在于,如何与两边的存储系统进行交互,从而保证数据不会丢失,同时也不会发生重复。这种协调逻辑是非常复杂的。
- 为一个已经存在的批量计算作业开发一个对应的实时计算作业:这个场景的技术难题在于,大多数的流式计算引擎都无法保证说,它们计算出的结果是与离线计算结果相匹配的。例如说,有些企业会通过实时计算应用来构建实时更新的dashboard,然后通过批量计算应用来构建每天的数据报表,此时很多用户就会发现并且抱怨,离线报表与实时dashboard的指标是不一致的。
- 在线机器学习:这类持续计算应用,通常都包含了大型的静态数据集以及批处理作业,还有实时数据流以及实时预测服务等各个组件。
以上这些例子就表明了在一个大型的流式计算应用中,流式计算本身其实只是占据了一个部分而已,其他部分还包括了数据服务、存储以及批处理作业。但是目前的现状是,几乎所有的流式计算引擎都仅仅是关注自己的那一小部分而已,仅仅是做流式计算处理。这就使得开发人员需要去处理复杂的流式计算应用与外部存储系统之间的交互,比如说管理事务,同时保证他们的流式计算结果与离线批处理计算结果保持一致。这就是目前流式计算领域急需要解决的难题与现状。
持续计算应用
持续计算应用可以定义为,对数据进行实时处理的整套应用系统。spark社区希望能够让开发人员仅仅使用一套api,就可以完整持续计算应用中各个部分涉及的任务和操作,而这各个部分的任务和操作目前都是通过分离的单个系统来完成的,比如说实时数据查询服务,以及与批处理作业的交互等。举例来说,未来对于解决这些问题的一些设想如下:
- 更新那些需要被实时提供服务的数据:开发人员可以开发一个spark应用,来同时完成更新实时数据,以及提供实时数据查询服务,可能是通过jdbc相关接口来实现。也可以通过内置的api来实现事务性的、批量的数据更新,对一些诸如mysql、redis等存储系统。
- 实时ETL:开发人员仅仅需要如同批处理作业一样,开发一样的数据转换操作,然后spark就可以自动完成针对存储系统的操作,并且保证数据的一次且仅一次的强一致性语义。
- 为一个批处理作业开发一个实时版本:spark可以保证实时处理作业与批处理作业的结果一定是一致的。
-
在线机器学习:机器学习的api将会同时支持实时训练、定期批量训练、以及实时预测服务。
Structured Streaming
Spark 2.0中,引入的structured streaming,就是为了实现上述所说的continuous application,也就是持续计算的。首先,structured streaming是一种比spark更高阶的api,主要是基于spark的批处理中的高阶api,比如dataset/dataframe。此外,structured streaming也提供很多其他流式计算应用所无法提供的功能:
- 保证与批处理作业的强一致性:开发人员可以通过dataset/dataframe api以开发批处理作业的方式来开发流式处理作业,进而structured streaming可以以增量的方式来运行这些计算操作。在任何时刻,流式处理作业的计算结果,都与处理同一份batch数据的批处理作业的计算结果,是完全一致的。而大多数的流式计算引擎,比如storm、kafka stream、flink等,是无法提供这种保证的。
- 与存储系统进行事务性的整合:structured streaming在设计时就考虑到了,要能够基于存储系统保证数据被处理一次且仅一次,同时能够以事务的方式来操作存储系统,这样的话,对外提供服务的实时数据才能在任何时刻都保持一致性。目前spark 2.0版本的structured streaming,仅仅支持hdfs这一种外部存储,在未来的版本中,会加入更多的外部存储的支持。事务性的更新是流式计算开发人员的一大痛点,其他的流式计算引擎都需要我们手动来实现,而structured streaming希望在内核中自动来实现。
- 与spark的其他部分进行无缝整合:structured steaming在未来将支持基于spark sql和jdbc来对streaming state进行实时查询,同时提供与mllib进行整合。spark 2.0仅仅开始做这些整合的工作,在未来的版本中会逐渐完善这些整合。
除了这些独一无二的特性以外,structured streaming还会提供其他feature来简化流式应用的开发,例如对event time的支持,从而可以自动处理延迟到达的数据,以及对滑动窗口和会话的更多的支持。目前structured streaming还停留在beta阶段,因此官方声明,仅供用户学习、实验和测试。
Structured Streaming的未来
spark官方对structured streaming未来的计划是非常有野心的:希望spark的所有组件(core、sql、dataset、mllib等)都能够通过structured steaming,以增量的方式来运行,进而支持更丰富的实时计算操作。structured streaming会设计为让其计算结果与批处理计算结果是强一致的。大数据用户的一个非常大的痛点,就是需要一个完全统一的编程接口。例如说,之前用户进行大数据开发时,需要整合使用多种计算引擎,比如mapreduce来进行etl,hive来执行sql查询,giraph来进行图计算,storm来进行实时计算,等等。而spark则可以完全统一这些操作。此外,structured streaming也希望能够完全涵盖一个持续计算应用中的方方面面。
Structured Streaming与其他流式计算应用的对比
属性 | Structured Streaming | Spark Streaming | Apache Storm | Apache Flink | Kafka Stream | Google Dataflow |
---|---|---|---|---|---|---|
Streaming API | 增量执行批处理计算 | 基于批处理计算引擎 | 与批处理无关 | 与批处理无关 | 与批处理无关 | 基于批处理计算引擎 |
基于数据位置前缀的计算完整性的保证 | 支持 | 支持 | 不支持 | 不支持 | 不支持 | 不支持 |
一致性语义 | exactly once | exactly once | exactly once | exactly once | at least once | exactly once |
事务性操作存储支持 | 支持 | 部分支持 | 部分支持 | 部分支持 | 不支持 | 不支持 |
交互式查询 | 支持 | 支持 | 支持 | 不支持 | 不支持 | 不支持 |
与静态数据进行join | 支持 | 支持 | 不支持 | 不支持 | 不支持 | 不支持 |