乐趣区

关于阿里云:RocketMQ-DLedger架构在小米的大规模实践

本文作者:邓志文,小米研发工程师,Apache RocketMQ Committer

小米消息中间件选型

小米外部的业务场景可分为两类,别离是数据业务和在线业务。

其中数据业务包含日志流的计算、剖析场景以及数据集成场景,个别应用外部自研的音讯队列 Talos。在线业务包含事件告诉、订单以及简单的异步调用场景,比方延时音讯、重试投递、死信等,个别应用 RocketMQ。

DLedger 架构是 RocketMQ 4.5 推出的全新架构,稳定性有保障。小米的在线外围业务规模微小,须要很高的可靠性保障,因而咱们最终抉择了 DLedger 架构。小米心愿用数据谈话,踊跃地拥抱社区倒退,并且咱们认为大规模落地 DLedger 既是挑战,也是机会。

Dledger 内核与优化

DLedger 架构与主从架构的次要区别在于 broker。咱们的理论部署中,单个 Broker 组部署 3 台机器(倡议部署奇数台),主节点独自部署,从节点与 NameServer 混合部署,通过 raid 形式将多块磁盘组成单块大盘。

DLedger 架构有两个外围模块:

①正本同步:主节点向从节点通过异步发送 push 申请。

②主动选主:主节点定时向从节点发送心跳,若从节点在指定工夫内没有收到心跳则触发从新选主。

正本同步的过程如上图所示:同步时 leader 节点会向从节点发送 push 申请,要求同步数据。

RocketMQ4.8 社区版本对 DLedger 做了以下两个重要优化:

  • 异步化 pipeline 模式:大幅晋升了同步双写的性能。
  • 批量日志复制:反对批量同步。然而批量同步会存在兼容性问题,从单条降级到批量的状况下会呈现不兼容。

小米外部针对批量同步进行了优化,做了兼容性革新:主从节点 BatchPush 兼容性优化,防止集群降级过程中集群不可用。具体优化内容为:BatchPush 兼容性优化,反对了 BatchPush 滚动降级;以 master 节点配置为主,slave 节点同时兼容 batch/single 申请。

咱们对 batch 同步做了性能测试,测试环境如上图右侧所示。测试后果为,开启 Batch 同步前后,极限值从 5.5w/ s 进步至 8w/s,10ms 内写入极限从 4.5w/ s 晋升至 7w/s。

DLedger 选举流程如上图所示。通过配置 preferredLeaderlds 能够指定优先选举某些节点为 leader。由 Candidate 发动投票,获取半数以上投票则成为主节点,否则从新发动投票。

故障状况下,故障复原过程如上图所示。

集群必须保障一半以上节点可用。如果从节点呈现故障,则业务无感知;如果主节点故障,则从新触发选举。主节点一旦产生故障,则会立刻进行与从节点的心跳,从节点会变为 Candidate 状态,发动新一轮投票选举,从残余存活的节点中选出新的 master 节点。

假如新的主节点并不是 PreferredLeader,则会检测 Leader 与 PreferredLeader 之间的水位差距。如果两者之间正本写入差距小于 1000 条,则会发动 LeaderShipTransfer,将 leader 的地位转移给 PreferredLeader,此时 Leader 节点不再接收数据写入。

Follower 节点接管到 LeaderShipTransfer 申请后,将节点状态设置为 Candidate,不再接管正本同步。

当 PreferredLeader 被设置为 Candidate 时,节点正本同步进度将落后于 Leader 节点,会导致 Candidate 发动投票失败。起因为正本同步落后,同时该节点 term 值大于 leader 节点,无奈从新置为 Follower,节点始终处于 Candidate 状态。

咱们对此进行了优化,在 PreferredLeader 节点接管到 LeaderShipTransfer 申请后,会跟上 leader 节点正本同步的进度,否则超时失败,防止了被配置为 PreferredLeader 的从节点数据不同步的问题。

DLedger 架构实践经验

1. 业务影响力

从 2020 年 8 月 RocketMQ 正式立项到当初,音讯规模已冲破到 260 亿条 / 天,预计 2022-Q2 可达 500 亿 / 天。

截至目前,小米外部已将多种业务自保护中间件比方 Notify、RabbitMQ 等进行了替换。

2. 性能优化

