聊一聊实时计算系统设计

本文做者:AIOps智能运维算法

做者简介数据库

饿马摇铃    百度云高级研发工程师后端

 

负责百度云智能运维产品(Noah)数据采集和计算方向架构设计和研发工做,对分布式系统架构有必定实践经验。网络

 

干货概览架构

本文是我在实时数据计算系统的设计、开发、运维生涯的一部分经验总结。主要介绍一些设计思路和常见问题的解决方案,不关注具体计算框架的使用。并发

本人主要致力于监控系统数据计算方向,主要业务场景有:监控数据的ETL、数据汇聚、分析、异常检测等。因为监控系统对时效性有较高需求,因此咱们的计算系统更偏向实时系统,根据业务场景的不一样,延迟从数百毫秒到分钟不等。下文提到的计算架构更可能是指整个计算处理通路,主要以监控场景下的系统设计为例,相信与其余场景下的架构也有相通之处。负载均衡

文章从如下几个方面展开。框架

首先,在第1节,咱们简述不一样数据规模和场景下,监控系统计算架构的可选方案。在公司、业务发展的不一样阶段,主要矛盾不一样,可以投入人力物力资源不一样,须要选择合适的架构方案。less

实时计算系统的设计有一个核心问题:如何同时知足高时效性和数据准确性?在现实环境中,高时效性和准确性很难同时达到,第2节中介绍了Watermark机制以实现二者的平衡。运维

第3节介绍百度监控系统的实时计算系统架构,描述了其基本组成、思路和实现中一些常见问题的解决方案。

最后,简单讨论了实时计算系统可用性建设

监控系统计算架构选型

对于包含数百到千级别节点的小集群,数据规模有限,全部采集、存储、计算逻辑均可以集成在一个模块中实现,这种多为领域专用系统。监控系统中,典型的有Prometheus,其采用单服务节点架构,提供简单的HA模式进行容错,这种架构的优势是部署使用简单。受限于单机资源,适合部署自治的多个实例,每一个实例监控不一样服务。大规模集群状况下,要实现全局的监控,须要合并多个监控实例的数据,在配置分发、可用性、容错、自动化部署管理等方面都须要更多的工做。从开发角度考虑,因为功能耦合严重,不利于开发升级。

比起领域专用系统,还有一种架构是使用通用性更强的OLAP系统来实现实时或者近实时的计算功能,如TSDB、ElasticSearch等系统都有必定的聚合计算能力。这些分布式系统都有水平扩展能力容错能力,但难以实现复杂业务计算,同时延迟不可控,复杂查询或大批量数据查询的延迟可能会达到分钟级别。

更多的状况下咱们采用存储计算分离的方案,以便存储和计算的各自演进和平台化。一般由一个提供精细查询能力的存储服务与一个计算模块组成。计算模块根据计算规则从存储系统中拉取数据并进行计算,这个架构的瓶颈在于存储系统可以支持的查询规模。根据咱们的经验,基于精心设计的内存数据库集群,可以承受百万级别的并发查询。这种架构下计算任务多为周期性调度,当查询性能降低时会形成任务的堆积。这个模型不方便处理延迟数据,须要必定机制预测数据完整时间,调度任务进行重算,任务调度的复杂度高。基于索引查询的计算系统的延迟取决于计算轮询的周期,适用于聚合类的涉及时间窗口的运算操做。

更高数据量和计算规则的状况下,流式计算是一个天然的选择,下降了写存储、索引、查询的消耗,计算延迟大幅下降。

当数据量进一步上升,须要的网络吞吐、计算能力骤增,后端的算力难以跟上数据量的增加。这时候能够将计算能力分散到全链路,将计算提早到数据产生端。在监控系统中,经过在采集端进行预计算和ETL操做,提取或整合有用信息,对于实时日志采集,能大幅度下降传输到后端的数据量。放到更大的视角上,这种将算力下放到数据源的思想,是目前大热的边缘计算的一个主要思路。

近年来,以AWS Lambda为首的Serverless计算架构获得了更多的重视。这个模型将计算抽象为事件以及触发的计算逻辑,计算逻辑实际由框架调度、分配资源执行。用户只须要编写计算逻辑,而不用关心可用性、可扩展、负载均衡等后端代码,极大的下降了开发成本。经过按需调度,自动扩缩容,业务运维方再也不关心容量规划等问题。私觉得当前常见计算框架的Serverless化是一个值得尝试的方向。目前的Serverless框架还存在不少问题,例如调度初始化虚机、容器的成本高,缺少状态存储等,比较适用于无状态的计算。

