以量化的方式衡量 Ceph RBD 性能(第二部分)
这是关于 Ceph RBD 性能的第二篇文章。在 第一部分 中,我们讨论了 Ceph 上的随机 IO 性能。这次我们分享顺序读/写测试数据。以防您忘记我们的硬件配置,我们使用 40 个 1TB SATA 磁盘作为数据磁盘,以及 12 个 SSD 作为日志。并且使用 4 个 10Gb 链路将存储集群与客户端连接起来,从而提供足够的网络带宽。下图显示了 QD=64 和 CAP=60MB/s 每 VM 的 SR 和 SW 性能。随着 VM/VM 数量的增加,每个 VM 的吞吐量逐渐下降。SR 最大总吞吐量 2759MB/sec 出现在 VM=80,SW 峰值总吞吐量 1487MB/sec 出现在 VM=50。但是,考虑到我们预定义的 QoS 要求(每个 VM 的吞吐量大于预定义目标的 90%),我们选择 VM=40 用于 SR 和 VM=30 用于 SW,这导致报告的指标为 2263MB/sec(SR)和 1197MB/sec(SW)。


这个结果足够好吗?与我们对随机 IO 所做的方法类似,我们将本机磁盘性能作为参考进行测量。我们观察到每个磁盘的顺序带宽约为 ~160MB/sec,读和写都是如此。并且我们测量到单个 10Gb NIC 的值为 ~900MB/sec。理论上,40 个 SATA 磁盘预计可以提供 6400MB/sec 的读取和 3200MB/sec 的写入(replica=2)。并且 4x 10Gb 可以提供 ~3600MB/sec 的带宽。因此,如下表所示,Ceph 的最终效率为 SR 的 57% 和 SW 的 37%。与随机 IO 测试结果相比,这不是一个完美的结果。

让我们看一下 Ceph 架构,以便更好地理解数据。下图说明了一个概念性的 Ceph 集群,它具有 M 个磁盘,每个磁盘映射了 N-1 个对象。磁盘卷的大小标记为 Volume_Size。假设对象大小为 Size_O,每个虚拟磁盘卷由 Volume_Size/Size_O 个对象组成。为了简化问题,我们故意忽略了一些组件(例如 PG 和副本影响)。虚拟磁盘卷的 IO 请求根据 CRUSH 算法分发到不同的对象,并成为磁盘上的实际读/写命中。由于多个对象映射到相同的物理磁盘,原始的逻辑顺序 IO 流混合在一起(绿色、橙色、蓝色和读取块)。并且每个物理磁盘上的实际 IO 模式变得随机,并发生磁盘寻道。因此,延迟会变得更长,总吞吐量会大大下降。
Blktrace 结果证明了我们的假设。我们在两个实验中收集了约 37K 个 IO 跟踪。在左图中,我们运行 40 个 VM。所有 VM 都生成完整的顺序读取。在右图中,我们同时运行 20 个顺序 IO VM 和 20 个随机 IO VM。即使在所有顺序 IO 的情况下,也有 26% 的 IO 非相邻——这意味着发生寻道。当有半个随机 IO 负载时,需要寻道的 IO 比例增加到 59%。在实际生产环境中,我们认为随机 IO 流的比例应该更高,这将对顺序 IO 流性能产生更大的影响。

下图显示了不同 FIO 队列大小 (QD) 和 VM 数量下顺序读/写模式的每个 VM 的 BW 和延迟分析。有几个发现
- 读取性能优于写入——因为写入生成与读取相比两倍的物理 IO。
- SSD 日志并没有像我们在随机 IO 测试中观察到的那样带来相同的优势。我们认为这是由于顺序 IO 具有更高的带宽吞吐量,这会迅速利用缓存空间。
- 对于 QD=8 的情况,读取延迟从 4ms 开始,到 15ms 结束。写入延迟从 9ms 开始,到 28ms 结束。进一步的研究表明,物理 IO 模式随着 VM 数量的增加而变得更加随机,这是合理的。
- 对于 QD=64 的情况,读取延迟从 17ms 开始,到 116ms 结束。写入延迟从 36ms 开始,到 247ms 结束。较大的起始延迟是不正常的,因为此时存储集群离满负荷运行还很远。延迟分解测试告诉我们,大部分延迟来自客户端,这表明存在潜在的优化机会。

