为啥顺序写入比 HDD 上的随机写入快

Posted

技术标签:

【中文标题】为啥顺序写入比 HDD 上的随机写入快【英文标题】:why sequential write is faster than random write on HDD为什么顺序写入比 HDD 上的随机写入快 【发布时间】:2020-08-27 22:50:36 【问题描述】:

就像在文件尾部附加日志条目,或者就像 mysql 记录它的重做日志一样,人们总是说顺序写入比随机写入快得多。但为什么?我的意思是,当您在磁盘上写入数据时,寻道时间和旋转时间决定了性能。但是在您连续两次连续写入之间,可能还有很多其他写入请求(如 nginx 记录 access.log)。这些写入请求可能会将磁头移动到其他磁道,并且当您的进程进行顺序写入时,它需要再次将磁头移回,并产生旋转时间。即使没有其他过程,磁头可以静止不动,您也需要等待旋转。 那么,顺序写入是否真的优于随机写入,仅仅是因为在许多情况下,顺序写入不包含寻道时间,而随机写入始终包含寻道时间,但顺序写入和随机写入都包含旋转时间?

【问题讨论】:

【参考方案1】:

磁盘的写入性能受存储设备的物理属性(例如,机械磁盘的物理转速(以每分钟转数为单位)、磁盘 I/O 单元与 I/O 请求大小的比率)的影响和操作系统/应用程序。

硬盘的物理特性

传统机械磁盘的一个主要缺点是,要满足 I/O 请求,磁头必须到达所需的起始位置(寻道延迟),而盘片必须到达所需的起始位置(旋转延迟) .

这适用于顺序和随机 I/O。但是,对于顺序 I/O,这种延迟会变得不那么明显,因为无需重新定位磁头即可写入更多数据。 “高级格式”硬盘的扇区大小为 4096 字节(最小的 I/O 单元),柱面大小在兆字节范围内。无需重新定位磁头即可读取整个圆柱体。所以,是的,存在寻道和旋转延迟,但无需进一步重新定位即可读取/写入的数据量要高得多。此外,从一个柱面移动到下一个柱面比从最里面的柱面移动到最外面的柱面(最坏情况下的寻道)效率更高。

写入 10 个连续扇区涉及一次寻道和旋转延迟,写入分布在磁盘上的 10 个扇区涉及 10 次寻道计数和旋转延迟。

一般来说,顺序 I/O 和随机 I/O 都涉及寻道和旋转延迟。顺序 I/O 利用顺序局部性来最大限度地减少这些延迟。

SSD 的物理特性

如您所知,固态磁盘没有移动部件,因为它通常由闪存构成。数据存储在单元格中。多个单元组成一个页面——最小的 I/O 单元,大小从 2K 到 16K 不等。多个页面以块的形式进行管理 - 一个块包含 128 到 256 个页面。

问题有两个方面。首先,一个页面只能写入一次。如果所有页面都包含数据,则除非擦除整个块,否则它们不能被再次写入。假设一个块中的一个页面需要更新,并且所有页面都包含数据,那么整个块必须被擦除和重写。

其次,单个块的写入周期数是有限的。为了防止某些块比其他块更快地接近或超过最大写入周期数,使用了一种称为磨损均衡的技术,以便独立于逻辑写入模式将写入均匀地分布在所有块上。此过程还涉及块擦除。

为了减轻块擦除带来的性能损失,SSD 采用垃圾收集过程,通过将块页面(不包括过时页面)写入新块并擦除原始块来释放标记为过时的已用页面。

这两个方面都可能导致物理读取和写入的数据多于逻辑写入所需的数据。整页写入可以触发 128 到 256 倍的读/写序列,具体取决于页/块关系。这称为写放大。与顺序写入相比,随机写入可能会命中更多的块,从而使它们的成本大大提高。

磁盘 I/O 单元与 I/O 请求大小的比率

如前所述,磁盘对可参与读取和写入的 I/O 单元施加了最低限度。如果将单个字节写入磁盘,则必须读取、修改和写入整个单元。

与顺序 I/O 相比,在 I/O 负载增加时触发大量写入的可能性很高(例如,在数据库事务日志的情况下),随机 I/O 往往涉及较小的 I/O 请求.随着这些请求变得小于最小的 I/O 单元,处理这些请求的开销会增加,从而增加了随机 I/O 的成本。这是由于存储设备特性而导致的写入放大的另一个示例。但是,在这种情况下,HDD 和 SSD 场景会受到影响。

操作系统/应用程序

操作系统有多种机制来优化顺序和随机 I/O。 由应用程序触发的写入通常不会立即处理(除非应用程序通过同步/直接 I/O 或同步命令请求),更改基于所谓的页面缓存在内存中执行并写入磁盘在稍后的时间点。

通过这样做,操作系统可以最大限度地提高可用数据总量和单个 I/O 的大小。原本执行效率低下的单个 I/O 操作可以聚合成一个可能更大、更高效的操作(例如,对特定扇区的多次单独写入可以成为一次写入)。此策略还允许 I/O 调度,选择对执行 I/O 最有效的处理顺序,即使应用程序定义的原始顺序不同。

考虑以下场景:Web 服务器请求日志和数据库事务日志被写入同一个磁盘。如果 Web 服务器写操作按相关应用程序发出的顺序执行,它们通常会干扰数据库写操作。由于基于页面缓存的异步执行,操作系统可以对这些 I/O 请求重新排序,以分别触发两个大型顺序写入请求。在执行这些操作时,数据库可以继续写入事务日志,不会有任何延迟。

这里需要注意的是,虽然 Web 服务器日志应该如此,但并非所有写入都可以随意重新排序。每当事务日志必须作为提交的一部分写入稳定存储时,数据库就会触发磁盘同步操作(Linux/UNIX 上的fsync,Windows 上的FlushFileBuffers)。然后,操作系统不能进一步延迟写入操作,必须立即执行所有先前对相关文件的写入。如果 Web 服务器也这样做,可能会对性能产生显着影响,因为顺序由这两个应用程序决定。这就是为什么将事务日志放在专用磁盘上以在存在其他磁盘同步/大量其他 I/O 操作的情况下最大化顺序 I/O 吞吐量是一个好主意(Web 服务器日志不应该成为问题) )。否则,随着总 I/O 负载和/或磁盘同步次数的增加,基于页面缓存的异步写入可能无法再隐藏 I/O 延迟。

【讨论】:

以上是关于为啥顺序写入比 HDD 上的随机写入快的主要内容,如果未能解决你的问题,请参考以下文章

为啥对 NVMe SSD 上的单个文件进行并发随机写入不会导致吞吐量增加?

随机内存写入比随机内存读取慢?

kafka性能为啥好

RAMdisk 读取似乎并不比硬盘 (HDD) 读取快

顺序写入和随机写入的区别

为啥将许多小字节数组写入文件比写入一个大数组要快?