vivo 超大数据规模分布式消息中间件架构演进实践

大数据
新一代数据架构覆盖数据全链路,包括数据的采集层、接入层,以及下游的海量计算、分布式存储等。本次分享题目为 vivo 超大数据规模分布式消息中间件架构演进实践。

一、vivo 架构演进实践

1. 业务背景

首先来介绍一下相关业务背景。

图片

上图展示了 vivo 互联网大数据场景下全链路架构。以终端用户为起点,经过统一的数据集成,数据进入统一数据接入层,再通过 ETL 的海量计算和实时的数据分拣,将数据存入实时数仓和离线数仓,最终赋能到下游的业务产品。这个架构是当前主流的架构体系。在此架构中分布式消息中间件(Kafka/Pulsar)致力于为用户提供一套在大数据场景下高吞吐、低延时、高可靠、高扩展、全托管、安全的统一数据接入服务和实时数仓服务。

我们认为,考虑 AI 大模型的变与不变,核心在于数据,对数据稳定性要求的日益提高也使得我们开始思考下一代消息中间件应该是什么样子的。图中展示了 vivo 的技术演进迭代路径。vivo 消息中间件项目从 2019 年立项,2021 年完成功能建设,项目进入快速发展的阶段,2022 年项目达到了成熟运营的水平。项目建设过程中,2021 年我们发现 Kafka 在超大数据规模场景下存在一些架构上的缺陷,所以我们团队开始对下一代分布式消息中间件 Palsar 进行调研,与之相关的项目在 2022 年正式立项。截至今年,经过一年的运营和引流,目前每天 Palsar 集群处理的消息量在 2 万亿左右。

图片

统一数据接入层的上一层是统一数据采集层。vivo 在统一数据采集层会做一些高可用的保障。

(1)离线链路写 HDFS 实现分钟级主备切换

对于离线链路,做到了分钟级的主备切换,这依赖于 manager 服务能实时检测HDFS 集群的健康状态并实时同步到 agent,当 HDFS 集群出现故障时,同时通知到上游的统一采集层以及下游的 ETL,在分钟级的时间段内切换到备份集群上,实现在离线链路上的高可用保障。

(2)高优业务双链路容灾快速切换

目前对于数据接入有实时链路和离线链路两套数据接入架构,并会对实时链路和离线链路接入的数据做分钟级对照校验,从而实现实时和离线两条链路保障高优业务的容灾切换。

2. 运营现状

图片

目前 vivo 内部 Kafka 集群日均处理消息数量达到了 20 万亿+,Palsar 集群日均处理消息数达到了万亿+,在这样超大数据规模的场景下,我们还与业务团队签署了 SLA 四个 9 的高可用的保障协议,以确保用户的高可用,同时实现降本增效。如图所示,经过三年建设,我们的单机利用率提升了 210% 左右,Kafka 集群机器规模增长 52%,接入数据量增长 340%。

3. Kafka 部署架构

图片

针对 Kafka 的部署架构,主要有两种方案。方案一是使用大量物理机搭建一个超大规模的集群。方案二是以几台或几十台物理机为一个单位建构若干小集群。这两种方各自有其优缺点,方案一有点类似于在互联网行业里的单体应用,而方案二更类似于微服务架构。实际两种方案的选择没有绝对的好坏之分。

方案一有几个优点:一是它的资源利用率较高,因为它不需要对每一个小集群都预留一定的 buffer;二是当集群规模比较大以后,它应对数据业务方的业务流量突增能力比较强,而不至于在业务流量突增时,由于集群负载较高,进而反压到客户端,影响用户;三是用户体验较好,对于业务团队只需维护一套集群的连接信息,无需根据业务场景自己维护、辨别、使用不同的集群连接信息。但同时方案一也带来了一些问题:一是其运维难度系数较高;二是一旦出现问题,故障影响面较广;三是集群的资源隔离性较差。

