[Paper Reading] Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems

今天看到一篇论文:Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems
这篇论文发表于 2013 年,介绍 Linux 内核的 block layer 针对现代硬件——高速 SSD、多核 CPU(NUMA)的新设计。
总的来说,设计方案不难理解,并没有涉及什么牛逼或者新颖的内容。这里面提到的内容从 Linux 3.11 开始出现在内核,Linux 3.16 成为内核的一个完整特性[6]。Linux 5.0 开始成为 block layer 的默认选项[7]。

Single-Queue For HDD

在此之前的 Linux block layer 应该是从 Linux 2.6 之后就没有怎么修改过。当时的 block layer 是针对 HDD 设计的。我们都知道,HDD 的随机 I/O 性能其实很差,每秒钟也就几百的吞吐量,延迟也要达到毫秒级。I/O 性能的瓶颈在于硬件,而不在内核 —— 论文说,当时的内核 block layer 吞吐可以达到百万 IOPS ,用于应对 HDD,绰绰有余。Block layer 的设计也比较简单,采用一个全局共享的请求队列(Request Queue):

[Paper Reading] Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems_第1张图片
图片来自论文

Request Queue 全局共享,由一个锁进行保护。所有对 Request Queue 的操作,如加入/移除一个 I/O 请求,I/O 何必,I/O 重排序,I/O 调度等,都需要进行互斥

在现代高并发、低延迟的硬件环境下,Request Queue 成为了 block layer 的主要瓶颈。
另外,文章还提到另外两个问题:

  1. 硬件中断(Hardware Interrupts)。块设备通过硬件中断来通知内核 I/O 已完成。但是,目前大多数硬件的设计都是将中断信号发送给 CPU 0,然后 CPU 0 再通过软中断,将这个请求转发给其它 CPU。这很容易导致 CPU 0 的负载高于其它 CPU。不过这是硬件设计的问题,内核也比较难优化这种情况。
  2. 远程内存访问(Remote Memory Access)。单请求队列的 block layer 设计对 NUMA 架构是无感知、不友好的。

猜测一下 block layer 设计成全局一个请求队列的原因:

  1. HDD 很慢,内核互斥访问一个全局队列不会成为系统瓶颈。
  2. CPU 核数较少,锁竞争的情况不严重。
  3. 全局一个队列有利于 I/O 优化(合并、重排序)。

Multi-Queue For SSD

和 HDD 相比,SSD 的随机性能有了质的提升:

  • SSD 的随机 I/O 性能和顺序 I/O 差别并不明显。
  • SSD 的随机 I/O 吞吐可以达到几十万每秒(超过百万 IOPS 的 SSD 很快就会到来)。
  • SSD 的随机 I/O 延迟是微秒级。

除此之外,多核 CPU (包括 NUMA)的发展,也会影响到 block layer 的设计。新 block layer 的设计,要解决的就两个问题:

  • 减少请求队列的锁争用。
  • 减少 Remote memory accesses。

原来的全局请求队列主要有两个功能:

  1. I/O 调度(包括 I/O 合并、I/O 重排序等优化)。
  2. 限流,避免硬件设备过载。

新的设计将这两个功能拆开,用两级队列来分别完成这两个功能:


[Paper Reading] Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems_第2张图片
图片来自论文
  • Software Staging Queues 负责 I/O 的调度和优化,可以配置一个 CPU core 一个队列,或者一个 CPU socket 一个队列。这将消除或大大减少锁争用。I/O 调度和优化只会在 Software Staging Queues 中完成,并且不会发生跨队列的 I/O 合并和排序。
  • Hardware Dispatch Queues 负责将从 Software Staging Queues 过来的 I/O 请求发送给底层硬件,其数量和硬件相关。目前普通硬件一般只有一个队列,高端硬件可能会有多个队列。

一点思考

对上层开发的影响,主要在 block layer 对 I/O 的优化有一些改变——不会发生跨队列的 I/O 优化。Block layer 对 I/O 的优化主要有两种:

  1. I/O 重排序:让乱序、分散的 I/O 请求变得有序、紧凑。这对 HDD 来说是个很大的优化,但是对 SSD 来说应该效果不明显。并且,分散的 I/O 才有利于利用 SSD 的并行能力。
  2. I/O 合并:将相邻的小 I/O 请求,合并成一个大 I/O 请求。由于 block layer 不会发生跨队列的 I/O 合并,所以应用层应该尽可能确保相邻的 I/O 在同一个线程里完成,并且应该为 I/O 线程绑定 CPU。

参考文章

[1] Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems

[2] The multiqueue block layer

[3] A block layer introduction part 1: the bio layer

[4] Block layer introduction part 2: the request layer

[5] The Linux Block Layer - Built for Fast Storage

[6] Blk-mq Is Almost Feature Complete & Fast With Linux 3.16

[7] Linux kernel 5.0+ switching to Multi-Queue Block as default

[8] Linux Multi-Queue Block IO Queueing Mechanism (blk-mq)

[Paper Reading] Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems_第3张图片
欢迎关注

你可能感兴趣的:([Paper Reading] Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems)