
为什么SSD会越用越慢?带你从底层架构分析GC与TRIM的物理真相
最近在做一个存储项目时遇到了一个现象,使用刚买回来的NVMe固态硬盘测试时性能很快,4K随机写轻松跑到几十万IOPS,延迟不到100微秒,换到一块旧的硬盘测试,系统的吞吐量明显下降了,await平均响应时间甚至能达到几十毫秒,这在us级响应的NVMe时代,绝对是不可思议的。
当时遇到这种情况,我的第一反应是觉得是硬盘使用寿命问题,其实分析下来真不像是硬件坏了,对于现代高速SSD来说,真正拖系统算力和总线带宽后腿的,是底层固件正在疯狂加班修bug——也就是大家常听说的GC垃圾回收(Garbage Collection)。
如果我们不了解闪存的物理规律、翻译层FTL的映射逻辑以及操作系统的文件管理机制,就根本没办法解释这种越用越慢的灵异现象,今天咱们就稍微往下挖一层,绕开操作系统,从NAND闪存的物理层出发,把决定SSD性能快慢的GC与TRIM机制扒开聊聊。
一、NAND闪存并非原地更新
要弄明白SSD为什么会掉速,先了解下机械硬盘的工作机制。

在使用机械硬盘时,盘片上涂的是磁性介质,如果我们想要修改某个扇区的数据,磁头会直接转过去,把那个位置的磁极性重新翻转一下就行了,新数据直接覆盖老数据,这个操作通常叫做原地更新(In-place Update)。
但在NAND闪存的物理世界里,不管是TLC还是QLC,这套做法就行不通了,闪存是靠往浮栅极里打电子来存数据,这种极其特殊的物理结构,决定了它有几条绕不开的地方:
1. 读写的基本单位是页(Page):一般是4KB或者16KB大小。
2. 擦除的基本单位是块(Block):一个Block里包着几百上千个Page,容量通常在16MB甚至更大。
3. 写前擦除(Erase-before-Write):不能像机械硬盘那样,直接往一个有数据的Page里覆盖写入,要想写新数据,这个Page必须是干干净净的已擦除状态。
这三条特性,直接决定了现代SSD控制器的核心工作模式:非原地更新(Out-of-place Update)。打个比方,操作系统让你把逻辑块地址为100的地方改成新数据,SSD内部的FTL主控没办法直接去改物理闪存上原来那个Page,它只能找一个全空的、干净的新Page,把新数据写进去,然后在内存的映射表里,把LBA 100指向这个新Page的物理地址。至于原来那个存着老数据的Page,就被打上了一个失效的标签,变成了一堆垃圾数据。
二、GC与Write Amplification
随着你的业务系统不停地写入、修改数据,SSD内部那些干净的Page很快就会被消耗光,渐渐地,各个物理Block里就混杂着一小部分有效数据,以及大量被打上失效标签的脏数据,当盘里剩下的空白Block低于设定的警戒线时,SSD的主控就着急了,它必须强行触发自救机制——GC(垃圾回收)。

在硬件底层看,GC的过程纯粹是一个体力活:
1. 找目标:FTL先去扫描所有的物理Block,挑出那些包含很多无效Page、但还有几张有效Page的半脏块。
2. 读出并搬运:把这个Block里的有效数据全部读出来,先放到主控的DRAM缓存里,然后再统一集中写到另一个完全干净的新Block中。
3. 擦除老块:原来那个Block里的数据全被腾空了,变成了垃圾,这时候,主控会给闪存颗粒发高压信号,执行Erase指令,一个十几兆的物理块重获新生。
这个来回折腾的过程,带来了一个极其恶劣的副作用:写放大(Write Amplification, WA)。
写放大的公式其实很简单:实际写入物理闪存的数据量 / 宿主机请求写入的数据量。
假设你的系统只要求改4KB的数据,但刚好触发了底层Block的空间告急,为了腾出这4KB的地方,固件被迫把整个Block里剩下的15MB有效数据全部读出来,再原封不动地写进新块里,宿主机明明只写了4KB,底层的颗粒却多挨了十几兆的写入损耗,所以这不仅消耗了SSD的擦写寿命,更是把本该服务业务的总线带宽占掉了。
所以这就引出了掉速的核心原因:前台垃圾回收(Foreground GC)。平时业务闲的时候,SSD会在后台偷偷摸摸做搬运(Background GC),我们感觉不到,但如果前端IO压力极大,比如大量的数据库并发写入,后台GC腾出干净空间的速度根本赶不上业务消耗的速度,干净的Block就会用光,主控只能被迫挂起宿主机的写入请求,强行进入前台GC状态。要知道,在微观时间里,读写一个Page只要几十到几百微秒,但执行一次Block的擦除操作,可能需要几个毫秒,当成千上万个IO请求被堵在硬件队列里,死等着那长达好几毫秒的擦除操作做完时,我们在操作系统层面看到的现象就是IOPS暴跌、系统卡死。
三、文件系统与底层固件的跨服聊天
写到这里,有人可能会想:既然垃圾数据这么占地方,为什么我在Linux里执行rm命令删掉几十个G的文件时,SSD不直接把这些空间回收了用来做GC呢?这里涉及到了计算机体系架构里一个非常经典的坑——抽象层的割裂。在Ext4、XFS这些文件系统眼里,万物皆文件,当你敲下rm的时候,文件系统为了保证响应速度,绝对不可能去把硬盘扇区挨个清零。它只是在元数据(Inode表和Block Bitmap)里改了个标记,说这块地方我不用了,你可以分给别人,在操作系统的认知里,删除操作到这里就完美结束了。
但是,底层SSD的主控不懂什么是Ext4,也不懂什么是Inode,它眼里只有干巴巴的LBA逻辑地址和PBA物理地址。文件系统在删文件的时候,并没有任何机制去通知底层主控这些LBA的数据作废了,于是,SSD主控依然会认为,只要我们没往这些LBA里覆盖写入新数据,那这里面存的就绝对是用户的核心资产,打死不能丢。这就造成了一个悲剧,操作系统明明已经不要的垃圾数据,在SSD触发GC的时候,居然被FTL当成宝贝一样,一遍又一遍地读出来、搬到新块里,这种无效搬运把GC的效率拉到了谷底,会严重加剧了写放大。
四、TRIM指令的功能
为了解决这个跨服聊天的尴尬局面,T13和NVM Express这些标准组织终于搞出了一个补丁——TRIM指令(在NVMe协议里叫Deallocate)。