方案二,这种小集群部署的优点:一是因为每个集群规模较小,运维比较简单,但如果总体集群的总数达到数千个,相应的运维投入也会随之变高;二是当集群出现故障时,只会影响自己集群内部,故障影响范围较小;三是集群跟集群之间严格做了物理隔离,资源隔离性非常好。其缺点,一是每一个集群都会需要一部分 buffer 来应对业务流量的突增,资源利用率较低;此外在应对用户流量突增及用户体验等方面的能力都会较差一些。

综合考虑上述两个方案的优缺点,在超大数据规模下,如果采用方案二,需要搭建和运维的 Kafka 集群数量可能达到上千个,单纯靠人力运维将会是一个较大的工作量,所以 vivo 采用的是方案一的部署架构,并针对其缺点进行了改进。

(1)引入资源组,实现集群内节点逻辑隔离

图片

首先针对大规模集群部署方案资源隔离性较差这一问题,通过在集群内部引入资源组实现集群内节点的逻辑隔离。资源组之间是逻辑隔离的,不会相互影响,从而实现了在同一个集群内部的机器逻辑隔离。

(2)基于项目维度实现智能动态限流

图片

第二个问题是限流,限流本质是通过牺牲一部分客户端的可用性来保障服务端的可用性。Kafka 集群的限流有几种方式,第一种是基于客户端的(如基于 client ID),还有一种是基于用户端的或称基于项目的限流。vivo 公司内部使用的是基于项目维度的限流。这种方式存在一些缺点,首先业务受损严重,一旦出现了限流的情况,用户的流量就进不来,进而导致用户端被反压,数据发送失败或消费延迟相关的问题;其次当限速阈值设置不合理时,会存在资源利用率较差和集群可用性风险,限速阈值限制较高时,集群的可用性得不到保障,限流阈值较低时,集群资源利用率较低;第三用户会经常收到限流告警信息,用户体验较差;第四用户收到限流告警后需要运维同学凭经验综合分析是否可以调整限速以便快速恢复业务,运维成本较高,因为限流阈值不支持自动进行动态调节,业务会频繁与 Kafka 组件的管理团队进行沟通去调节这个阈值。

图中左下方的案例示意了简单根据项目数量设定限流阈值时可能出现的一种情况。假设一台单机的流量阈值是 100M/s,A、B 两个项目均运行在这台单机上,对应每一个项目分配到的限流阈值是 50M/s,当流量超过限流值 50M/s 后,红色阴影区域内的流量都会被牺牲掉。但实际上多个项目之间存在流量的波动周期的差距,因而不能采取一刀切的方式根据项目数量平均分配限流阈值。

针对这种情况,一种优化思路是对在波峰期的项目 A,寻找其同一个资源组内当前流量值较低的项目 B,从项目 B 把流量借过来,动态调高 A 项目的限流阈值,当 B 项目流量增长后,再把流量还回去。基于这样的优化思路,我们团队基于统一的监控平台、统一的指标采集平台,以及统一的告警检测平台实现了智能动态限流。

图片

智能动态限流需要解决限流粒度、限流阈值、可用性以及资源利用率这四个维度的平衡。这里我们引入了公司内部提供的统一告警检测平台。在指标采集过程中可能需要做一些降噪处理,解决数据的突刺现象,基于告警检测平台统一检测的算法可以屏蔽掉异常告警,获得精准预警,然后基于此再去做动态的限流调整。这套智能动态限流方案使 vivo 公司内部因为限流导致业务受损的情况降低了 90%。

(3)流量均衡与资源均衡

图片

Kafka 的架构设计上分区与 broke 节点强绑定,默认的分区分配算法不能很好的解决分区均衡性的问题,无法实现动态调整。如上图所示,Kafka 默认的分区轮询分散算法会产生两种情况。第一种情况下,因为无法保证每一个 topic 的分区数量都能与 broker 成正比,会出现一些 broker 上分配的分区数比较多,一些 broker 上分配的分区数比较少的情况。另外一种情况是,即使我们保证了在不同的 broker 上分区数量是尽可能一致的,但是由于 Kafka 的分区是有状态的,所以说它会存在一些分区流量比较大,而另一些分区的流量比较小。这两种情况都会使 broker 之间产生很大的流量差异。