小米外部的很多业务场景都须要延时音讯,然而,RocketMQ 的延时音讯与音讯重试绑定,一旦客户端呈现大量生产失败,会导致延时性能受到影响。

小米针对上述痛点进行了优化。

此前为一个线程解决 18 个 level,level 之间相互影响。因而,咱们将 Timer 替换为 ScheduledExecutorService,每一个线程负责一个 level,使得 level 之间不会相互影响。上图右下角表格显示,革新后的 TPS 仍然较差,远不能满足业务团队的需要。

于是咱们持续进行革新,通过异步形式投递音讯,由多个线程解决一个 level,大幅晋升了延时音讯的性能,比方边读边写的性能可达 3.2w/s,相比于原先的 700/ s 有了质的飞跃。

然而开启异步投递后将无奈保障延时音讯的程序性。

3. 性能拓展

开源 RocketMQ 只有固定级别的延时音讯,无奈满足业务场景灵便延时音讯的需要。最终,咱们通过插件的形式实现了任意提早音讯,不便兼容社区后续的延时音讯,也能够轻松将其进行替换。

具体实现流程如下:所有延时音讯都发送到对立的延时 topic 里,插件将 topic 里的音讯拉到本人的 CommitLog 中,再通过异步线程将提早音讯写入 RocksDB。而后将提早音讯从 RocksDB 加载到工夫轮,由工夫轮将到期的音讯投递给业务 topic。

Pull Service 基于 Push 生产拉取音讯,可轻松对插件进行程度扩大,consumer 实例数减少时,可能依赖 rebalance 个性实现主动负载平衡。另外,应用 RocksDB 做存储,依赖 kv 个性无需对延时音讯做排序,升高了复杂度。延时音讯也是 RocketMQ 里的一环,因而也须要很高的可靠性,所以咱们基于 DLedger 实现了 3 正本,可靠性失去了很高的保障。

任意提早音讯曾经在外部所有集群上线,业务规模宏大,性能和可靠性也失去了验证。

RocketMQ5.0 以前,次要的生产模式为 Pull 和 Push。而它们实质上都是 pull 的模式,客户端须要与队列数做绑定,一个分区最多只能被一个客户端生产,一旦消费者数量大于分区数量,则会导致空转,有客户端无奈生产到音讯。同时,生产能力不同也会导致音讯沉积。此外,如果机器特地多比方有 1000 台,则队列的分区也必须为 1000 个。一旦有业务进行降级,则 1000 台机器都须要进行降级,耗时久,且降级时频繁高低线会对生产造成很大影响。

RocketMQ5.0 推出的 POP 生产模式能在肯定水平上解决上述痛点。该模式下,队列可被多个客户端生产,客户端无需进行 rebalance,高低线也不会相互影响,生产更平衡。即便有 1000 台机器,可能只须要几个分区、几个队列。

但 RocketMQ5.0 的 POP 模式依赖了内置的 level 延时,因为 level 不够准确,因而在客户端生产特地慢的场景下会呈现生产反复的问题。此外,POP 模式只能在 PushConsumer 里应用。

因而,咱们对 RocketMQ5.0 的 PoP 模式进行了优化,应用秒级延时音讯,并反对了 PullConsumer 场景。优化后的 POP 模式已在小米外部全集群上线,POP 生产数量超 10 亿 / 日。

咱们还基于 Static Topic 实现了动静负载平衡。

集群负载变高当前须要进行扩容,然而须要人工进行运维,手动地将流量高的 topic 从旧节点上迁徙至新节点。而基于 Static Topic 实现了动静负载平衡后,新的节点退出后可能主动将不同 broker 组上的流量进行平衡。

它蕴含两个级别的平衡策略:

  • 磁盘平衡:按天级别统计 TPS 和检测负载。RocketMQ 中无奈删除 topic,因而只有按 TPS 统计,即可大略统计出不同节点磁盘的比例。
  • TPS 平衡:按小时统计 TPS 和检测负载。

如上图,有四个 broker 组,不同 broker 组之间的流量阈值设置为 5k/s,一旦超过 5k/ s 则须要做 rebalance。新建两个 topic,其中 topicA 有 3 个队列,topicB 有 5 个队列。

新建 topic 的调配策略为:先按 TPS 对 Broker 进行排序,再将 Topic 所有 queue 依照 Broker 程序循环调配。

