暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

磁盘IO性能优化

SHAREit技术团队 2021-06-29
2067


数据库系统总会涉及非易失性存储,我们需要知道一个典型的计算机系统是如何进行存储管理的。

本文回顾硬盘的物理特性,硬盘的主要性能指标,以及操作是如何进行硬盘 I/O 性能优化的,最后参考开源系统来讨论如何根据硬盘特性进行系统设计。


一、磁盘IO背景知识

传统的HDD是“马达+磁头+磁盘”的机械结构,SSD则变成了“闪存介质+主控”的半导体存储芯片结构,两者有完全不同的数据存储介质和读写方式。对比如表1-1所示。

表1-2所示是某两款SSD和HDD的对比,由表可以看到的是,读写速度有从几倍到几百倍的差异,随机读写性能(速度和时延)差异最为明显
如表1-3所示,从内存拷贝1MB数据的时间大概在毫秒级,和SSD磁盘随机访问时间相当。而常规的文件发送需要4次内存拷贝过程,所以文件发送的过程中减少内存拷贝的次数也是磁盘IO优化的重要方向。

 

二、常见的硬盘 I/O 优化

通过上面的分析,我们知道硬盘(特别是HDD)的随机读写性能大幅低于连续读写性能,为了降低 I/O 成本,主要有以下方式:
  • 追加写:同时根据磁盘顺序读写快、随机读写慢的特点,尽量做追加写;

  • 使用用较大的文件:通过优化文件的大小提高读写性能

  • IO调度策略优化:根据IO的特点选择合适的IO调度策略

  • 零拷贝技术:通过用户态直接IO或者减少数据拷贝次数达到

这些设计思想也被许多开源软件广泛采用。


1.追加写
追加写的方式可以利用磁盘顺序写比随机写快很多的特点,数据库比较常用的方式是采用LSM-Tree这种数据结构。
Google BigTable的论文把 LSM-Tree(Log Structured-Merge Tree)这个古老的数据结构带回前沿,基于 LSM-Tree 的存储引擎有:Leveldb、Rocksdb、HBase、Cassandra 等等。不同于传统的 B 树类存储引擎,基于 LSM-Tree 的存储引擎尤其适合写多读少的场景。
LSM-Tree核心思想就是放弃部分读能力,换取写入的最大化能力。LSM-Tree ,这个概念就是结构化合并树的意思,它的核心思路其实非常简单,就是假定内存足够大,因此不需要每次有数据更新就必须将数据写入到磁盘中,而可以先将最新的数据驻留在内存中,等到积累到最后多之后,再使用归并排序的方式将内存内的数据合并追加到磁盘队尾(因为所有待排序的树都是有序的,可以通过合并排序的方式快速合并到一起)。
总之,LSM-Tree 充分利用了内存随机读写 + 顺序落盘 + 定期归并来获取最大性能。

2.使用较大的文件
硬盘最适合顺序的大文件 I/O 读写,在硬盘上分散的多个小文件会损害性能;同时,元数据过多也会带来很多 I/O 开销(请求很多次 inode)影响性能,所以我们尽量:
  • 将小文件合并为大文件

  • 优化元数据存储和管理

 

Google File System和 Facebook Haystack是两个典型的案例:

  • GFS 选择了当时看来相当大的 64M 作为数据存储的基本单位,就是为了减少大量元数据;

  • Facebook Haystack 同样将小文件集合成大文件来减少了元数据数目;同时精简元数据,去掉一切 Facebook 场景中不需要的元数据,压缩元信息到足够小并全部加载到内存中,避免请求 inode 带来的开销。


3.IO调度策略优化
文件系统在通过驱动读写磁盘时,不会立即将读写请求发送给驱动,而是延迟执行,这样Linux内核的I/O调度器可以将多个读写请求合并为一个请求或者排序(减少机械磁盘的寻址)发送给驱动,提升性能。
目前Linux版本主要支持3种调度机制:
  • CFQ,完全公平队列调度。早期Linux 内核的默认调度算法,它给每个进程分配一个调度队列,默认以时间片和请求数限定的方式分配IO资源,以此保证每个进程的 IO 资源占用是公平的。这个算法在IO压力大,且IO主要集中在某几个进程的时候,性能不太友好。

  • DeadLine,最终期限调度。这个调度算法维护了4个队列,读队列,写队列,超时读队列和超时写队列。当内核收到一个新请求时,如果能合并就合并,如果不能合并,就会尝试排序。如果既不能合并,也没有合适的位置插入,就放到读或写队列的最后。一定时间后, I/O调度器会将读或写队列的请求分别放到超时读队列或者超时写队列。这个算法并不限制每个进程的IO资源,适合IO压力大且IO集中在某几个进程的场景,比如大数据、数据库使用HDD磁盘的场景。

  • NOOP,也叫NONE,是一种简单的FIFO调度策略。因为固态硬盘支持随机读写,所以固态硬盘可以选择这最简单的调度策略,性能最好。


4.零拷贝方式
在 Linux 中零拷贝技术主要有 3 个实现思路:用户态直接 I/O、减少数据拷贝次数以及写时复制技术。
  • 用户态直接 I/O:应用程序可以直接访问硬件存储,操作系统内核只是辅助数据传输。这种方式依旧存在用户空间和内核空间的上下文切换,硬件上的数据直接拷贝至了用户空间,不经过内核空间。因此,直接 I/O 不存在内核空间缓冲区和用户空间缓冲区之间的数据拷贝。

  • 减少数据拷贝次数:在数据传输过程中,避免数据在用户空间缓冲区和系统内核空间缓冲区之间的CPU拷贝,以及数据在系统内核空间内的CPU拷贝,这也是当前主流零拷贝技术的实现思路。

  • 写时复制技术:写时复制指的是当多个进程共享同一块数据时,如果其中一个进程需要对这份数据进行修改,那么将其拷贝到自己的进程地址空间中,如果只是数据读取操作则不需要进行拷贝操作。



参考资料:

https://www.jianshu.com/p/fad3339e3448

https://juejin.cn/post/6844903949359644680

https://gist.github.com/jboner/284183


 SHAREit技术团队 

扫码 ╳ 关注我们

微信号|SHAREitTech

文章转载自SHAREit技术团队,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论