![为什么存储的性能会随着不同的队列深度而发生变化?](https://linux22.com/image/797809/%E4%B8%BA%E4%BB%80%E4%B9%88%E5%AD%98%E5%82%A8%E7%9A%84%E6%80%A7%E8%83%BD%E4%BC%9A%E9%9A%8F%E7%9D%80%E4%B8%8D%E5%90%8C%E7%9A%84%E9%98%9F%E5%88%97%E6%B7%B1%E5%BA%A6%E8%80%8C%E5%8F%91%E7%94%9F%E5%8F%98%E5%8C%96%EF%BC%9F.png)
我正在为我们的服务器寻找存储升级。我正在查看各种 PCIe SSD 设备的基准测试,通过比较,我发现 IOPS 在不同队列深度下会发生变化。这是怎么回事?为什么会发生这种情况?我的理解是:我有一个最大(理论上)为 100k IOPS 的设备。如果我的工作负载持续产生 100,001 IOPS,我的队列深度将为 1,对吗?但是,从我在基准测试中看到的情况来看,一些设备在较低的队列深度下运行速度较慢,然后在深度为 4-64 时加速,然后在更大的深度下再次减速。队列深度不是操作系统(或存储控制器)的属性吗?那么为什么会影响 IOPS?
答案1
简短的回答是,如果有多个未完成的 IO 请求,硬盘会优化数据检索,这通常会以延迟为代价来增加吞吐量。
NCQ 会这样做,重新排序 IO 请求以优化吞吐量。
SSD 的工作方式与机械驱动器不同,因为它们具有并行闪存芯片来存储数据。即,如果您一次发出一个 IO 请求,则延迟(搜索 + 读取时间)决定了 IOPS。但是,如果您一次发出 4 个请求,SSD 磁盘可能能够以并行或其他优化方式检索它们,并且您可能会获得 4 倍的吞吐量。
队列深度越高,优化磁盘的可能性就越大。由于 IOPS 是吞吐量的函数,因此队列深度越高,IOPS 就越高。
编辑:
真正的队列位于发出所有请求的操作系统中。也就是说,我推测控制器驱动程序将一定数量的队列传递给控制器和磁盘,以便它们可以在优化的队列深度下工作。磁盘必须有自己的队列才能进行优化。
答案2
这是一个老问题,但值得提供更多信息,因为它被多次看到。这个答案基于 SSD,因为原始问题就是关于 SSD 的。
队列深度和基于队列深度的 IOPS 变化。假设队列深度为 1。在这种情况下,给出的规格不是基于驱动器落后于系统生成的请求数,而是意味着系统向 SSD 生成 1 个请求。请求有一个事务时间,因此如果一次只发送 1 个请求,SSD 只能处理 1 个请求。这应该是有道理的。由于事务时间,一次发送 1 个请求比一次发送 32 个请求要慢,这就是 QD32 之类的规格的含义。
此外,正如另一条评论指出的那样,您可能能够在 PCIe 而不是 SATA 上与 SSD 并行执行一些读取/写入操作。
以三星 970 Pro 为例,QD1 = 55,000,QD32 = 500,000 IOPS。这基本上是因为您只发送一个请求,而不是一次发送 32 个请求。事务时间减少了,因此您主要处理数据传输。因此,减去大量的事务处理,数据传输的实际功能就会增加。
因此,磁盘的规格与队列深度的定义并不完全相同。系统的队列深度基本上是尚未处理的请求数。该规格基于系统一次发送给驱动器的事务。但是,如果您处理的是 SAN,则队列深度基本上是正在进行的请求数。因此,我不太确定该术语的确切定义。对我来说,它似乎因您所指的系统的特定部分而异。
至于操作系统和设备之间的事务,设备将缓冲一定数量的事务,之后操作系统将不再发送更多事务。必须有一种允许有序处理的握手形式,这意味着操作系统不能向驱动器发送超过其物理承载能力的请求。否则,系统就会一片混乱,设计也很差。
换句话说,像“当您收到传入请求但队列深度已满时会发生什么”这样的问题不应该发生在磁盘上,并且磁盘没有“队列深度”来保存请求,它有一个“队列”。驱动器将保存的请求的物理数量将根据驱动器的类型而变化。它不能太小,否则磁盘无法很好地优化读/写,并且它不能太大,原因有很多,成本是其中之一,在队列中有一定数量的请求后无法优化可能是另一个原因。