做者 | RocketMQ社区
来源|阿里巴巴云原生公众号git
“童年的雨天最是泥泞,倒是记忆里最干净的曾经。凛冬散尽,星河长明,新的一年,万事顺遂,再见,2020!”github
走过这个岁末,万众期待的 Apache RocketMQ 4.8.0 终于发布了,在这个版本中社区对 RocketMQ 完成大量的优化和问题修复。更重要的是,该版本从性能、稳定性、功能三个方面大幅度提高 DLedger 模式能力。apache
DLedger 是 OpenMessaging 中一个基于 Raft 的 CommitLog 存储库实现,从 RocketMQ 4.5.0 版本开始,RocketMQ 引入 DLedger 模式来解决了 Broker 组内自动故障转移的问题,而在 4.8.0 版本中社区也对 RocketMQ DLedger 模式进行了全面升级。缓存
RocketMQ 4.7.0 从新升级了同步双写的架构,利用异步化 pipeline 模式大幅提高了同步双写的性能。在 RocketMQ 4.8.0 中,社区将这一改进应用到 DLedger 模式中, 下图展现了 DLedger 模式下 broker 处理发送消息的过程。在本来的架构中, SendMessageProcessor 线程对每个消息的处理,都须要等待多数派复制成功确认,才会返回给客户端,而在新版本中,利用 CompletableFuture 对线程处理消息的过程进行异步化改造,再也不等待多数派的确认便可对下一个请求进行处理,Ack 操做由其余线程确认以后再进行结果处理并返回给客户端。经过对复制过程进行切分并将其流水线化,减小线程的长时间等待,充分利用 CPU,从而大幅提升吞吐量。性能优化
Batch 一直是性能优化的重要方式,在新版本中,能够经过设置 isEnableBatchPush=true 来开启 DLedger 模式的批量复制。经过将多条数据聚合在一个包中进行发送,能够下降收发包的个数,从而下降系统调用和上下文的切换。在数据发送压力比较大,而且可能达到系统收发包瓶颈的状况下,批量复制能显著提升吞吐量。值得注意的是,DLedger 模式下的批量复制并不会对单个包进行延时的攒批处理,所以不会影响单个消息的发送时延。网络
除了上述的性能优化,社区还对 DLedger 模式下影响性能的锁、缓存等作了数项性能优化,使 DLedger 模式下的性能提高数倍。架构
为了验证和测试 Dledger 模式的可靠性,除了本地对 DLedger 模式进行了各类各样的测试,社区利用 OpenMessaging-Chaos 框架对 RocketMQ DLedger 模式进行了大量 Chaos 测试。OpenMessaging-Chaos 是一个利用故障注入来验证各类消息平台一致性和高可用性的测试框架,在 OpenMessaging-Chaos 的测试中,客户端并发地向待测试集群发送和接收消息,中间会间隔性地对集群进行故障注入,最后给出测试结果,包括是否丢消息,是否有重复消息,集群平均故障恢复时间等。利用 OpenMessaging-Chaos,咱们验证了 DLedger 模式在如下故障注入场景下的表现:并发
random-partition(fixed-partition)故障随机挑选节点进行网络隔离,模拟常见的对称网络分区。框架
random-loss 故障随机挑选节点并对这些节点接收和发送的网络包进行按比例丢弃,模拟一些节点网络较差的状况。dom
random-kill(minor-kill、major-kill、fixed-kill)故障模拟常见的进程崩溃状况。
random-suspend(minor-suspend、major-suspend、fixed-suspend)故障模拟一些慢节点的状况,好比发生 Full GC、OOM 等。
以 minor-kill 故障注入为例,咱们部署 5 个节点组成一组 DLedger 模式的 RocketMQ broker 进行 Chaos 测试。minor-kill 故障注入会随机挑选集群中少数节点进程杀死,因为杀死少数节点,即便集群不可用也能在一段时间内恢复,方便测试集群平均故障恢复时间。
测试过程当中咱们设置四个客户端并发向 RocketMQ DLedger 集群发送和接收消息,故障注入时间间隔为 100s,即 100s 正常运行,100s 故障注入,一直循环,整个阶段一共持续 2400s。测试结束后,OpenMessaging-Chaos 会给出测试结果和时延图。下图展现了整个测试过程当中入队操做的时延状况。
图中纵坐标是是时延,横坐标是测试时间,绿色框表示数据发送成功,红色框表示数据发送失败,蓝色框表示不肯定是否数据添加成功,灰色部分表示故障注入的时间段。能够看出一些故障注入时间段形成了集群短暂的不可用,一些故障时间段则没有,这是合理的。因为是随机网络分区,因此只有杀死的少数节点包含 leader 节点时才会形成集群从新选举,但即便形成集群从新选举, DLedger 模式在一段时间后也会恢复可用性。
下图是测试结束后 OpenMessaging-Chaos 给出的统计结果,能够看到一共成功发送了 11W 个数据,没有数据丢失,这代表即便在故障下,RocketMQ DLedger 模式仍旧知足 At Least Once 的投递语义。此外,RTOTestResult 代表 12 次故障时间段一共发生了 3 次集群不可用的状况(与上述时延图一致),但每次集群都能在 30 秒之内恢复,平均故障恢复时间在 22 秒左右。
在 OpenMessaging Chaos 测试过程当中,咱们发现了 DLedger 模式存在的数个隐性问题并进行了修复,提升了 DLedger 模式下对进程异常崩溃、慢节点、对称/非对称网络分区、网络丢包的容错能力,也进一步验证了 DLedger 模式的可靠性。
在旧版本中一组 Broker 中选谁做为 Leader 彻底是随机的。可是在新版中咱们能够经过配置 preferredLeaderId 来指定优先选举某个节点为 Leader,以下图所示,经过在三个机房部署 DLedger 模式的 broker 组,利用 preferred leader 能够更好的实现机房对齐的功能,图中 DC1 中服务更好,咱们能够优先选择在 DC1 中部署 Master。此外,利用 preferred leader 还能够更好实现 DLedger 集群混部,从而充分利用机器资源。
从 RocketMQ 4.8.0 开始,DLedger 模式支持批量消息发送,从而在消息类型的支持上彻底与 Master-Slave 部署形态保持一致。
除了对 DLedger 模式的大量优化,本次 RocketMQ 版本一共包含 Improvement 25 个,Bug Fix 11 个,文档和代码格式优化 16 个。据不彻底统计,这些贡献来自近 40 位 RocketMQ 社区的 Contributor,感谢你们的积极参与。也很是期待有更多的用户、厂商、开发者参与到 RocketMQ 建设中来,加入 Apache RocketMQ 社区,永远不会太迟!