固态硬盘:赶紧入手一块!
我从 20 世纪 90 年代就开始组装电脑,所以见证了很多新技术逐渐成为主流。大多数都是摩尔定律预测的稳步、渐进式的改进,但其他一些则是游戏规则改变者,是真正以令人惊讶的方式推动性能向前发展的创新。我记得安装了我的第一块 3D 显卡后启动《雷神之锤》——真是天壤之别!我第一次从固态硬盘 (SSD) 启动时,又找回了同样的感觉——哇,真是太不一样了!
然而,在最近一次志同道合的 Linux 用户聚会上,我了解到我的许多同行实际上还没有转向固态硬盘。在该群体中,最初不愿尝试固态硬盘的主要原因可以归结为三个主要担忧:
-
我担心它们的可靠性;我听说它们会磨损。
-
我不确定它们是否能很好地与 Linux 配合工作。
-
我不确定固态硬盘真的会在我的系统上产生多大影响。
幸运的是,这三个担忧要么是基于误解、过时的数据、夸大其词,要么就是不正确的。
固态硬盘可靠性概述固态硬盘与硬盘驱动器的区别
传统的硬盘驱动器 (HDD) 在读取或写入文件时可能会出现两个机械延迟:将读/写头旋转到正确的半径,以及等待盘片旋转直到文件开头到达磁头(图 1)。驱动器就位以读取新文件所需的时间称为寻道时间。当您听到独特的硬盘驱动器咔哒声时,那是执行器臂在移动以访问许多不同的文件位置。例如,我的硬盘驱动器(一个相当典型的 2011 年 7200 RPM 消费级驱动器)的平均寻道时间约为 9 毫秒。

图 1. 硬盘驱动器
固态硬盘没有旋转盘片和读/写头,而是将数据存储到闪存芯片阵列中。因此,当请求新文件时,固态硬盘的内部存储器可以在亚毫秒内找到并开始访问正确的存储器位置。虽然从闪存读取本身速度并不快,但固态硬盘可以并行地从多个不同的芯片读取,以提高性能。这种并行性和近乎瞬时的寻道时间使得固态硬盘在大多数基准测试中都明显快于硬盘驱动器。我的固态硬盘(一个相当典型的 2012 年设备)的寻道时间为 0.1 毫秒——真是很大的改进!
可靠性和寿命
比较硬盘驱动器和固态硬盘的可靠性数据非常难找到。故障率比较要么没有足够多年的数据,要么是基于旧的第一代固态硬盘,这些固态硬盘不能代表当前市场上的驱动器。虽然固态硬盘受益于没有移动部件(对于笔记本电脑等移动设备尤其有利),但传统观点是,当前固态硬盘的故障率与硬盘驱动器接近。即使它们高或低几个百分点,考虑到两种驱动器类型都有非零故障率,您在任何一种情况下都需要备份解决方案。
除了可靠性之外,固态硬盘确实存在独特的寿命问题,因为存储中的 NAND 闪存单元具有独特的预期寿命限制。每个单元的寿命取决于其单元类型。目前,有三种类型的 NAND 闪存单元:
-
SLC(单层单元)NAND:每个单元一位,约 10 万次写入。
-
MLC(多层单元)NAND:每个单元两位,约 1 万到 3 千次写入,比 SLC 慢。写入范围取决于单元的物理尺寸——较小的单元制造成本更低,但可以处理的写入次数更少。
-
TLC(三层单元)NAND:约 1 千次写入,比 MLC 慢。
有趣的是,所有三种类型的单元都在幕后使用相同的晶体管结构。聪明的工程师们找到了一种方法,使单个闪存单元在 MLC 或 TLC 模式下保存更多信息。在编程时,他们可以使用低电压、中低电压、中高电压或高电压来表示单个单元中的四种独特状态(两位)。缺点是,随着单元被写入数千次,浮栅底部的氧化绝缘体会开始退化,并且每种状态所需的电压量会增加(图 2)。对于 SLC 来说,这没什么大不了的,因为状态之间的差距很大,但对于 MLC 来说,有四种状态而不是两种,因此每种状态电压之间的空间量会缩短。对于 TLC 的三位信息,有六种状态,因此每个电压范围之间的距离甚至更短。

图 2. NAND 闪存单元
最后的转折是写入放大。即使操作系统发送 1MB 的数据,固态硬盘实际上也可能在幕后进行更多写入,用于诸如磨损均衡和低效垃圾回收之类的操作(如果未启用 TRIM 支持,请参阅本文后面的 TRIM 部分)。我见过的大多数实际写入放大值都在 1.1 到 3.0 之间,具体取决于数据的可压缩程度以及固态硬盘在垃圾回收和磨损均衡方面的智能程度。
那么,您可以期望固态硬盘为您服务多久?寿命取决于您写入多少数据,而 tune2fs 实用程序可以非常轻松地从您现有的文件系统中估算出来。运行 tune2fs -l /dev/<device>
。(提示:如果您正在使用 LVM,统计信息将位于 dm-X 设备下,而不是 sdaX 设备下。)感兴趣的关键字段是“文件系统创建时间”和“生命周期写入次数”。使用这些来计算自文件系统创建以来每天的平均 GB 数。对于我的笔记本电脑,它是 2.7GB/天,对于我的工作站,它是 6.3GB/天。有了这些速率,再加上对写入放大的粗略猜测,您可以估计任何固态硬盘的寿命。
Est. Lifespan (y) = SSDCapacity(GB) * (WriteLimit based on cell type) ------------------------------------------------- DailyWriteRate (GB/day) * WriteAmplification * 365 (days/yr)
因此,如果我要调整 256GB 三星 840 Evo(使用 TLC 单元)的大小,写入速率为 6.3GB/天,写入放大率为 3,那么在失去写入新数据能力之前,它应该能为我提供大约 37 年的服务。
Linux 的固态硬盘注意事项TRIM
撤销删除实用程序之所以有效,是因为当您删除文件时,您实际上只是删除了文件系统指向该文件的指针,并将文件内容留在磁盘上。文件系统知道新释放的空间,并最终会重用它,但驱动器不知道。硬盘驱动器可以像写入新扇区一样高效地覆盖数据,因此这实际上不会损害它们,但这会减慢固态硬盘的写入操作,因为它们无法高效地覆盖数据。
固态硬盘在内部将数据组织成 4k 页,并将 128 页分组到一个 512k 块中。固态硬盘只能写入空 4k 页,并以 512k 块增量擦除。这意味着,虽然固态硬盘可以非常快速地写入,但覆盖是一个慢得多的过程。TRIM 命令通过为文件系统提供一种方法来告知固态硬盘已删除的页,从而使您的固态硬盘以最高速度运行。这使驱动器有机会在后台执行缓慢的覆盖过程,确保您始终拥有大量可用的空 4k 页。
Linux TRIM 支持默认未启用,但很容易添加。一个需要注意的地方是,如果您的文件系统和固态硬盘之间有额外的软件层,这些层也需要启用 TRIM。例如,我的大多数系统都有固态硬盘,使用 LUKS/dm-crypt 进行全盘加密,使用 LVM 进行简单卷管理,最后是 ext4 格式化的文件系统。以下是如何启用 TRIM 支持,从最接近驱动器的层开始。
dm-crypt 和 LUKS
如果您未使用加密文件系统,则可以跳到 LVM 说明。自内核 3.1 以来,dm-crypt 中已支持 TRIM。修改 /etc/crypttab,为固态硬盘上的设备添加 discard 关键字
#TargetName Device KeyFile Options
sda5_crypt UUID=9ebb4c49-37c3...d514ae18be09 none luks,discard
注意:在加密分区上启用 TRIM 确实会使攻击者更容易暴力破解设备,因为他们现在将知道哪些块未使用。
LVM
如果您未使用 LVM,则可以跳到文件系统部分。自内核 2.6.36 以来,LVM 中已支持 TRIM。
在 /etc/lvm/lvm.conf 的“devices”部分中,添加一行 issue_discards = 1
devices {
...
issue_discards = 1
..
}
...
文件系统
完成任何所需的 dm-crypt 和 LVM 编辑后,更新 initramfs,然后重新启动
sudo update-initramfs -u -k all
虽然 Btrfs、XFS、JFS 和 ext4 都支持 TRIM,但我在此处仅介绍 ext4,因为它似乎是最广泛使用的。要测试 ext4 TRIM 支持,请尝试手动 TRIM 命令:fstrim <挂载点>
。如果一切顺利,该命令将运行一段时间并退出。如果它退出并显示任何错误,则说明文件系统和设备之间的设置存在问题。重新检查您的 LVM 和 dm-crypt 设置。
以下是 /(已设置为 TRIM)和 /boot(未设置)的输出示例
~$ sudo fstrim /
~$ sudo fstrim /boot
fstrim: /boot: FITRIM ioctl failed: Inappropriate ioctl for device
如果手动命令有效,您可以决定是使用 ext4 文件系统中内置的自动 TRIM,还是运行 fstrim
命令。使用自动 TRIM 的主要好处是您不必考虑它,并且它几乎可以立即回收可用空间。自动 TRIM 的一个缺点是,如果您的驱动器没有良好的垃圾回收逻辑,则文件删除可能会很慢。另一个缺点是,如果驱动器快速运行 TRIM,您将没有机会通过撤销删除实用程序找回您的数据。在可用空间充足的驱动器上,我通过 cron 使用 fstrim 命令。在空间紧张的驱动器上,我使用自动 ext4 方法。
如果您想走自动路线,启用自动 TRIM 很简单——只需将 discard
选项添加到相关 /etc/fstab 条目的 options 部分即可。对于手动 TRIM,只需将 fstrim <挂载点>
放入 cron 作业中,或在您方便时手动运行它即可。
无论您是否使用 discard
选项,您可能都希望将 noatime
选项添加到 /etc/fstab。启用 atime(默认设置)后,每次访问文件时,都会更新访问时间,从而消耗您宝贵的写入周期。(一些教程要求您也包含 nodiratime,但 noatime 就足够了。)因为大多数应用程序不使用 atime 时间戳,所以关闭它应该可以提高驱动器的寿命
/dev/mapper/baldyl-root / ext4 noatime,discard,errors=remount-ro 0 1
分区对齐
当固态硬盘首次发布时,许多磁盘分区系统仍然基于旧的基于扇区的逻辑来放置分区。如果分区边界与固态硬盘的内部 512k 块擦除大小没有很好地对齐,则可能会导致问题。幸运的是,主要的分区工具现在默认使用 512k 兼容范围
-
自 util-linux 版本 2.17.1(2010 年 1 月)以来,fdisk 使用 1 兆字节边界。
-
自版本 2.02.73(2010 年 8 月)以来,LVM 默认使用 1 兆字节边界。
如果您想知道您的分区是否与正确的边界对齐,以下是来自 Intel X25-M 固态硬盘的示例输出,擦除块大小为 512k
~$ sudo sfdisk -d /dev/sda
Warning: extended partition does not start at a cylinder boundary.
DOS and Linux will interpret the contents differently.
# partition table of /dev/sda
unit: sectors
/dev/sda1 : start= 2048, size= 497664, Id=83, bootable
/dev/sda2 : start= 501758, size=155799554, Id= 5
/dev/sda3 : start= 0, size= 0, Id= 0
/dev/sda4 : start= 0, size= 0, Id= 0
/dev/sda5 : start= 501760, size=155799552, Id=83
由于主分区 (sda5) 的起始和结束编号都可以被 512 整除,因此一切看起来都不错。
在 Linux 中监控固态硬盘
我已经介绍了运行 tune2fs -l <device>
是获取文件系统设备统计信息的好地方,但是这些统计信息在您重新格式化文件系统时会被重置。如果您想获取更长时间范围的统计信息(在驱动器级别),smartctl 就是用于此目的的工具。SMART(自我监控、分析和报告技术)是 ATA 标准的一部分,它提供了一种让驱动器跟踪和报告关键统计信息的方法,最初的目的是预测驱动器故障。由于驱动器写入量对于固态硬盘非常重要,因此大多数制造商都将其包含在 SMART 输出中。在固态硬盘设备上运行 sudo smartctl -a /dev/<device>
,您将获得大量有趣的统计信息。如果您在 smartctl 输出中看到消息“Not in smartctl database”,请尝试构建最新版本的 smartmontools。
每个供应商的统计信息标签可能不同,但您应该能够找到诸如“Media_Wearout_Indicator”之类的字段,该字段将从 100 开始倒数,直到驱动器接近闪存磨损极限,以及诸如“Lifetime_Writes”或“Host_Writes_32MiB”之类的字段,这些字段指示已写入驱动器的数据量(图 3)。
图 3. smartctl 输出(已修剪)
其他通用技巧交换空间:如果您的计算机正在积极使用交换空间,那么额外的 RAM 可能比固态硬盘更适合升级。鉴于寿命与写入紧密相关,您最不希望做的就是将数 GB 的交换空间反复泵入和泵出驱动器。
硬盘驱动器仍然发挥作用:如果您有空间,则可以通过保留硬盘驱动器来获得两全其美的效果。它是存储音乐、电影和其他不需要快速 I/O 的媒体的好地方。根据您对固态硬盘写入的严格程度,您甚至可以将 /tmp、/var 甚至只是 /var/log 等文件夹挂载在硬盘驱动器上,以减少固态硬盘写入。Linux 灵活的挂载和分区工具使这变得轻而易举。
固态硬盘可用空间:当固态硬盘有足够的可用空间用于磨损均衡和垃圾回收时,它们的运行效果最佳。调整大小并管理您的固态硬盘,使其保持在 80% 以下的满容量。
破坏 TRIM 的因素:RAID 设置无法将 TRIM 传递到底层驱动器,因此请谨慎使用此模式。在 BIOS 中,确保您的控制器设置为 AHCI 模式而不是 IDE 仿真模式,因为 IDE 模式不支持 TRIM 并且通常速度较慢。
固态硬盘性能现在让我们进入问题的核心——固态硬盘如何使常见任务更快地完成的实际、真实世界的示例。
测试设置
在基准测试之前,我有一个固态硬盘用于我的 Linux 操作系统,另一个固态硬盘用于我需要启动到 Windows 7 时,还有一个硬盘驱动器用于存储媒体文件和执行低吞吐量、高容量的工作(例如调试 JVM 转储或编码视频)。我使用 partimage
备份了硬盘驱动器,然后我使用 Clonezilla 可启动 CD 将我的 Linux 固态硬盘克隆到硬盘驱动器上。虽然大多数来源都说您不必担心 ext4 上的碎片,但我还是在硬盘驱动器上使用了 ext4 碎片整理实用程序 e4defrag
,只是为了让它尽最大努力跟上固态硬盘的速度。
以下是我用于基准测试的开发工作站上的硬件——非常标准的配置:
-
CPU:3.3GHz Intel Core i5-2500k CPU。
-
主板:Gigabyte Z68A-D3H-B3(Z68 芯片组)。
-
内存:8GB (2x4GB) 1333 DDR3。
-
操作系统:Ubuntu 12.04 LTS(64 位,内核 3.5.0-39)。
-
固态硬盘:128GB OCZ Vertex4。
-
硬盘驱动器:1TB 三星 Spinpoint F3,7200 RPM,32MB 缓存。
我选择了一组十个测试,试图展示一些典型的 Linux 操作。我在每次测试后使用 echo 3 | sudo tee /proc/sys/vm/drop_caches
清除了磁盘缓存,并在完成一组测试后重新启动。我对每个驱动器运行了五次该组测试,并在下面显示的条形图上绘制了平均值加上 95% 置信区间。
启动时间
因为我是测试工作站上的唯一用户,并且使用全盘加密,所以 X 设置为自动登录。一旦 cryptsetup 提示我输入磁盘密码,系统将直接跳过典型的 GDM 用户登录进入我的桌面。这使得测量启动时间变得复杂,因此为了获得最准确的测量结果,我使用了 bootchart 包,该包提供了一个非常酷的甘特图,显示每个组件的启动时间(图 4 中显示了部分输出)。我使用 Xorg 进程启动来指示 X 何时启动,使用 Dropbox 面板小程序启动来指示 X 何时可用,并减去了 cryptsetup 中花费的时间(其持续时间更多地取决于我输入磁盘密码尝试的次数,而不是任何磁盘的速度)。固态硬盘在这里击败了所有竞争对手。

图 4. bootchart 输出
表 1. 启动时间测试 | 硬盘驱动器(秒) | 固态硬盘(秒) | 快 % |
Xorg 启动 | 19.4 | 4.9 | 75% |
桌面就绪 | 33.4 | 6.6 | 80% |

图 5. 启动时间
应用程序启动时间
为了测试应用程序启动时间,我测量了 Eclipse 4.3(J2EE 版本)、军团要塞 2 (TF2) 和 Tomcat 7.0.42 的启动时间。Tomcat 有四个 WAR 文件,每个文件约 50MB,在启动时需要解压缩。Tomcat 在日志中提供了服务器启动时间,但我必须手动测量 Eclipse 和军团要塞。一旦工作区可见,我就停止了 Eclipse 的计时。对于军团要塞 2,我使用了在 Steam 客户端中按下“Play”和军团要塞 2 “Play”菜单出现之间的时间。
表 2. 应用程序启动时间测试 | 硬盘驱动器(秒) | 固态硬盘(秒) | 快 % |
Eclipse | 26.8 | 11.0 | 59% |
Tomcat | 19.6 | 17.7 | 10% |
TF2 | 72.2 | 67.1 | 7% |

图 6. 应用程序启动时间
这三个应用程序之间存在相当大的差异,其中 Eclipse 从固态硬盘中获益最多,而 Tomcat 和军团要塞 2 的收益是存在的,但不太明显。
单文件操作
为了测试单文件 I/O 速度,我通过 time dd if=/dev/zero of=f1 bs=1048576 count=256
创建了一个约 256MB 的文件,将其复制到一个新文件,然后通过 cat
读取它,重定向到 /dev/null。我使用 time 实用程序来捕获每个测试的实际经过时间。
测试 | 硬盘驱动器(秒) | 固态硬盘(秒) | 快 % |
创建 | 1.5 | 0.5 | 67% |
复制 | 3.3 | 1.1 | 69% |
读取 | 2.2 | 0.2 | 63% |