TRIM并不是什么神秘的垃圾清理算法,说白了其实是个带外的消息通知协议,有了TRIM,删除文件的逻辑就闭环了。
1.文件系统依旧在元数据里把空间标记为空闲。
2.紧接着,系统的存储驱动层会通过PCIe总线,专门给SSD发一条TRIM报文,从LBA 0x1000到0x50000这片区域,我已经彻底删了。
3.SSD主控收到报文秒懂,立马去自己的映射表里,把这些LBA对应的物理Page全部标记为无效。
TRIM真正大显身手的时刻,是在未来的GC环节,当下一次底层触发GC,准备搬运某个Block里的数据时,主控一查映射表,发现这些Page已经被TRIM标记为作废了,那么在搬运的时候,它就会直接略过这些页面,连读都不读,等有效数据全搬完,直接给老Block通上高压电执行擦除操作。
没有了对无效数据的重复搬运,GC的执行效率直接起飞,写放大效应就被死死压制,这就解释了为什么开启TRIM支持后,SSD能在很长一段时间内维持住出厂时的巅峰写性能。
五、为什么有人喜欢留一手预留空间
原理搞清楚了,咱们聊点项目里的调优方法,为什么大佬们总是强调,重负载场景千万别拿消费级SSD去顶?关键就在于固件里的预留空间。

因为闪存必须异地更新,SSD手里必须时刻攥着一批空白物理块才能周转得开,消费级SSD为了在电商宣传页面上显得容量大、性价比高,标称1TB的盘,厂商通常只在底层预留7%左右的OP空间。这点空间,你稍微来点高并发写入,GC周转的池子就会被打穿,紧接着进入GC的降速,速度大打折扣,而真正的企业级NVMeSSD(比如标称3.2TB的盘,实际里面贴的闪存颗粒往往是4TB的),厂商在底层直接预留了28%甚至更多的OP空间,这片海量的物理空间操作系统看不见,是纯给主控做GC腾地方的后备资源,池子足够大,哪怕前端IO压力再变态,主控也有足够的缓冲余地在后台从容地擦除Block,从而保证我们的业务流转。这就是企业盘能达到稳态性能的秘密。
现在存储颗粒涨价非常迅猛,带动硬盘内存持续暴涨,如果我们手头预算紧,只有消费级SSD,又必须顶高并发怎么办?当然有办法:手动做OP。在给新买的1TB消费级SSD做分区的时候,咬咬牙,只给业务分800GB,剩下的200GB硬留着变成Unallocated未分配状态,千万别格式化,这么干的物理逻辑就是:因为这剩下的200GB没被文件系统接管,系统永远不会往这片LBA里写数据,在SSD主控的视角里,这200GB对应的物理块就是天然的、不会被占用的空白区。用这种软件分区的手段,可以给这块盘造出了20%的冗余OP,在随后的重负载压测中,我们会发现它的稳态IOPS极限被拉高几倍,缓和了掉速的毛病。
六、建立底层的系统全局观
从NAND的物理擦写机制,到GC的被动触发,再到TRIM的跨层通知,我们会发现,所谓的SSD掉速,其实是整个计算机体系在享受了固态存储极速随机读取的红利后,必须在底层付出的物理代价。当我们去设计一套高速落盘的日志系统,或者调优数据库的刷盘策略时,脑海里要能想到,总线那头的SSD主控,正在手忙脚乱地更新着映射表,要能感知到每一次毫无节制的碎片化写入,都会让底层的晶体管承受多大的高压擦除损耗;有了这种穿透软件直达物理底层的系统级视野,以后在面对诡异的IO报警时,自然能快速找到解决方案。
如果您对本篇文章感兴趣,欢迎WX关注本作者嵌入式软硬件系统,后续将分享更多关于PCIe软硬件、驱动、上位机相关的理论和实践知识。

专注于嵌入式软硬件相关经验分享、工程实践与技术探索,涵盖单片机、FPGA、PCIe、windows/linux驱动开发、Qt上位机软件以及测控系统设计等多方面内容。