copy from:

http://wiki.sankuai.com/pages/viewpage.action?pageId=785766444

背景

订单推送到达目前状况频繁,排查问题耗时耗力,急需开发一套监控系统,以快速定位或提前预警。经过调研发现公司有个完整解决方案:大白平台,但是我们需要按城市维度聚合计算,大白目前不支持查询门店的城市数据,因此只有自行开发一套针对我们业务场景的监控系统。这其中最重要的就是实时计算框架选型和存储服务选型,本文先谈实时计算框架选型。目前业界主流的实时计算框架有4种:storm、spark streaming、samaza、flink,公司暂时只支持storm和spark streaming服务。

实时计算,一般指分布式流处理,是对无边界数据集进行连续不断的处理、聚合和分析。它跟MapReduce一样是一种通用计算,但我们期望延迟在毫秒或者秒级别。这类系统一般采用有向无环图(DAG)。DAG是任务链的图形化表示,我们用它来描述流处理作业的拓扑,比如在storm中就称作topology。如下图所示,其实单机也可以运行,但是考虑到吞吐量和容灾,业界一般都是分布式运行的。

关注点

当选择不同的流处理系统时,有以下几点需要注意的:

运行时和编程模型:平台框架提供的编程模型决定了许多特色功能,编程模型要足够处理各种应用场景。

函数式原语:流处理平台应该能提供丰富的功能函数,比如,map或者filter这类易扩展、处理单条信息的函数;处理多条信息的函数aggregation;跨数据流、不易扩展的操作join。

状态管理:大部分应用都需要保持状态处理的逻辑。流处理平台应该提供存储、访问和更新状态信息。

平台的成熟度和接受度:成熟的流处理框架可以提供潜在的支持,可用的库,甚至开发问答帮助。选择正确的平台会在这方面提供很大的帮助。

以上这四点我们都不用考虑,有公司的大数据团队负责封装API方便调用。

消息传输保障:消息传输保障一般有三种:at most once,at least once和exactly once。At most once的消息传输机制是每条消息传输零次或者一次,即消息可能会丢失;A t least once意味着每条消息会进行多次传输尝试,至少一次成功,即消息传输可能重复但不会丢失;Exactly once的消息传输机制是每条消息有且只有一次,即消息传输既不会丢失也不会重复。

容错:流处理框架中的失败会发生在各个层次,比如,网络部分,磁盘崩溃或者节点宕机等。流处理框架应该具备从所有这种失败中恢复,并从上一个成功的状态(无脏数据)重新消费。

性能:延迟时间(Latency),吞吐量(Throughput)和扩展性(Scalability)是流处理应用中极其重要的指标。

运行时和编程模型

运行时和编程模型是一个系统最重要的特质,因为它们定义了表达方式、可能的操作和将来的局限性。因此,运行时和编程模型决定了系统的能力和适用场景。

实现流处理系统有两种完全不同的方式:一种是称作原生流处理,意味着所有输入的记录一旦到达即会一个接着一个进行处理。

第二种称为微批处理。把输入的数据按照某种预先定义的时间间隔(典型的是几秒钟)分成短小的批量数据,流经流处理系统。

两种方法都有其先天的优势和不足。

首先以原生流处理开始,原生流处理的优势在于它的表达方式。数据一旦到达立即处理,这些系统的延迟性远比其它微批处理要好。除了延迟性外,原生流处理的状态操作也容易实现,后续将详细讲解。

一般原生流处理系统为了达到低延迟和容错性会花费比较大的成本,因为它需要考虑每条记录。原生流处理的负载均衡也是个问题。比如,我们处理的数据按key分区,如果分区的某个key是资源密集型,那这个分区很容易成为作业的瓶颈。

接下来看下微批处理。将流式计算分解成一系列短小的批处理作业,也不可避免的减弱系统的表达力。像状态管理或者join等操作的实现会变的困难,因为微批处理系统必须操作整个批量数据。并且,batch interval会连接两个不易连接的事情:基础属性和业务逻辑。

