对于 Flink 未来的一个可能的方向,Stephan 继续表达了他对 Application 这种偏在线服务的场景的兴趣。他先是将我们平时所说的批处理和流计算总结为 Data Processing,同时将消息驱动和数据库之类的应用总结为 Applications,而 Stream Processing 就是连接这两种看起来截然不同的场景的桥梁。
我在一开始听到这个的时候也有点一头雾水,不明就里的感觉,经过这几天对这个问题的思考,有了一些自己的理解,我将在文末展开进行解释。提到 Application,就不得不提现在很流行的 FaaS(Function as a Service)。在这个领域,Stephan 觉得大家都忽视了 State 在这里面的重要性。比如一个典型的 Application 场景,一般都会具备以下这些特点:
整个 Application 会有一个或者多个入口,计算逻辑由消息来驱动
具体的业务逻辑被拆分成粒度较小的几个单元,每个逻辑单元使用一个 Function 来执行具体的逻辑
Function 之间会互相调用,一般来说我们也会将这些调用设计为异步的模式
每个 Function 的计算逻辑可能会需要一些状态,比如可以使用数据库作为状态的存储
在完整的计算逻辑完成之后,我们会通过一个统一的出口返回处理的状态
在这个场景里,我们看到了至少三点需求:
计算逻辑由消息驱动
计算逻辑和互相调用的关系必须可以比较灵活的进行组织
计算逻辑需要状态的支持,并且在某些情况下,需要保证 exactly once 的处理语义
这里面属第三点最难做。大家可以想象一下,假如现在我们的 Application 要处理类似电商场景下单这样的过程,同时我们依赖数据库作为这个应用的状态存储。我们有一个专门的库存管理逻辑和一个下单逻辑。在一个完整的购买逻辑里,我们需要先调用库存管理模块,检查下该商品是否有库存,然后将该商品的库存从数据库里减去1。这一步成功之后,我们的服务再继续调用下单逻辑,在数据库里面生成一个新的订单。
在一切都正常的时候,这样的逻辑还是比较简单的,但一旦有错误出现就会相当麻烦。比如我们已经将库存减掉,但是在生成订单的过程中发生了错误,这样我们还得想办法让库存进行回滚。一旦类似的业务逻辑单元变多之后,你的应用代码将变得异常复杂。这个问题就是典型的 end-to-end exactly once,我们希望一个错综复杂的计算流程,要么全部一起成功,要么全部失败,就当它完全没发生过一样。