第三个Flink 1.7中做了很多工作的功能是Schema升级。这个功能和基于流的应用紧密相关。就像你可以对数据库进行数据Schema升级一样,你可以修改Flink表中列的类型或者重新写一个列。
另外我想简单介绍的是流处理技术不仅仅是简单对数据进行计算,这还包括了很多与外部系统进行事务交互。流处理引擎需要在采用不同协议的系统之间以事务的方式移动数据,并保证计算过程和数据的一致性。这一部分功能也是在Flink 1.7中得到了增强。
以上我对Flink 1.7的新功能向大家做了简单总结。下面让我们来看看今天我演讲的主要部分,也就是利用Flink来搭建应用和服务。我将说明为什么流处理是一个搭建应用和服务或者微服务的有趣技术。
我将从左边这个高度简化的图说起,我们一会儿将聊一些其中的细节。首先我们来看一个理解应用简单的视角。如左图所示,一个应用可以是一个Container,一个Spring应用,或者Java应用、Ruby应用,等等。这个应用从诸如RPC,HTTP等渠道接收请求,然后依据请求进行数据库变更。这个应用也可能调用另一个微服务并进行下一步的处理。我们可以非常自然的想到进入到应用的这些请求可以看做是个事件组成的序列,所以我们可以把它们看做是事件流。可能这些事件被缓存在消息队列中,而应用会从消息队列中消费这些事件进行处理,当应用需要响应一个请求时,它将结果输出到另一个消息队列,而请求发送方可以从这个消息队列中消费得到所发送请求的响应。在这张图中我们已经可以看到一些有趣的不同。
第一个不同是在这张图中应用和数据库不再是分开的两个实体,而是被一个有状态的流处理应用所代替。所以在流处理应用的架构中,不再有应用和数据库的连接了,它们被放到了一起。这个做法有利有弊,但其中有些好处是非常重要的。首先是性能上的好处是明显的,因为应用不再需要和数据库进行交互,处理可以基于内存中的变量进行。其次这种做法有很好并且很简单的一致性。
这张图被简化了很多,实际上我们通常会有很多个应用,而不是一个被隔离的应用,很多情况下你的应用会更符合这张图。系统中有个接收请求的接口,然后请求被发送到第一个应用,可能会再被发到另一个应用,然后得到相应。在图中有些应用会消费中间结果的流。这张图已经展示了为什么流处理是更适合比较复杂的微服务场景的技术。因为很多时候系统中不会有一个直接接收用户请求并直接响应的服务,通常来说一个微服务需要跟其他微服务通信。这正如在流处理的架构中不同应用在创建输出流,同时基于衍生出的流再创建并输出新的流。
到目前为止,我们看到的内容多少还比较直观。而对基于流处理技术的微服务架构而言,人们最常问的一个问题是如何保证事务性?如果系统中使用的是数据库,通常来说都会有非常成熟复杂的数据校验和事务模型。这也是数据库在过去许多年中十分成功的原因。开始一个事务,对数据做一些操作,提交或者撤销一个事务。这个机制使得数据完整性得到了保证(一致性,持久性等等)。
那么在流处理中我们怎么做到同样的事情呢?作为一个优秀的流处理引擎,Flink支持了恰好一次语义,保证了每个事件只会被处理一遍。但是这依然对某些操作有限制,这也成为了使用流处理应用的一个障碍。我们通过一个非常简单流处理应用例子来看我们可以做一些什么扩展来解决这个问题。我们会看到,解决办法其实出奇的简单。
让我们以这个教科书式的事务为例子来看一下事务性应用的过程。这个系统维护了账户和其中存款余额的信息。这样的信息可能是银行或者在线支付系统的场景中用到的。假设我们想要处理类似下面的事务: