关于高性能计算:如何提升存储性能之IO模型和AIO大揭秘

14次阅读

共计 3776 个字符,预计需要花费 10 分钟才能阅读完成。

如何晋升存储系统的性能是一个对存储工程师们来说是永恒的大命题,解决这个问题并没有一击即中的银弹,IO 性能的优化都在细节里。明天咱们来讲一讲性能和 IO 模型之间的关系。

咱们先从本地磁盘的 IO 模型说起。一方面,对本地磁盘来说,传统机械磁盘 HDD 介质的 IO 性能比 CPU 指令和应用程序差了好几个数量级;另一方面,新型的 SATA SSD 和 NVMe SSD 硬盘的性能大幅晋升,在硬盘外部,磁盘控制器芯片具备多个队列来解决并发的 IO 申请,磁盘自身具备了更高水平并发的能力。那么如何解决磁盘交互慢,以及利用新型磁盘外部个性,晋升数据拜访性能,升高零碎开销呢?由此零碎工程师们引入了多种 IO 模型来应答这些问题。

01 IO 模型

简略来说,咱们能够在上面这张二维的表中,别离从同步和异步、阻塞和非阻塞两个维度,演绎一下当初 Linux 操作系统中不同的 IO 模型。

同步阻塞 IO

这是应用程序编写时最罕用的 IO 模型。在该模型中,应用程序执行零碎调用时,会导致应用程序阻塞。例如,利用收回一个读的零碎调用,程序后续的逻辑会被阻塞,直到零碎调用实现(数据传输实现或失败)为止。当然,这个应用程序的阻塞,并不代表其它的利用不能继续执行,在这个利用被阻塞期间,会让出 CPU,CPU 能够执行其它的应用程序,只是这个程序自身被拜访磁盘 IO 操作阻塞住了。从处理器角度来看,还是挺高效的,而且即便传统 HDD 响应较慢,这种读写模式所波及的用户态、内核态上下文切换也不多,能满足大部分利用的性能需求。

同步非阻塞 IO

同步非阻塞模型和第一中模型的最大区别,是应用程序以非阻塞形式发送 IO 零碎调用之后,零碎会间接返回一个返回码(EAGAIN 或者 EWOULDBLOCK),这个返回码是提醒应用程序期待或稍后再次被动询问 IO 是否实现。在 IO 实现后的那次零碎调用,零碎会返回数据,这意味着 IO 可能曾经实现了,但仍需利用再次被动申请,能力取得数据,所以会带了一些额定的延时,存储整体的延时性能差,且产生了屡次内核和用户态之间的上下文切换,对延时要求高的利用个别不会采纳该模型。

异步阻塞 IO

第三个 IO 模型,也称之为零碎事件驱动模型或 IO multiplexing,也是十分罕用的 IO 模型。其机制能够简略了解为应用程序在发送零碎调用时,利用操作系统的 epoll 机制,被动申明去监听某个 IO 描述符 fd 状态的变动(或事件的类型),epoll 机制会保障这个 fd 在产生指定变动后告诉利用,数据曾经筹备好,再由应用程序发动 IO 操作。在理论从磁盘进行 IO 过程中,由 epoll 机制自身去监听事件,应用程序并不关注 epoll 外部的执行,应用程序能够执行其它操作。

异步非阻塞 IO

话题终于来到明天的重点,异步非阻塞 IO,也称为 AIO。这种模型的特点,是应用程序收回 IO 申请之后,零碎会间接返回,告知这个申请曾经胜利发动并被零碎接管了。零碎后盾在执行具体 IO 操作过程中,应用程序能够执行其它业务逻辑。当 IO 的响应达到时,会产生一个信号或由零碎间接执行一个回调函数来实现这次的 IO 操作。通过形容和下图能够看到,这种模型带来几个益处,一是利用并不会被某次 IO 申请阻塞,后续应用逻辑能够持续进行,且不须要轮询或再次发动相干零碎调用;二是这种模式的上下文切换很少,它能够在一个上下文实现多个 IO 的提交,因而零碎开销也很小。

AIO 是 Linux2.6 内核提出的一个规范个性,提出来的目标,就是反对异步非阻塞模型。目前,AIO 有两种实现形式,别离是应用 libaio 和 io_uring。2.6 以上版本的内核曾经实现了内核级别的 AIO 反对,配合用户态 libaio 库,即可反对异步非阻塞模式拜访,到当初曾经非常成熟和稳固。在 5.x 内核中引入的 io_uring,则将作为对立框架,用于反对磁盘和网络等数据拜访的异步非阻塞操作,尽管 io_uring 利用场景更广,但成熟稳定性还欠缺一些,目前还在一直迭代中。因而业界通常说 AIO 的时候,默认指的就是 libaio 这种实现。

