SSD的工作原理、GC和TRIM、写入放大以及性能评测
SSD的物理结构和工作原理
SSD是由SSD控制器,FLASH存储阵列,板上DRAM(可选),以及跟HOST接口,诸如SAS、SATA、或者PCIE也就是我们通常说的NVMe磁盘。它的结构图如下:
上面的Nand Flash表示的是Flash颗粒,SSD控制器通过若干个主控通道并行操作这些Flash颗粒,就像RAID0一样,这样可以提高数据写入的并行性以及效率。每一个Flash颗粒又进一步细分为多个block(块),每一个block又包含多个page,在SSD内部,SSD控制器和Flash之间的最小访问单元粒度是page。一般一个page的大小为4k,一个block包括16个pages。在写入数据的时候,像raid0的工作机制一样,同时并行地将数据写入到每个Flash颗粒的一个block中的可用的page中,当一个block写满之后会接着写下一个block 。
目前磁盘的分区格式大都变为GPT(也就是EFI)了,也就是将整个磁盘按照线性地址空间组织起来,通过LBA(Logical Block Address,逻辑地址)来寻址,每个LBA代表一个sector。操作系统一般会以页的方式来访问SSD,当用户写入一页数据时,SSD控制器会从block中找到一个page来存放这些数据,并且同时将用户的LBA和flash颗粒中的page这种对应关系纪录下来,作为一条记录加入到SSD内部维护的一张映射表(Map Table),当有数据修改时,会更新映射表中的相应记录。当用户要读取相应的数据时,SSD首先会去查找Map Table中找到存放数据的pages,然后从中将数据读取出来返回给用户。关于映射表,不同的SSD是存在不同的地方的,对于有DRAM的,直接将映射表存放在DRAM里,而没有DRAM的,则将这些映射关系也存储在了flash颗粒了。
SSD的GC和写入放大
GC是(Garbage Collection,垃圾回收)的缩写,是固态硬盘(SSD)的一个基本技术,它对SSD的性能和寿命有直接的影响。这里主要介绍一下GC是如何工作的。
当使用机械硬盘时,文件系统可以直接将新数据写入到旧数据存储的位置,即可以直接覆盖旧数据。在固态硬盘中,境况有所不同。如果想让存储无用数据的块写入新数据,就需要先把整个块删除,才可以写入新的数据,也就是说固态硬盘并不具备直接覆盖旧数据的能力。对于固态硬盘来说,GC(垃圾回收)是指把现存数据重新转移到其他闪存位置,并且把一些无用的数据彻底删除的过程。上面介绍了,数据写入的方式,即以页面为单位写入,但是要想删除数据却需要以块为单位。因此要删除无用的数据,固态硬盘首先需要把一个块内包含有用的数据先复制粘贴到全新的块中的页面内,这样原来块中包含的无用数据才能够以块为单位删除。删除后,才能够写入新的数据,而在擦除之前是无法写入新数据的。
说了GC之后,再说一下经常听到的SSD的写放大问题。因为当写入新数据时,如果SSD控制器找不到可以写入的page时,会执行GC过程,然后GC机制会将一些block中的有效数据合并写入其他的block中,然后将这些block的无效数据擦出,再将新数据写入到这些block中,而在整个过程中除了要写入用户的数据之外,实际上SSD还写入了一些其他block合并过来的数据,所以这就叫写入放大。
TRIM或DISCARD
了解了GC和写入放大之后,再来说一下TRIM和DISCARD。TRIM(或者DISCARD)的出现主要为了提高SSD垃圾资源的回收效率以及减少写入放大的发生。我们知道,在文件系统上删除某个文件时候,它只是简单的在逻辑数据表内把存储要删除的数据的位置标记为可用而已,而并不是真正将磁盘上的数据给删除掉。使用机械硬盘的系统根本就不需要向存储设备发送任何有关文件删除的消息,因为在将来,系统可以随时把新数据直接覆盖到无用的数据上。固态硬盘的情况就不同,只有当系统准备把新数据要写入那个位置的时候,固态硬盘才意识到原来这写数据已经被删除了!(无用数据。),而如果在这之前,SSD执行了GC操作,那么GC会把这些实际上已经删除了的数据还当作是有效数据进行迁移写入到其他的block中,这是没有必要的。
TRIM和DISCARD的支持,不仅仅要SSD实现这个功能,而是整个数据链路中涉及到的文件系统、RAID控制卡以及SSD都需要实现。要使用这个功能必须要在mount文件系统时,加上discard选项。如果想要确认SSD是否支持,可以通过hdparm -I命令检查。
SSD性能测试
我们在购买SSD时如何对其进行性能评估呢?不能只看它的官方数据,可以常用的性能测试比如fio、IOMeter等工具评估一下,并且需要测试一下SSD使用率达到80%以上时SSD的性能。
比较有趣的是,我发现有些SSD针对常用的测试工具fio做了优化,所以使用fio是测试不出真实性能,必须上IOMeter。