我们在做这种大规模的物理机集群部署时,都会考虑通过一台物理机挂载多块磁盘从而提高物理机的 IO 效率。但 Kafka 的底层架构设计上一个分区与 broker 的某一块磁盘绑定,无法充分发挥多块磁盘的 IO 效率。

图片

如上图所示,假设当前有两个 topic,其中绿色 topic 的流量是 100MB/s,红色 topic 的流量是 300MB/s。在 broker1 上挂载了 data1 到 data4 共 4 块磁盘,但是当前 Topic 分区 P1-L 的数据只能写入到磁盘 data1,这带来一个致命的缺陷,当磁盘 data1 出现 IO 瓶颈时,即使 data2 或者 data3 是空闲的,也没办法将数据转写到 data2 或者 data3 的磁盘上面去。这样就导致当某一块盘上出现多个较大分区时,它的磁盘 IO 瓶颈就会成为这一台机器的性能瓶颈,没办法很好地利用起多块盘的 IO。

图片

基于该缺陷,我们团队也做了很多思考。首先,在当前分区均衡算法上注入一些与主机相关的负载因子,使其去做更好的分区计划。在第一期,我们注入了磁盘容量、CPU、流量等负载因子,使算法能生成更好的分区分散计划。在第二期的分区均衡算法优化上,注入了均衡性相关的参数,如分区分散均衡、副本分散均衡等,使其能够更好生成更加均衡的分区分散计划。在跨机房方面我们也做了一些改进,实际情况中可能不需要所有的业务都实现跨机房容灾,但是所有业务都必须实现跨交换机容灾。每个公司的机房建设不太一样,我们公司的机房建设中,交换机是单上联的,所以在交换机这个层面可能存在单点故障的风险。因此在后面交换机风险改进方案里,我们也将交换机信息注入到分区均衡算法中,从而规避交换机的单点故障风险。未来我们也在思考跨机房实现分区分散,机房与机房之间的网络延迟降低到可以接受的范围之内可轻松实现。

图片

其实 Kafka 核心架构带来的问题远不止上述提到的几点,尤其是在超大数据规模场景下,问题表现得尤为明显。第一是 Kafka 资源利用率比较低,因为 Kafka 无法根据未来的流量增长进行预测,所以也无法实现长期的均衡。第二是 Kafka 故障恢复慢,因其分区数据是和磁盘绑定的,当进行数据迁移时,迁移周期会比较长,尤其当一块磁盘上有几 T 数据或一台 broker 上有几十 T数据时,磁盘故障需要做踢盘或 broker 节点故障需要做下线时,需要迁移几 T 或几十 T 数据。数据迁移过程中还需要考虑不能影响实时业务数据的写入,迁移周期一般都是周级。第三是 Kafka 故障率高,均衡时会做数据的拷贝、消费延迟时会读磁盘数据导致磁盘 IO 受到影响,一旦出现这个问题,对实时数据的写入也会存在影响,所以它的故障率会比较高。第四是无法快速响应业务增长,当集群扩容后需要先对分区做一次均衡,然后做流量历史数据的迁移,全部迁移完后才可以将实时数据写入到扩容机器上,整个扩容的周期较长。一般对于 Kafka 集群的扩容是以天或者以周为单位进行的。

图片

基于以上所有的缺陷,我们发现核心问题在于 Kafka 数据存储架构设计上,无法通过扩展能力的建设解决上述缺陷。Kafka 的架构设计没办法做到存算分离、分层存储、分散存储等。所以我们考虑要对整个分布式消息中间件做引擎的升级,解决方案有两种,第一是基于 Kafka 的原有架构进行改造,第二是引入下一代的云原生分布式消息中间件 Pulsar。

二、Pulsar 核心架构升级

图片

Pulsar 是基于云原生理念设计的分布式消息流组件,它在存储层和计算层实现了存算分离,并且其同一分区的数据可以分散成多个 segment,每个 segment 可以落到不同的 bookie 存储节点上,实现了在存储节点上的分散,也可以实现在磁盘之间的分散。Pulsar 的核心架构具有以下几个核心优势:

  • 存储与计算分离。
  • 存储、计算独立扩展。
  • 秒级扩缩容。
  • 秒级的故障恢复。
  • 屏蔽硬件故障。