我们认为低顺序 IO 性能问题不仅是 Ceph 的挑战,也是所有具有类似设计的分布式存储系统的挑战。根据我们的理解,有两种通用的方法可以提高顺序 IO 性能:加快随机 IO 或优化 IO 模式以增加顺序 IO 百分比。
- 首先,让我们看看减少随机 IO 延迟的可能性。一种方法是优化现有的软件代码。还记得我们观察到 SW 只有一个 VM QD=64 时有 36ms 的延迟吗?考虑到存储集群此时离满负荷运行还很远,延迟非常高。我们认为额外的延迟来自软件问题(锁定、单线程队列等)。通过消除这些软件瓶颈,我们应该能够缩短 IO 延迟并提高总吞吐量。另一种方法是加速文件存储部分,可以通过添加更多内存或将 SSD 作为写回/直通缓存来实现。后者似乎更有趣,因为与 DRAM 相比,成本优势通常日志可能不会使用所有 SSD 空间。但是,这需要更多的实验来了解如果我们同时将 SSD 用于日志和缓存,所需的带宽是多少。有一些相关的 BP 讨论了这一点——例如缓存层(尽管根据我的理解,它在不同的级别使用 SSD 缓存)和新的 NAND 接口支持等。
- 第二种方法是改变 IO 模式,从而有更高的相邻 IO 百分比,减少寻道发生。有两种情况会导致逻辑顺序 IO 流中断:第一种情况是当同一卷的逻辑地址增加时,映射对象从一个对象移动到另一个对象(无论是在同一物理存储节点还是不同的节点上)。第二种情况是它被写入到相同硬盘但来自不同卷的其他 IO 读取/写入中断。因此,我们也可以尝试两种调整方法。第一种方法是使用更大的对象大小——从而减少跳转到不同对象/节点的可能性。第二种方法是使用更好的映射规则。默认情况下,我们将所有磁盘放入同一个池中。因此,来自一个虚拟卷的虚拟地址空间也分发到所有物理磁盘。在这种情况下,来自不同卷的许多 IO 流击中相同的硬盘,导致更高的碎片访问模式。更好的方法是创建多个池。每个池都有有限的磁盘并服务于较少的卷。因此,较少的 IO 流共享相同的硬盘,从而产生更好的顺序模式。下图演示了这两种配置。这个想法来自 ATC 2013 中最好的论文“Copysets: Reducing the Frequency of Data Loss in Cloud Storage”。作者的原始目标是减少磁盘丢失的影响,这对于 Ceph 来说是有效的。我们建议将其视为“最佳实践”并向 Ceph 添加一些功能,以方便管理员的工作。
我们做了一些测试来验证这两个调整选项,如下所示。左侧条形图(4MB 对象)是默认配置,对象大小为 4MB,所有磁盘使用一个池。第二个条形图(32MB 对象)是对象大小为 32MB,所有磁盘使用一个池。最右侧的条形图(32MB 对象 + 新映射规则)是对象大小为 32MB,10 个池,每个池 4 个磁盘。在 40VM/volume 和相同的压力负载下,平均每个 VM 的带宽从 43MB/sec 增加到 57MB/sec(增益 33%)和 64MB/sec(增益 13%)。这似乎是一个不错的开端。下一步,我们将继续尝试不同的调整参数,以了解权衡并确定优化机会以实现更高的顺序吞吐量。例如,Inktank 的 Sage Weil 建议我们应该启用 RBD 客户端缓存,预计这将增加读/写包的大小,从而减少每个 IO 的延迟。

总而言之,Ceph 的默认顺序 IO 性能并不令人满意。虽然通过应用一些调整 BKM 性能有所改善,但仍需要进一步研究和优化。如果您对这个主题有任何建议或意见,请通过电子邮件(jiangang.duan@intel.com)告知我们。再次感谢团队的工作,提供数据并帮助审查。在下一部分中,我希望我们能分享更多关于如何在 Ceph 中使用 SSD 的内容。
顺便说一下,我本月在香港 OpenStack 会议上发表了主题演讲“开源好用吗?对 Swift 和 Ceph 性能的深入研究”(链接)。感谢所有参加我演讲的人,特别是考虑到这是最后一天的最后一节课。
图标图像:¶
![]()