本文作者:邓志文,小米研制工程师,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」大众号获取更多技术干货