相反地,微批处理系统的容错性和负载均衡实现起来非常简单,因为微批处理系统仅发送每批数据到一个worker节点上,如果一些数据出错那就使用其它副本。微批处理系统很容易建立在原生流处理系统之上。

编程模型一般分为组合式和声明式。组合式编程提供基本的构建模块,它们必须紧密结合来创建拓扑。新的组件经常以接口的方式完成。相对应地,声明式API操作是定义的高阶函数。它允许我们用抽象类型和方法来写函数代码,并且系统创建拓扑和优化拓扑。声明式API经常也提供更多高级的操作(比如,窗口函数或者状态管理)。

容错性

流处理系统的容错性与生俱来的比批处理系统难实现。当批处理系统中出现错误时,我们只需要把失败的部分简单重启即可;但对于流处理系统,出现错误就很难恢复。因为线上许多作业都是7 x 24小时运行,不断有输入的数据。流处理系统面临的另外一个挑战是状态一致性,因为重启后会出现重复数据,并且不是所有的状态操作是幂等的。容错性这么难实现,那下面我们看看各大主流流处理框架是如何处理这一问题。

Apache Storm:Storm使用上游数据备份和消息确认的机制来保障消息在失败之后会重新处理。消息确认原理:每个操作都会把前一次的操作处理消息的确认信息返回。Topology的数据源备份它生成的所有数据记录。当所有数据记录的处理确认信息收到,备份即会被安全拆除。失败后,如果不是所有的消息处理确认信息收到,那数据记录会被数据源数据替换。这保障了没有数据丢失,但数据结果会有重复,这就是at-least once传输机制。

Storm采用取巧的办法完成了容错性,对每个源数据记录仅仅要求几个字节存储空间来跟踪确认消息。纯数据记录消息确认架构,尽管性能不错,但不能保证exactly once消息传输机制,所有应用开发者需要处理重复数据。Storm存在低吞吐量和流控问题,因为消息确认机制在反压下经常误认为失败。

Spark Streaming:Spark Streaming实现微批处理,容错机制的实现跟Storm不一样的方法。微批处理的想法相当简单。Spark在集群各worker节点上处理micro-batches。每个micro-batches一旦失败,重新计算就行。因为micro-batches本身的不可变性,并且每个micro-batches也会持久化,所以exactly once传输机制很容易实现。

状态管理

大部分大型流处理应用都涉及到状态。相对于无状态的操作(其只有一个输入数据,处理过程和输出结果),有状态的应用会有一个输入数据和一个状态信息,然后处理过程,接着输出结果和修改状态信息。

因此,我们不得不管理状态信息,并持久化。我们期望一旦因某种原因失败,状态能够修复。状态修复有可能会出现小问题,它并不总是保证exactly once,有时也会出现消费多次,但这并不是我们想要的。

Spark Streaming是微批处理系统,它把状态信息也看做是一种微批量数据流。在处理每个微批量数据时,Spark加载当前的状态信息,接着通过函数操作获得处理后的微批量数据结果并修改加载过的状态信息。

流处理框架性能

这里所讲的性能主要涉及到的是延迟性和吞吐量。

对于延迟性来说,微批处理一般在秒级别,大部分原生流处理在百毫秒以下,调优的情况下Storm可以很轻松的达到十毫秒。

同时也要记住,消息传输机制保障,容错性和状态恢复都会占用机器资源。例如,打开容错恢复可能会降低10%到15%的性能,Storm可能降低70%的吞吐量。总之,天下没有免费的午餐。对于有状态管理,Flink会降低25%的性能,Spark Streaming降低50%的性能。

也要记住,各大流处理框架的所有操作都是分布式的,通过网络发送数据是相当耗时的,所以进了利用数据本地性,也尽量优化你的应用的序列化。

还有我司同学做的比较spark streaming与storm调研对比

技术团队做的比较Spark Streaming 与 Storm 比较

results matching ""

    No results matching ""