图 7. 文件 I/O
多文件操作
首先,我通过 tar -c ~/workspace > w.tar
归档了我的 1.1GB Eclipse 工作区中的 20 万个文件,以测试归档速度。其次,我使用 find -name "*.java" -exec fgrep "Foo" {} > /dev/null
来模拟在 7k 个 java 文件中查找关键字。我使用 time 实用程序来捕获每个测试的实际经过时间。这两个测试都使硬盘驱动器非常嘈杂,因此看到明显的差异我并不感到惊讶。
测试 | 硬盘驱动器(秒) | 固态硬盘(秒) | 快 % |
tar | 123.2 | 17.5 | 86% |
find & fgrep | 34.3 | 12.3 | 64% |

图 8. 多文件 I/O
总结如果您还没有考虑过固态硬盘,或者因为此处提到的任何原因而退缩,我希望本文能促使您冒险尝试一下。
就可靠性而言,现代固态硬盘的性能与硬盘驱动器相当。(无论如何,您都需要良好的备份。)如果您担心寿命,您可以使用现有系统的数据来估算当前一代 MLC 或 TLC 驱动器的寿命。
Linux 中对固态硬盘的支持已经存在一段时间了,即使您只是默认安装主要的 Linux 发行版,它也能很好地工作。TRIM 支持、一些 ext4 调整以及通过 tune2fs 和 smartctl 进行监控都可以帮助您维护和监控固态硬盘的整体健康状况。
最后,一些真实世界的性能基准测试说明了固态硬盘如何提高任何使用磁盘存储的操作的性能,尤其是涉及许多不同文件的操作。
因为即使是仅用于操作系统的预算型固态硬盘也可以提供显着的性能提升,所以我希望如果您一直在犹豫不决,现在就尝试一下。