图片

Pulsar 支持在硬件上面的秒级恢复。如图所示,左边是 Kafka 的架构,当磁盘发生故障后,必须去副本所在的 broker 节点把数据先同步一份,之后才可以把实时流量数据写到我们的 broker 磁盘上。但是数据同步的周期性较长,可能要一天或者更长的时间,在这段时间之内,如果分区的副本数设置为 2,分区都处于单副本运行的高风险状态。而 Pulsar 可以实现秒级的恢复,因为它不需要去做历史数据的同步,分区流量可以秒级的转移到其他磁盘或其他的 broker 上。Pulsar 后台有一个缺副本的发现机制,补齐历史数据。在实时场景下,我们更关注对实时写入的数据做冗余的高可用保障,反而对于历史数据同步性的要求不高。

图片

Pulsar 具备秒级扩缩容的能力,这主要基于它存储与计算分离的架构。因其存储计算分离,它的 broker 和 bookie 也是分离的。一个无状态的服务实现秒级的扩缩容是很简单的,基于 K8S 或者 docker 来讲的话,只需要弹一个 Pod,然后去拉取一个镜像,重启后就可以完成秒级的弹性伸缩。Pulsar 在 broker 层是无状态的设计,使其它天然具备了秒级扩缩容能力。在 bookie 层,可以将其看作存储层,它也可以做到秒级的扩缩容,只要扩容 bookie 节点被 broker 感知到以后,可以实时地将 broker 的流量写到 bookie 节点上进行持久化的存储。

图片

Pulsar 核心架构优势还体现在客户端内存分配上。在 Kafka 的架构下,尤其是在指定 key 的场景下,如果 broker 节点出现宕机或者响应缓慢的情况,就会反压客户端,导致客户端 buffer pool 被故障分区的数据打满,进而导致雪崩的现象。因为一个分区不可用,导致整个 topic 的所有分区都不可用甚至当前 producer 涉及的所有 topic 的所有分区都不可用。左下方是我们公司内部一次故障时的流量监控曲线,可以看到,Kafka 单个 broker 节点一场后,整个资源组里所有 topic 的流量都无法写入,就是因为故障节点直接把客户端内存占满后,正常分区的数据没办法分配到内存,无法写入到服务端。对于这个问题,Pulsar 做了架构上的改造。客户端内存的隔离粒度做到了分区级,当右上图 broker2 出了问题,即使分区的 deque 被打满以后,也不会去占用整个客户端内存,消息还是能通过其他可用分区发送出去。右下方图展示了我们故障演练的情况,它可以秒级恢复到其他 broker 节点上。

Pulsar 和 Kafka 的性能对比可以参见下图。

图片

三、高可用保障及可观测

高可用保障是我们的生命线,没有高可用,其他一切工作都是没有意义的。

图片

高可用保障主要围绕故障展开,包括事前预防故障的发生、事后快速恢复,以及故障解决后应该怎样复盘并提出改进措施。我们在事前,会基于对技术架构的理解做故障演练和测试,在流程规范和平台工具方面进行保障。事中最核心的是整个监控告警体系,在此基础上进行质量运营,及时发现、响应,最终支撑组件在超大数据规模下的高可用。

图片

我们的监控告警体系可以分为多个维度。在基础设施层,实现了对机房、网络、交换机的监控;在主机层,实现了对 CPU、内存、磁盘流量相关的监控;在服务层,尤其是在 Kafka 的服务层,会对 GC、warning 日志或 error 日志进行监控告警;在用户层,支持限流告警、延迟告警以及流量突增的告警。以上都是为了在故障发生前一步告警,以便及时介入人工干预,避免故障发生。所有告警指标的采集都由统一检测平台,经过降噪,统一发出异常告警,触达我们的用户、运维以及管理人员。在进行监控告警体系建设时,比起频繁告警,我们更重视告警的精准度,尤其是在有限的人力运维情况下,太多的告警会导致运维人员对告警的敏感度下降,忽视关键告警,最终导致故障的发生。