libaio 的呈现,的确对 SSD 等新型介质是一个很好的反对和解放。如果不借助 libaio,要充分发挥硬件性能的话,须要在应用程序级别引入多线程或多机多任务。这种形式存在两个有余,一是多线程之间须要上下文切换,而且也不能为了并发而无限量地引入大量的线程,这样对系统和 CPU 开销都很大;二是有的应用程序自身并没有实现多线程,也没有做多机并发,因而也不可能通过多线程形式来晋升对底层的利用。而通过 libaio,就能够在一个线程的状况下,充分利用 SSD 等新型硬件外部多队列来实现并发(即 SSD 的控制器保护了多个工作队列,应用程序通过应用 libaio,就能够在单线程下,释怀地往硬件下发大量 IO 申请,由硬件自身来解决多并发的问题),从而晋升单线程应用程序的性能,也可能缩小零碎因为多线程切换带来的开销。AIO 是以后高性能零碎(不论是存储或是其余零碎)晋升解决能力的一个重要形式。

02 AIO(libaio)的限度

文件在关上时有两种形式,dio 和 buffer io。dio 不写 pagecache,间接和盘交互,buffer io 会有内存 pagecache 染指,某些场景下会对性能有晋升,但有些特定 IO 场景中性能反而可能会降落。例如程序大 IO,性能可能反而不如 dio,这是因为 buffer io 要先写内存,再刷盘,而 HDD 或其它磁盘间接进行程序 IO 性能可能更高;另外某些对数据可靠性要求比拟高的场景中,写 pagecache 可能会有数据失落的危险,例如 MySQL 等数据库,这些利用在写数据时通常都会应用 dio,读的时候会引入应用程序本身的一些缓存机制来晋升性能。

之所以介绍了一下 dio 和 buffer io 的背景,是因为 libaio 的一个限度是只反对 dio。这是因为 buffer io 会遇到 bounce buffer 调配阻塞的问题,此外,在遇到非对齐的 IO 时,还会触发写惩办,这些对效率影响都较大,与 libaio 心愿晋升性能南辕北辙了,因而 libaio 在实现的时候默认就是 dio 了。

而新的 io_uring 则反对 buffer io(对于 io_uring,咱们就在当前再介绍了)。

03 分布式文件系统对 AIO 的反对及意义

对网络存储或者内部存储来说,客户端次要性能就是 IO 转发,所以客户端不波及间接拜访磁盘(IO 拜访模型,尤其是 AIO 的初衷,就是解决本地拜访的问题),所以通常来说(尤其是对网络文件系统),相似 GlusterFS 等开源的分布式文件存储个别不会反对 AIO。然而,但对于一些利用,例如 MySQL,它不晓得本身的数据起源是本地文件系统还是网络文件系统,所以应用程序默认应用的是 libaio,如果客户端不反对 AIO,只是进行 AIO 转发的话,性能就会受到制约。在这种场景下,客户端就要模仿后端 AIO 的实现,进而充分发挥客户端的性能了。

04 YRCloudFile 客户端对 AIO 的反对

YRCloudFile 新版本的客户端对 AIO 的读写模式进行了反对。对于 YRCloudFile 客户端 AIO 的实现方面,须要了解接口 io_setup、io_cancel、io_destroy、io_getevents、io_submit,内核中对应的接口为 aio_read/write 和 aio_complete。在客户端中,首先要断定该申请是否是 AIO 申请,而后在执行 aio_read/write 的时候,决定是否异步,aio_read/write 是实现的重点。

对于 AIO 读而言:首先要查看 data buff 和 offset 是否对齐,对于非 PAGE_SIZE 对应的申请,须要计算出其对应的物理 pages,而后顺次 pin user pages,提早被换出,再封装申请并异步下发。映射 page 到内核线性地址空间后,从存储后端读取到数据进行填充,数据填充完后,回调 aio_complete,并开释 pages 的援用计数。

期间要思考 pagecache 的影响,须要将重叠区间的 pagecache 进行回刷和期待,能够参考 filemap_write_and_wait_range 的解决。

此外,还要思考如下三类对齐的场景:

场景 1:date_len <= PAGE_SIZE,写入数据在同一个 page 的场景。
场景 2:date_len <= PAGE_SIZE,数据逾越两个 page 的场景。
场景 3:date_len > PAGE_SIZE,数据在首个 page 内有偏移。
对于写而言:能够参考读的逻辑,大体上也是封装申请异步下发。并发解决后,回调 aio_complete,在这个过程中,同样须要思考 pagecache 的影响。

性能数据

在实现 libaio 的反对后,客户端在应用 fio+libaio 场景的测试中,性能随着 iodepth 根本出现线性增长状态,直到达到客户端的性能下限,单客户端性能如下:

05 总结

在分布式文件系统中,客户不仅关注整个集群的性能,同时也会关注单个客户端的性能以及单线程下利用拜访的性能。对于很多业务而言,并发度不高,单线程的提早间接影响了零碎的性能;而局部业务逻辑 (如 Nginx,MySQL,seastar) 都应用到了 AIO 模型,如果客户端不反对 AIO,那么后端数据拜访的性能将会受到制约。

YRCloudFile 在新版本中实现客户端的 AIO 反对后,进一步补救了这一短板,将可能更好地适配这些利用场景。

正文完
 0