2015年12月雅虎使用生产环境中的真实数据对Spark Streaming、Storm以及Flink等流系统计算引擎做了一项基准测试,并得到了以下的测试结果:
我们从上图可以清楚地看到,随着吞吐量的增大,Spark Streaming的延迟也越来越大;而Storm和Flink随着吞吐量的变化延迟波动不是很大。至于为什么这样本文就不详细介绍了。雅虎的流系统基准测试有个明显的问题,就是虽然使用了真实的数据,但是整个测试经过聚合之后仅仅只有100个key,相比其它现实世界的用例,Key的数量实在是太少了。基于这些问题,Flink的母公司dataArtisans对这个基准测试进行了扩展,使用到了Tweet的数据流,每秒会更新数百万个Key,这个看起来和现实更接近,最后的测试结果如下:
(扩展的基准测试都懒得和Spark Streaming比较了)从上图可以看出Flink的吞吐量明显比Storm高;中间的Flink吞吐量受到了Kafka集群和Flink集群之前的带宽影响,而第三个是把Kafka集群和Flink集群放到了一个机房(也就是消除了集群机房之间的带宽影响),这样导致Flink的吞吐量达到了 15000000 events/sec
了!
但是测试的最终结果是保持到持久化系统里面(比如Redis),然后我们把雅虎的测试和dataArtisans公司的测试结果对比一下:
我们发现当Key的数量在100的时候,吞吐量明显比Key数量在1000000的时候要高很多,这是因为整个系统的瓶颈是在将数据写入到持久化系统里面!写的Key数量越多,消耗的时间就越长!所以社区才会引入可查询状态(Queryable State)。
引入可查询状态的好处将有助于消除对键值存储(key-value stores)之类的外部系统的依赖,这些键值存储在实践中经常是瓶颈,正如上图所示。将Flink内部的状态暴露给外部实际上是将数据库的很大一部分工作移动到流处理器中,这将提供高吞吐量查询,而且计算好的状态可以立即被访问。
可行性
上节已经讨论了Flink社区引入可查询状态(Queryable State)的目的。那么在现有的Flink里面实现可查询状态(Queryable State)是否可行呢?答案肯定是可以的。我们都知道,Flink为用户提供了状态管理抽象,以保证流系统的容错处理;分区(partitioned )的状态接口实现为用户提供了不同类型的状态访问;但是这些状态在之前仅仅对Flink的内部可用,所以我们只需要把这部分的访问暴露到外部就可以让用户直接在查询里面查询Flink的状态。
可查询状态(Queryable State)实现
上节讨论了Flink的可查询状态可行性的思路。那么在实现上又是咋弄的?关于Queryable State的实现对应的Issue是FLINK-3779,设计文档可以参考这里(需要翻墙,我已经下载下来了,点击本文下面的 点击进入下载)。下图是Flink的可查询状态实现。
整个过程如下:(1)、查询客户端请求了一个可查询状态:/job/operation/state-name/key
,Flink会请求State Location Server得到 key-partition
的存储位置;
(2)、而State Location Server会从ExecutionGraph中查找位置;
(3)、当 key-partition
的存储位置找到之后,会提供给查询客户端;
(4)、查询客户端根据状态存储的位置向相应的State Registry查询 state-name 和 key;
(5)、最后State Registry将结果返回给查询客户端,这样客户端就得到了相应的状态信息。
上面的整个过程并没有涉及到持久化系统,如果应用程序只对最新的实时结果感兴趣,那么这样的系统就完全可以了;如果应用程序会查询历史的状态结果,Flink的Query Service会把过去计算好的状态信息存储到持久化系统,这样用户既可以查询实时的状态信息,也可以查询历史的状态信息。
那么引入了可查询状态之后,性能变得咋样呢?测试结果如下:
如果想及时了解Spark、Flink、Hadoop或者Hbase相关的文章,欢迎关注微信公共帐号:iteblog_hadoop
我们可以看出,引入了可查询状态之后,即使处理的Key值过多,但是其吞吐量和100个key的吞吐量差不多!性能提升很多啊。