图片

因为人具有主观能动性,人为因素是导致故障的重要诱因之一,所以我们需要一套贯穿于整个事前事中以及事后的规范体系来规范人的行为。包括事前对代码管理、方案和代码的评审、发布和变更、变更灰度优先级、值班等的规范,事中对故障处理的规范、预案执行的规范、日常运维的规范,事后故障的管理规范,以及故障的复盘规范等,通过一套全生命周期的规范来尽可能规避人为因素导致的故障。

图片

Pulsar 作为新一代云原生分布式消息中间件,架构设计非常优秀,但是作为新兴组件缺乏长期超大规模数据处理的验证,在稳定性上也存在较多问题。基于我们平台的高可用体系,以及监控告警体系的实践,经过故障演练和自测,我们在近两年间解决了 Pulsar 27 个严重影响稳定性的问题,19 个重要问题,44 个一般问题。目前在达到 2 万亿日均处理消息量的情况下,我们做到了全年无故障。

图片

可观测对于用户来讲,可能关注的是 topic 的流量指标,尤其是 top 级别的流量指标,根据观测结果决定是否需要对某一些 topic 做治理,或者判断该 topic 消耗的成本是不是与它所带来的收益正相关。此外我们还会关注消费延迟指标。我们的可观测平台,能够实时定位到用户某一台 IP 节点上的机器出现消费延迟的情况,方便我们在数据消费延迟的时候能够快速定位到问题。

图片

我们的告警实现了从数据接入,到检测配置,再到告警配置以及告警处置四个方面的闭环,相关的配置都可以通过平台进行配置操作,对告警的处置、告警的回调、告警的详情都可以通过可观测的告警平台进行查看。

图片

最后对于运维管理人员而言,我们更关注的是当遇到故障后如何快速恢复,以及是否能通过一些日常巡检来发现当前系统存在的异常。因此我们在运维管理方面,也实现了可观测,包括对 topic 的流量监控,对整个资源组的 GC 监控,以及对延迟的监控等。

四、vivo 架构未来规划

图片

最后谈一下 Pulsar 未来规划。Pulsar 作为下一代云原生的分布式消息中间件一定会成为未来的主流。因此我们对其分层存储以及函数式计算、全链路监控会重点规划。另外如何应用 Pulsar SQL,以及 Pulsar function 使其更好地赋能业务也是我们未来需要去考虑的一些点。最后,关于 Pulsar 容器化的问题我们也有一定的思考,前文在介绍 Pulsar 部署架构的部分提到了大量小集群运维,采用纯人力的运维不太现实,如果说未来能够实现容器化,由容器化来帮助我们做集群管理,就能大量节省运维人力成本。

责任编辑:姜华 来源: DataFunTalk
相关推荐

2023-01-11 21:11:37

RabbitMQRocketMQ消息中间件

2024-03-28 12:55:00

消息中间件RocketMQ

2017-12-04 09:00:00

金融开源软件分布式消息中间件

2021-11-14 16:07:35

中间件阿里Seata

2019-08-12 11:00:59

美团网MySQL数据库

2023-06-29 10:10:06

Rocket MQ消息中间件

2023-10-24 07:50:18

消息中间件MQ

2022-09-21 16:09:28

消息中间件

2021-12-14 10:39:12

中间件ActiveMQRabbitMQ

2022-11-02 10:08:46

分布式高并发消息中间件

2015-08-11 11:16:36

淘宝中间件

2018-04-03 09:27:42

分布式架构系统

2016-01-12 14:59:40

分布式存储分布式存储架构

2013-03-22 14:44:52

大规模分布式系统飞天开放平台

2019-11-12 08:40:03

RocketMQ架构

2023-06-29 11:06:46

vivoID服务器

2023-05-08 08:09:26

路由元信息谓词

2022-08-09 08:31:29

RocketMQ消息中间件

2022-03-25 08:40:32

分布式架构

2015-06-19 07:50:47

点赞
收藏

51CTO技术栈公众号