通常来讲根据场景需求,一般对不一样的架构会组合使用。例如百度监控系统内部是以流式计算与近线计算相结合的方式提供服务的,近线计算从时序数据库(TSDB)中拉取数据进行计算。对于Trace、在线数据分析等具备比较复杂查询需求可是相对比较低频的操做,更适合基于索引查询的架构。

准确性与时效性

对于实时系统,咱们对时效性有更严格的需求,可是一般高时效性伴随着低准确度,两者不可兼得。在分布式环境下,自然存在长尾的延迟数据,这多是原始数据自身的延迟,也多是由采集点异常、网络延迟、网络抖动、数据通路中负载等形成的延迟。数据源越多,分散的越广,这个长尾效应就会越严重,等待数据完整所须要的时间也越长。咱们须要在最终数据的准确性和时效性间作折中。

不一样场景对二者的需求不一致,一般来讲报警、自动止损等操做须要最高的时效性,可以容忍必定的精度缺失,在审计、订单等数据上咱们更多的追求准确性,时效性能够适当放宽。解决这个折衷的经常使用机制是Watermark

Watermark是在数据流中增长标志信息,用以指示一个窗口内的数据已经“彻底”到达,能够进行计算。

示例:假设咱们要统计10s内到达的事件数目,以事件时间(Event Time,即事件携带的时间,多为事件产生时间)做为时间基准。以下图所示,横线为Wall Time时间线,单位为s。圆球表示事件,圆球里面的数字为事件时间,其虚线指向产生时间,圆球正对的Wall Time时间线上的点为被计算系统处理的时间(Process Time),两个时间之间的差值为实际延迟。每一个事件都或多或少存在延迟,其中数字为45的圆球延迟最大。对于事件时间[40, 50]这个汇聚窗口,假设咱们将Watermark线画在53处,则咱们认为数据在53以前已经彻底到达,已经接收到的那些数据能够参与汇聚,Watermark以后到来的事件则忽略。

具体怎么肯定Watermark一般取决于需求,对于数据点数量级比较稳定的场景,能够设置一个到达的数据点的比例,在某一个判断周期内,只要到达的数据点比例知足阈值则可添加Watermark。主流开源计算框架对Watermark的实际定义不尽相同,具体使用参考对应计算框架的定义。

私觉得Watermark机制隐含的一个重要思想是将数据准确性的定义交还给用户,让用户决定。产品或者架构上的功能,存在多种方案的状况下,选择最泛化的那个方案,暴露出参数而后让用户来选择,不要本身替用户作决定。固然为了简化实现成本和用户使用成本,能够设置固定的一些选项,并选择一个需求最大的做为默认值。

一般Watermark以后的过时数据点会被丢弃。常常的,除了知足高时效性需求外,咱们也须要在以后保证数据的最终准确性,即在必定时间段以后的数据是准确的。经常使用思路是部署两套计算系统,流式计算用以实现低延迟可是准确性低的需求,批量计算用于补偿计算数据的准确性,这就是Lambda架构。最典型的使用Lambda架构的场景是从日志中统计PV/UV,一般是一个流式采集系统和流式计算框架进行实时的PV/UV计算,同时有一套离线系统,按期拉取原始日志,经过批量计算系通通计准确的PV/UV数值。一般这种架构的缺点是两套系统的资源消耗,开发运维成本高

当前主流计算框架如Spark和Flink对流式和批量计算进行了统一抽象。能够必定程度下降两套系统的开发运维成本,下降了不一样框架的开发运维成本,两次计算的的资源消耗依旧存在。

对于知足交换率和结合率的算子,如常见的统计方法(MAX/MIN/SUM/COUNT),在存储侧支持相同运算的状况下,能够将两次运算合并成一次。咱们内部称这个方案为多版本,即数据生产一部分就汇聚一部分,每次汇聚产生一个数据版本,由存储在写入时合并,或者在查询时合并。本质上,这是将汇聚的功能迁移了一部分至存储。

百度监控实时计算系统架构

百度监控系统的实时计算系统承担了监控系统数据处理栈的主要计算功能,天天处理数千亿条消息。本节在实际系统的基础上,进行了必定的抽象,介绍一个较为通用的系统架构。

如图所示,架构主要包含如下组件:

  • 接入模块:包括数据拉取和数据接收,前者主动拉取数据,后者接收由上游模块推送的数据。

  • 分发模块:根据配置的计算规则,过滤订阅的数据,并根据调度策略、集群状态将规则对应的数据分配到一个或多个处理单元进行计算。

  • 处理单元:包括一个物理计算模块和对应的输入输出消息队列。物理计算模块执行实际的业务计算逻辑,不一样处理单元间能够是同构的也能够是异构的,根据不一样的业务场景和用户需求,可使用不一样的技术栈。

  • 控制模块:接收用户提交的计算规则和管理操做,分配调度资源,产生对其余模块的控制信息。

  • 数据推送模块:拉取计算结果,根据计算规则将数据分发到下游模块。

每一个物理计算模块都对应一个输入和输出消息队列,以将数据接入、据输出与计算层隔离,增长一个新的第三方系统的交互不会影响计算功能。升级变动物理框架不会影响其余组件。

因为大数据处理框架,在其数据规模、节点数目达到必定规模时,其处理性能以及异常恢复速度都会降低。咱们将一个固定计算能力以及配套的资源(如消息队列)抽象为一个处理单元,每一个处理单元处理一部分的数据,取决于计算功能的物理实现,这个处理单元能够对应一个集群或者一个做业。一个处理单元的具体规模取决于具体的技术选型和硬件条件。确认处理单元的好处是便于容量规划,能够以一个处理单元做为粒度进行扩缩容。若是须要嫌粒度过大,分层次进行扩缩容,先在一个处理单元内部扩展直到极限,以后启动一个新的处理单元。

实现中须要考虑如下几个点:

1 负载均衡

负载均衡发生在系统的每个层次。

数据接入层与和分发模块之间的采用随机发送的策略以均衡分发模块的压力

数据拉取和数据推送模块须要动态平衡每一个实例上的拉取或推送任务,经常使用的策略是一致性哈希,以每一个任务的实际数据量做为权重。

计算过程是最须要考虑负载均衡的场景,聚合计算一般会遭遇数据倾斜问题,即某些key的数据量远大于其余,这就形成汇聚该Key的任务OOM。下面提供几种经常使用解决思路:

  • 对于知足交换率和结合率的计算方法,如MAX/MIN/SUM/COUNT等,能够添加多层预聚合,下降最终聚合的数据量。预聚合层次间能够随机方式,最终汇聚以前按Key哈希。

 

  • 负载均衡或者说任务调度对应Bin Packing等一系列等价的最优化问题。这些问题是NP-Hard的,能够经过近似算法来逼近,典型的有First Fit算法。实现时通常须要自定义计算框架的分区逻辑,如Spark能够经过自定义Partitioner来实现。

2 控制节点扇入扇出规模

不管是具有状态副本的分布式存储系统、基于DAG的分布式计算系统仍是Stateless的接入集群,当集群规模持续增大时,节点间交互会显著增大,最差的状况下全链接,扩容节点会有指数级的链接增加。这会严重影响系统对水平扩容能力,扩容带来的收益跟不上单机资源消耗的增加。

对于分布式系统,经过控制集群或者做业规模能够实现必定程度的控制,对于接入模块,能够限制下游链接到上限。

可用性

对于可用性要求高的服务能够多集群热备的方式,在上述架构中,能够经过运行多个并行的处理单元处理相同的数据流来实现。也能够部署整个集群,经过采集端多写的方式复制数据流。最后须要根据输出结果的延迟、准确度等判断策略选择一个计算结果输出。

服务无损升级,能够经过启动一个新的计算单元,并行处理数据,待数据“预热”后,进行切换。

在部署时,接入模块尽量的靠近数据源,保证每一个地域一套。系统多地域部署,每一个地域内部模块间尽可能自治。接入端发送数据时优先发送本地域,异常时尝试其余地域。模块间交互能够打QoS(服务质量)标签增长网络优先级以下降网络丢包。

监控上,除了基础资源、流量等监控外,最重要的是全通路时延监控,常见方案是构造业务流量,统计在系统中的延迟。这个延迟指标一般是多维度的,根据部署和业务使用状况可能须要关注不一样地域,不一样业务,不一样处理通路的延迟。这些延迟指标,能够指示系统进行流量调度或者资源的重分配。

总  结

本文简单介绍了百度的分布式监控计算系统架构的演进和当前的实时计算架构,并提供了部分常见问题点解决思路。架构是不断在演进的,咱们的系统仅仅是“够用”,还有更多的工做须要开展,如架构的轻量化,统一易用的计算表示层,计算的自动优化等。

因为我的水平有限,若是行文中有错误,或者有须要进一步探讨的,请在留言中指出。

原文连接地址:https://developer.baidu.com/topic/show/290317

相关文章
相关标签/搜索