仲裁队列和磁盘的重要性
仲裁队列对于 RabbitMQ 来说还比较新,许多人还没有从传统的镜像队列迁移过来。在您迁移到这种新的队列类型之前,您需要确保您的硬件能够支持您的工作负载,而一个重要因素就是您使用的存储驱动器。
在这篇博文中,我们将更深入地了解仲裁队列及其在不同存储配置下的性能特征。
HDD 还是 SSD?一个驱动器还是多个驱动器?
简而言之,我们强烈建议在使用仲裁队列时使用 SSD。原因是仲裁队列对 IO 延迟敏感,而 SSD 比 HDD 提供更低的延迟 IO。随着 IO 延迟的增加,您会看到吞吐量降低、端到端延迟增加以及其他一些不良影响。
在本帖的后面,我们将通过使用不同 SSD 和 HDD 配置进行各种基准测试来演示为什么我们推荐这样做。
为什么仲裁队列对 IO 延迟敏感?
让我们看一下单个代理上的写入路径,以了解原因。请记住,发布和消费都算作写入。发布涉及入队操作,消费涉及确认操作,两者都必须持久化并复制。请注意,如果您在没有发布者确认或消费者确认的情况下使用仲裁或镜像队列,那么您需要问问自己为什么使用复制队列。
操作首先写入内存和预写日志 (WAL)。每个代理有一个 WAL,它为该代理上的所有仲裁队列服务。从那里,操作通过段写入器写入每个队列的段文件。
不过,有一个优化措施,这意味着入队操作(消息)可能永远不需要写入段文件。新到达的消息保存在内存中,消息可以在写入段文件之前被消费者传送和确认。在这种情况下,这些消息不会写入磁盘,因为就代理而言,它们实际上不再存在。
这意味着对于消费者跟上的队列,消息通常根本不会写入段文件。在内存中消息准备刷新到段文件时,消费者已确认了该消息。如果 IO 延迟很高,那么 WAL 最终会成为瓶颈。每个代理都有一个 WAL 和一个段写入器进程,它们充当仲裁队列 Raft 集群所依赖的共享基础设施。将操作同步到活动 WAL 文件就像 Raft 集群的心跳一样。如果同步速度慢,那么 Raft 集群的吞吐量就会下降。
同步段文件也可能成为瓶颈。WAL 由一个或多个文件组成;一个文件正在积极写入,零个或多个非活动文件由于达到最大 WAL 文件大小限制而被滚动。这些非活动 WAL 文件只有在所有消息都写入段文件和/或被确认(参见上面的优化措施)后才能安全删除。如果段文件的写入速度很慢,那么 WAL 会变得越来越大,因为消息无法以足够快的速度写入段文件。
HDD 非常适合大型顺序写入,但不适合小型或随机 IO。如果您的写入必须访问多个文件,在文件系统中跳来跳去,那么 HDD 比 SSD 产生的 IO 延迟要高得多。WAL 和段文件最棒的地方在于它们是追加式文件。因此,HDD 有可能提供不错的性能,但前提是没有大量随机 IO 争用。一旦 WAL 和段文件 IO 必须与其他磁盘 IO 竞争,性能就会开始下降。
好的,但是使用 HDD 的性能如何?
现在我们将使用 SSD 和 HDD 进行一些性能基准测试,并分析结果。
有四个主要参与者使用磁盘
- Mnesia 和消息存储(数据)
- 日志(日志)
- 仲裁队列段文件(段)
- 仲裁队列 WAL(wal)
这些工作负载中的每一个都具有不同的 IO 模式,我们可以尝试隔离这些磁盘工作负载以提高性能。
我们有六个集群,它们在 CPU 数量等方面共享某些方面,但使用不同类型和数量的磁盘。
共享
- 3 节点集群
- 实例类型:c4.4xlarge
- 16 个 vCPU
- 15GB 内存
- 2Gbps EBS 实例吞吐量(VM 的磁盘 IO 吞吐量上限为 2Gbps/250MBs)
- 5Gbps 网络(625MB/s)
所有磁盘均为 200GB SSD(io1)或 1TB HDD(st1)。每个磁盘的吞吐量能力都大于 c4.4xlarge EC2 实例的使用能力。
唯一
- 将所有数据存储在一个驱动器中
- 集群 rabbitmq1,SSD1=data/logs/segment/wal
- 集群 rabbitmq10,HDD1=data/logs/segment/wal
- 将 WAL 存储在单独的驱动器上,但将段文件存储在与传统队列数据相同的驱动器上
- 集群 rabbitmq4,SSD1=data/logs/segment SSD2=wal
- 集群 rabbitmq13,HDD1=data/logs/segment HDD2=wal
- 为传统队列数据、段文件和 WAL 文件分别分配专用驱动器
- 集群 rabbitmq7,SSD1=data/logs SSD2=segment SSD3=wal
- 集群 rabbitmq16,HDD1=data/logs HDD2=segment HDD3=wal
纯仲裁队列工作负载
首先,我们将测试仅包含仲裁队列的工作负载。
吞吐量基准测试 #1 - 一个仲裁队列
一个发布者、一个队列、一个消费者、1kb 消息,没有速率限制。
我们看到,SSD 集群 rabbitmq1、rabbitmq4 和 rabbitmq7 都达到了大约 19k msg/s。HDD 集群的吞吐量较低,rabbitmq13(2 个磁盘)和 rabbitmq16(3 个磁盘)仅略微落后,约为 17k msg/s。单个 HDD 集群明显落后,约为 13k msg/s。
结论
对于单队列工作负载,将 WAL 从段文件工作负载分离到单独的磁盘上,为我们带来了接近 SSD 性能的效果。
吞吐量基准测试 #2 - 四个仲裁队列
4 个发布者、4 个队列、4 个消费者、1kb 消息,没有速率限制。
使用 4 个仲裁队列,我们看到了不同的情况。HDD 的性能比它们的 SSD 对手高出约 2k msg/s。我们必须记住,当消费者能够跟上的时候,操作通常只写入 WAL 文件。WAL 在四个队列之间共享,因此我们通过它推送更多字节。WAL 文件是顺序写入的,我们的 st1 HDD 可以管理 500MB/s 的吞吐量(尽管 VM 本身被限制在 250MB/s)。
结论
在只有顺序写入的世界中,HDD 可能会产生与 SSD 相似甚至更好的结果。仲裁队列仅工作负载,消费者跟上的情况下,应该会看到绝大多数写入只进入单个追加式 WAL 文件。
延迟基准测试 #1 - 40 个仲裁队列
40 个发布者、40 个队列、40 个消费者、1kb 消息,每个发布者 10 msg/s(总计 400 msg/s)。
SSD
HDD
在总速率仅为每秒 400 个 1kb 消息的情况下,我们看到 SSD 和 HDD 具有相当的端到端延迟。
延迟基准测试 #2 - 40 个仲裁队列
40 个发布者、40 个队列、40 个消费者、1kb 消息,每个发布者 50 msg/s(总计 2000 msg/s)。
HDD
这次我们看到 HDD 的延迟明显更高
- 第 75 个百分位数 ~4ms vs ~15ms
- 第 99.9 个百分位数 ~20ms vs ~110ms
我们还看到,两个磁盘和三个磁盘的 HDD 配置比单个 HDD 的延迟更低。在我们的测试中,两个磁盘和三个磁盘配置之间没有太大区别,因为我们没有 mnesia 或消息存储数据与仲裁段数据竞争。
结论
随着吞吐量的增加,我们看到 SSD 比 HDD 产生了更低的延迟。
轻混合工作负载(传统延迟和仲裁)
到目前为止,我们已经看到仲裁队列在隔离状态下进行了测试,没有任何传统或镜像队列负载。在这个测试中,我们将看到仲裁队列在仲裁队列和非复制延迟队列的混合工作负载中的表现如何。延迟队列比普通的传统队列更密集,应该会产生更多的磁盘争用。
吞吐量基准测试 #1 - 一个仲裁队列
一个发布者、一个队列、一个消费者、1kb 消息,没有速率限制。
延迟队列工作负载:40 个发布者、40 个队列、40 个消费者、16b 消息,每个发布者 10 msg/s(总计 400 msg/s)。
我们看到,在使用这种后台延迟队列加载的情况下,SSD 集群的吞吐量没有受到影响,仍然保持在 20k 条消息/秒。然而,单个 HDD 集群受到严重影响,从 13k 条消息/秒下降到 6k 条消息/秒。现在,写密集型 WAL 工作负载必须与消息存储竞争,这将涉及大量的磁盘寻道。
两个和三个磁盘的 HDD 集群表现更好,吞吐量略有下降,这是因为大多数写入都写入 WAL,WAL 有一个专用磁盘,并且仍然可以实现顺序写入。
结论
较低的非法定人数队列消息吞吐量会对 HDD 造成更大的影响,但可以通过将工作负载隔离到单独的磁盘上来减轻影响。
吞吐量基准测试 #2 - 四个法定人数队列
4 个发布者、4 个队列、4 个消费者、1kb 消息,没有速率限制。
延迟队列工作负载:40 个发布者、40 个队列、40 个消费者、16b 消息,每个发布者 10 msg/s(总计 400 msg/s)。
我们再次看到 HDD 的吞吐量下降,单磁盘集群的下降幅度最大。
延迟基准测试 #1 - 40 个法定人数队列
40 个发布者、40 个队列、40 个消费者、1kb 消息,每个发布者 10 msg/s(总计 400 msg/s)。
延迟队列工作负载:40 个发布者、40 个队列、40 个消费者、16b 消息,每个发布者 10 msg/s(总计 400 msg/s)。
SSD
HDD
上次,在没有混合工作负载的情况下,我们看到 SSD 和 HDD 的端到端延迟相当。然而,这次,单个 HDD 集群的端到端延迟大幅增加,第 75 百分位数达到 50 毫秒,第 99.9 百分位数达到 300 毫秒。两个和三个磁盘配置的第 75 百分位数延迟相当,但在第 99.9 百分位数处,有一个峰值达到 25 毫秒。
结论
在轻量级混合工作负载下,单个 HDD 配置表现不佳,但具有用于 WAL 的单独磁盘的配置几乎与 SSD 相当。
延迟基准测试 #2 - 40 个法定人数队列
40 个发布者、40 个队列、40 个消费者、1kb 消息,每个发布者 50 msg/s(总计 2000 msg/s)。
延迟队列工作负载:40 个发布者、40 个队列、40 个消费者、16b 消息,每个发布者 10 msg/s(总计 400 msg/s)。
SSD
HDD
我们再次看到,单个 HDD 的表现最差,但这次,两个和三个磁盘的 HDD 集群的表现更差,徘徊在 20-60 毫秒之间,而 SSD 则徘徊在 5-15 毫秒之间。
结论
在轻量级混合工作负载下,但法定人数队列负载较高时,我们发现 HDD 明显处于劣势。
中等混合工作负载(经典延迟和法定人数)
这次,我们将延迟队列流量增加五倍,从 400 条消息/秒增加到 2000 条消息/秒,看看我们的 SSD 和 HDD 集群的表现如何。
吞吐量基准测试 #1 - 一个法定人数队列
一个发布者、一个队列、一个消费者、1kb 消息,没有速率限制。
延迟队列工作负载:40 个发布者,40 个队列,40 个消费者,16 字节消息,每个发布者 50 条消息/秒(2000 条消息/秒)。
这次,HDD 的吞吐量降得很低。我们可以看到,两个和三个磁盘配置有所帮助,但帮助不大。
- 1 个磁盘:约 300 条消息/秒
- 2 个磁盘:约 1700 条消息/秒
- 3 个磁盘:约 2300 条消息/秒
但是看看 SSD,它们的吞吐量与以往一样。
结论
一旦混合工作负载达到一定程度,HDD 上的法定人数队列吞吐量就会降得很低,无论您是否将磁盘工作负载隔离。显然,这里还有其他因素在起作用,因为具有隔离的段和 WAL 文件加载的三个磁盘配置还不够。
吞吐量基准测试 #2 - 四个法定人数队列
4 个发布者、4 个队列、4 个消费者、1kb 消息,没有速率限制。
延迟队列工作负载:40 个发布者,40 个队列,40 个消费者,16 字节消息,每个发布者 50 条消息/秒(2000 条消息/秒)。
这次,单个 HDD 几乎只处理了一条消息。两个和三个磁盘配置的吞吐量约为 2300 条消息/秒。
这次要注意,单个 SSD 集群受到了延迟队列流量的影响。两个和三个 SSD 集群几乎没有受到影响,这表明法定人数队列即使在 SSD 上也可以从磁盘工作负载隔离中获益。
延迟基准测试 #1 - 40 个法定人数队列
40 个发布者、40 个队列、40 个消费者、1kb 消息,每个发布者 10 msg/s(总计 400 msg/s)。
延迟队列工作负载:40 个发布者,40 个队列,40 个消费者,16 字节消息,每个发布者 50 条消息/秒(2000 条消息/秒)。
SSD
HDD
单个 HDD 基本上无法工作,两个和三个磁盘配置的延迟很大,其中两个磁盘的延迟超过 1 秒,尽管消息速率很低。
结论
随着法定人数队列和非法定人数队列负载的增加,HDD 集群的端到端延迟持续恶化。SSD 基本保持不变。
延迟基准测试 #2 - 40 个法定人数队列
40 个发布者、40 个队列、40 个消费者、1kb 消息,每个发布者 50 msg/s(总计 2000 msg/s)。
延迟队列工作负载:40 个发布者,40 个队列,40 个消费者,16 字节消息,每个发布者 50 条消息/秒(2000 条消息/秒)。
SSD
HDD
同样,单个 HDD 集群无法处理任何消息。三个磁盘配置完全将法定人数队列负载与延迟队列磁盘负载隔离,显示出最佳延迟,但仍然比 SSD 的延迟高得多。
最终结论
SSD 上的法定人数队列表明它们对混合工作负载并不十分敏感,但在较高负载下可以从多 SSD 驱动器配置中获益。
我们还发现,在 HDD 上运行时,法定人数队列处理 **混合** 工作负载的效果并不好。可以通过将段和 WAL 文件与 mnesia(元数据)和消息存储(经典队列数据)工作负载隔离到单独的 HDD 上来缓解这些问题,但在一定程度的经典队列流量下,吞吐量会大幅下降。该负载水平完全取决于您的特定设置。
法定人数队列什么时候可以在 HDD 上安全使用?虽然不建议,但您仍然可以在低队列数的纯法定人数队列工作负载或低容量的混合工作负载下获得良好的性能。但我们已经看到,法定人数队列的性能在 HDD 上会急剧下降,因此您是在冒险。我们强烈建议使用 SSD,并建议在使用法定人数队列时不要使用 HDD。
在本系列的下一篇文章中,我们将探讨从经典镜像队列迁移到法定人数队列,并使用一些示例工作负载来演示您可能会期待的结果。