Linux 下 SMR 硬盘性能优化分析

0x00 起因

近期收到了一块问题硬盘,问题是在 Linux 上面反应慢。看了一下硬盘的型号 ST2000DM008 2T 硬盘 转速 7200 缓存 256M,一看参数还可以不应该出现卡顿的现象。随即去jd查询了一下价格,一看居然还不贵。本着商家的良心都是喂狗的基本原则。去继续搜索了一下,得到一个关键词 SMR 硬盘,看了无数的吐槽文章之后决定好好研究一下。

0x01 分析

先介绍一下硬盘的发展史,早期硬盘的磁极是水平放置的,也就是一条直线分成无数段,每一个段里有 2 个位置 用来存 0 或者 1 。 后来就变成了 PMR 垂直式的也就是说把之前的最小的段旋转 90 度以后,重新堆放,这样的好处是提升了存储的密度,但是带来的问题是如果只通电一次的话,数据会在几年以后丢失。但是这种情况基本上不会存在。因为硬盘不会只拷贝好数据以后就断电几年,目前这也是最常见的硬盘。

最后说一下 SMR,当达到物理的极限以后,商家还要增加容量降低成本,怎么办呢,那就只好压缩存储的最小单元。让一个磁头同时读取2个磁道的信息,那么问题来了,如果我只是要改写一个磁道上面的内容怎么办?那么会将另一个磁道的内容放置到缓存里面,然后不断的把缓存里面的数据重新写回对应的位置。那么问题来了,这样的话速度必然回慢下来,所以为了弥补这个缺陷,提高转速,增大缓存成为了必要的手段。

这样的好处是在顺序读写的时候性能爆表,但是在随机读写的时候性能直线下降,测试数据表明顺序读写速度可高达 100 MB,但是随机读写的数据惨不忍睹 只有 1MB 或 0.x MB。更由于固件优化的原因如果到手的是一块全 0 的全新硬盘,那么硬盘的固件在测速的时候会直接返回根本不去读写,可以跑出 “500MB” 的成绩,响应时间为 0 。

因为随机读写的弱鸡性能如果用来做系统盘,那只能卡顿的连北都找不到,基于前面的分析,我们从io的性能下手来尝试提升。 对待这种资源不足的问题只有2个方案,开源和节流。开源方面在限定io总数的情况下是不可能了,能做的只有节流了。那么在节流方面根据 io 消耗依次排序,应用系统>不同文件系统对是io的消耗>操作系统本身的消耗。那么优化的方面就要从这 3 方面来努力。
分别是

  1. 重新开发优化现有的应用系统改变写入的频次以及数据的大小
  2. 实验不同的文件系统对 io 消耗的测试
  3. 关闭操作系统本身不需要的服务,以及不常用的操作系统日志等

0x03 分析实践

作为 SA 可以做的是上面提到的后 2 点,我们先从实验不同文件系统开始进行尝试1。实验过程中配合关闭操作系统日志及不常用的服务进行对比。

1. ext4 优化

ext4 文件系统目前是最主流的 linux 下日志型文件系统之一,从 ext3 开始 ext 类型的文件系统加开发了 3 种日志模式,分别为 Writeback 模式,它仅记录元数据; Ordered 模式,它记录元数据,但写为元数据的数据是从日志中写入的;Journal 模式(最可靠的模式),它同时记录元数据和数据。注意,虽然 Journal 模式是确保文件系统一致的最佳选择,但它也是最慢的,因为所有数据都要经过日志 2

从日志下手进行实验,ext4 默认启用的是 Ordered 模式的日志系统(ext3同样也是),我们要更改为 Writeback 模式,使用 dd 命令来测试生成文件的速度来验证是否有所提升。下面来修改文件系统的日志记录方式,这里参考的是 SweeNeil 3 的方法。 首先查看一下 ext4 使用的是什么日志记录方式

sudo dmesg | grep -B 1 mounted filesystem

[    1.637628] PM: Image not found (code -22)
[    1.669041] EXT4-fs (sda1): mounted filesystem with ordered data mode. Opts: (null)

从上面可以看出sda1 使用的是 ordered data mode。 ex4 文件系统更改根文件系统的日志模式要在系统启动的时候添加内核引导参数来实现。具体做法为在内核引导参数的最后添加 rootflags=data=journal 这样的字眼,data 后面接就是日志的模式,可以写 journal 或者 writeback,因为默认是ordered 所以这种模式不用设置。 由于journal 是最安全最全的记录的,这里我们要使用 writeback 模式来进行速度的实验。 下面这个命令可以查询现有的内核引导参数

cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-4.19-x86_64 root=UUID=fda5d69b-9aeb-4d3c-aa84-5c79e8e79c7a rw quiet resume=UUID=4cea8e09-f68a-46e6-aa4c-4607689e8ee1

下面我们来修改内核引导的参数 一般的时候grub的引导配置文件为 /boot/grub/grub.cfg 也有在 /boot/grub2/grub.cfg 下面的编辑之前可以使用 find 命令或locate 名开先查找一下 grub.cfg 的所在位置使用 root 权限去编辑,在里面找到和上面启动内核参数相同的第一行(一般会有两行一样的),在最后加上 rootflags=data=writeback

linux   /boot/vmlinuz-4.19-x86_64 root=UUID=fda5d69b-9aeb-4d3c-aa84-5c79e8e79c7a rw  quiet resume=UUID=4cea8e09-f68a-46e6-aa4c-4607689e8ee1 
linux   /boot/vmlinuz-4.19-x86_64 root=UUID=fda5d69b-9aeb-4d3c-aa84-5c79e8e79c7a rw  quiet resume=UUID=4cea8e09-f68a-46e6-aa4c-4607689e8ee1 rootflags=data=writeback

保存后重启主机即可,开机以后进入到系统以后再使用下面的命令来查询是否已经生效。

cat /proc/cmdline 

生效以后我们开始测速

time dd if=/dev/zero of=test.file bs=1G count=2 oflag=direct

2+0 records in
2+0 records out
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 4.57648 s, 469 MB/s
dd if=/dev/zero of=test.file bs=1G count=2 oflag=direct  0.00s user 0.64s system 13% cpu 4.633 total

dd 参数说明4
if = : 输入文件名
of= : 输出文件名
bs= : 设置的块的大小
count=:块的个数
oflag=FLAGS:指定写的方式FLAGS
direct:读写数据采用直接IO方式
time 命令是用来记录命令使用的时间

经实验在 Ordered 模式下速度一般在400-500MB/s 在 writeback 模式下可达 600-800 MB/s ,可以看到是由 io 方面的提升(以上均在固态硬盘下实验)。

实测用这种方式来装机实验,smr 硬盘,速率不稳定,遇到缓存整理的情况比较多,一旦进入整理就会减缓主机的速度。所以不建议使用,但是在其他的 linux 机器上面会出现比较好的io性能,还能兼顾一些稳定性,能够应对突然的掉电。

2. ext2 实验

看到日志记录的方式会有io方面的提升,那么可以实验的无日志的记录方式,ext2 用 ext2 的方式重装,在安装阶段消耗时间较长的是在重建 ext2 文件系统阶段,后面可能明显的感受到安装速度极快。但是这种方式带来的问题在于,如果出现了掉电,那么需要将近 30 分钟来进行 fsck 的修复,且正常关机以后,下次启动还会修复。

3. ext3 文件系统

ext3 文件系统装机的时间太长所以直接放弃了。其他日志型文件系统的io性能均不能达到 ext 系列这里不再尝试。ext4 与 ext3 的无日志模式都没有 ext2 模式纯粹,且没有日志会造成安全性问题,所以这里也不再尝试。具体的参考资料是各个文件系的测试对比5

4.trim

在各种文章中都会提及 trim 技术,这个技术本来是给 SSD 的硬盘使用的,是给 SSD 硬盘做手动的磁盘整理使用的一个技术。由于 SMR 硬盘的缓存大,这里借用这个磁盘整理的技术来进行对 SMR 的磁盘整理。

我的预想是先做一次磁盘的整理,然后使用 crontab 每隔 2 分钟做一次磁盘整理,因为 2 分钟内一般不会写入太多的内容,所以整理的速度应该会非常之快,借此来弥补随机读写性能差的问题。Centos 下,已经有了现成的整理的 systemd 服务,没有被启用。里面的内容默认就是 2 周一次整理,提取有效的内容就是下面的脚本。

/usr/sbin/fstrim -all || true 

与 ext4 writeback 模式配合实验,结果是速度不稳定和单独的 ext4 writeback 模式情况基本上没有区别。在整理的时候硬盘 io 会急剧增大,没有达到预期的效果。

5.其他文件系统

Centos 7 默认可以格式化的文件系统有 ext 234、xfs、btrfs、vfat等,但是实际上可以用作 Linux 根文件系统的只有 ext 系列,xfs 和 btrfs 这 3 种配合 LVM 做排列组合。由于默认的 xfs 这里不再对 xfs 进行实验,下面进行 btrfs 进行实验 之前提到过各种文件系统的速度对比5,btrfs 的表现并不突出,而且还有将 SSD 优化成 HDD 的能力,本来不想实验,但是这是最后的选择了,没有选项了。

只好继续。 用 btrfs 进行了装机,部署应用后发现,硬盘指示灯的状态居然还不错,没有常亮只有频闪,这就见到了希望。正常使用测试,这速度非常的不错,基本上达到了与 PMR 硬盘速度持平的状态,SMR 硬盘的问题得到了极大的缓解。

6. 操作系统层面的优化

关于减小操作系统的 io 开销,可以从以下的几个方面入手,以上的实验过程都有进行操作系统的配置,最终发现操作系统本身的开销过小,不足以影响整体的 io 消耗。

  1. 调整操作系统的日志级别,调整操作系统日志级别为 emerg (实验过程中已经关闭了 rsyslog 的服务没有明显的影响)6
  2. 关闭无用的 systemd 服务7

0x04 结论

通过上面的实验,操作系统层面的 io 消耗几乎可以忽略不计,对 SMR 硬盘最友好的是 btrfs 文件系统。作为单 SMR 硬盘可以使用这个文件系统进行 Linux 装机,btrfs 是目前最接近 PMR 速度的文件系统。 参考文章


  1. https://yq.aliyun.com/articles/87436 ↩︎
  2. https://blog.csdn.net/qq_32473685/article/details/103585546 ↩︎
  3. https://blog.csdn.net/SweeNeil/article/details/88948646 ↩︎
  4. https://www.cnblogs.com/machangwei-8/p/10353628.html ↩︎
  5. https://blog.csdn.net/lzqinfen/article/details/44835553 ↩︎ ↩︎
  6. https://blog.csdn.net/u011630575/article/details/51966725 ↩︎
  7. https://blog.csdn.net/z1026544682/article/details/95747025 ↩︎
上一篇
下一篇