最终后果如上图:topicA 的三个队列别离调配在 BrokerA、BrokerB、BrokerC,topicB 的五个队列别离调配在 BrokerA(2 个)、BrokerB(1 个)、BrokerC(1 个)、BrokerD(1 个)。

随着流量进入 topic,势必会造成 broker 组之间呈现流量差距。如上图,四个 Broker 的流量别离为 13k、9k、9k、4k,已达 rebalance 阈值,因而须要进行 rebalance。

Balance 策略如下:

① 依照 TPS 对 Topic 进行由高到低的排序——排序后果为 TopicB、TopicA。

② 依照 TPS 对 Broker 进行由低到高的排序——排序后果为 BrokerD、BrokerA、BrokerB、BrokerC。

③ 按 TPS 由高到低对 Topic/queue 进行重新分配——首先调配 TopicB,再调配 TopicA。

④ 调配策略:按 TPS 由低到高对 Broker 循环调配,计算出每个 Broker 调配的 queue 个数——后果为 BrokerA 上的一个队列挪动至 BrokerD。

⑤ 查看 Broker 以后调配的 queue 个数,对 queue 进行迁徙。

⑥ 依照上述逻辑循环,直到流量低于 Broker 阈值。

咱们对监控、日志、限流方面也别离进行了欠缺。

最开始咱们应用小米外部的监控平台进行监控和报警。现在,小米已将 Prometheus+Grafana 链路买通,有了更丰盛的图表组件,可能提供更丰盛的查问和报警。

以往小米外部并没有对日志进行收集和监控,如果服务呈现抖动,会在机器上查看日志。然而随着机器的减少,查看日志的老本也逐步变大。此外,日志可能提前裸露某些问题,因而咱们将 ElasticSearch+Grafana 买通,既对立了日志搜寻的入口,又减少了日志的监控能力。

Broker 尽管有自我爱护,但仅针对集群级别。很多业务会应用雷同的集群,为了保障不同集群、不同业务之间互不烦扰,咱们减少了 topic 级别的限流能力,不会影响 topic 失常的业务逻辑,只会在异常情况下触发限流,既爱护了 broker 也爱护了其余业务。

4. 灾备

小米的很多业务对可靠性要求特地高,因而须要多机房做灾备。

咱们目前有三个灾备计划:

  • 多机房多活。
  • 跨机房互备。
  • 双机房热备。

多机房多活:在多个机房部署 Broker 组,每个 broker 组部署在同一个机房。业务发送流量时,三个 broker 组都失常工作。其中一个 broker 组呈现问题后,通过负载平衡主动将流量导到另外两个 broker 组上。

该模式的缺点为 broker 须要保留肯定的 buffer 的,否则切流之后可能导致宕机。

跨机房互备:在多个机房部署 broker 组,每个 broker 组部署跨多个机房。有机房呈现问题时,其余两个节点仍旧可用的,集群也可用。客户端无需进行任何革新,不须要本人实现流量平衡,且易于保护。

双机房热备属于备选计划,单集群三机房部署,双机房应用 Replicator 同步。

将来布局

小米对 RocketMQ 的将来布局次要分为新个性落地和运维能力。

新个性方面,冀望实现分级存储、DLedger 模式读写拆散、以及批存储 &Client auto batch 的落地利用。

运维能力方面,冀望实现扩缩容自动化以进步运维能力,落地 OpenTracing 以实现对 RocketMQ 的全方位监控。

退出 Apache RocketMQ 社区

十年铸剑,Apache RocketMQ 的成长离不开寰球靠近 500 位开发者的积极参与奉献,置信在下个版本你就是 Apache RocketMQ 的贡献者,在社区不仅能够结识社区大牛,晋升技术水平,也能够晋升集体影响力,促成本身成长。

社区 5.0 版本正在进行着热火朝天的开发,另外还有靠近 30 个 SIG(兴趣小组)等你退出,欢送立志打造世界级分布式系统的同学退出社区,增加社区开发者微信:rocketmq666 即可进群,参加奉献,打造下一代音讯、事件、流交融解决平台。

微信扫码增加小火箭进群

另外还能够退出钉钉群与 RocketMQ 爱好者一起宽泛探讨:

钉钉扫码加群

关注「Apache RocketMQ」公众号获取更多技术干货

退出移动版