<audio id="audio" title="46 | SSD硬盘（上）：如何完成性能优化的KPI？" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/d1/bf/d115f9c1f7af989a3a44e0fed9948dbf.mp3"></audio>

随着3D垂直封装技术和QLC技术的出现，今年的“618”，SSD硬盘的价格进一步大跳水，趁着这个机会，我把自己电脑上的仓库盘，从HDD换成了SSD硬盘。我的个人电脑彻底摆脱了机械硬盘。

随着智能手机的出现，互联网用户在2008年之后开始爆发性增长，大家在网上花的时间也越来越多。这也就意味着，隐藏在精美App和网页之后的服务端数据请求量，呈数量级的上升。

无论是用10000转的企业级机械硬盘，还是用Short Stroking这样的方式进一步提升IOPS，HDD硬盘已经满足不了我们的需求了。上面这些优化措施，无非就是，把IOPS从100提升到300、500也就到头了。

于是，SSD硬盘在2010年前后，进入了主流的商业应用。我们在[第44讲](https://time.geekbang.org/column/article/113809)看过，一块普通的SSD硬盘，可以轻松支撑10000乃至20000的IOPS。那个时候，不少互联网公司想要完成性能优化的KPI，最后的解决方案都变成了换SSD的硬盘。如果这还不够，那就换上使用PCI Express接口的SSD。

不过，只是简单地换一下SSD硬盘，真的最大限度地用好了SSD硬盘吗？另外，即便现在SSD硬盘很便宜了，大部分公司的批量数据处理系统，仍然在用传统的机械硬盘，这又是为什么呢？

那么接下来这两讲，就请你和我一起来看一看，SSD硬盘的工作原理，以及怎么最大化利用SSD的工作原理，使得访问的速度最快，硬盘的使用寿命最长。

## SSD的读写原理

SSD没有像机械硬盘那样的寻道过程，所以它的随机读写都更快。我在下面列了一个表格，对比了一下SSD和机械硬盘的优缺点。

<img src="https://static001.geekbang.org/resource/image/a5/7c/a53e407311293609cb0753c7889a367c.jpeg" alt="">

你会发现，不管是机械硬盘不擅长的随机读写，还是它本身已经表现不错的顺序写入，SSD在这些方面都要比HDD强。不过，有一点，机械硬盘要远强于SSD，那就是耐用性。如果我们需要频繁地重复写入删除数据，那么机械硬盘要比SSD性价比高很多。

要想知道为什么SSD的耐用性不太好，我们先要理解SSD硬盘的存储和读写原理。我们之前说过，CPU Cache用的SRAM是用一个电容来存放一个比特的数据。对于SSD硬盘，我们也可以先简单地认为，它是由一个电容加上一个电压计组合在一起，记录了一个或者多个比特。

### SLC、MLC、TLC和QLC

能够记录一个比特很容易理解。给电容里面充上电有电压的时候就是1，给电容放电里面没有电就是0。采用这样方式存储数据的SSD硬盘，我们一般称之为**使用了SLC的颗粒**，全称是Single-Level Cell，也就是一个存储单元中只有一位数据。

<img src="https://static001.geekbang.org/resource/image/06/a7/0698c240459faa11254932905675dba7.jpeg" alt="">

但是，这样的方式会遇到和CPU Cache类似的问题，那就是，同样的面积下，能够存放下的元器件是有限的。如果只用SLC，我们就会遇到，存储容量上不去，并且价格下不来的问题。于是呢，硬件工程师们就陆续发明了**MLC**（Multi-Level Cell）、**TLC**（Triple-Level Cell）以及**QLC**（Quad-Level Cell），也就是能在一个电容里面存下2个、3个乃至4个比特。

<img src="https://static001.geekbang.org/resource/image/94/79/949106cb0ca5985a47388caef6925a79.jpeg" alt="">

只有一个电容，我们怎么能够表示更多的比特呢？别忘了，这里我们还有一个电压计。4个比特一共可以从0000-1111表示16个不同的数。那么，如果我们能往电容里面充电的时候，充上15个不同的电压，并且我们电压计能够区分出这15个不同的电压。加上电容被放空代表的0，就能够代表从0000-1111这样4个比特了。

不过，要想表示15个不同的电压，充电和读取的时候，对于精度的要求就会更高。这会导致充电和读取的时候都更慢，所以QLC的SSD的读写速度，要比SLC的慢上好几倍。如果你想要知道是什么样的物理原理导致这个QLC更慢，可以去读一读这篇[文章](https://www.anandtech.com/show/5067/understanding-tlc-nand/2)。

### P/E擦写问题

如果我们去看一看SSD硬盘的硬件构造，可以看到，它大概是自顶向下是这么构成的。

<img src="https://static001.geekbang.org/resource/image/6a/5e/6ac3cfd51d39d3e3022effc7e4255e5e.jpeg" alt="">

首先，自然和其他的I/O设备一样，它有对应的**接口和控制电路**。现在的SSD硬盘用的是SATA或者PCI Express接口。在控制电路里，有一个很重要的模块，叫作**FTL**（Flash-Translation Layer），也就是**闪存转换层**。这个可以说是SSD硬盘的一个核心模块，SSD硬盘性能的好坏，很大程度上也取决于FTL的算法好不好。现在容我卖个关子，我们晚一会儿仔细讲FTL的功能。

接下来是**实际I/O设备**，它其实和机械硬盘很像。现在新的大容量SSD硬盘都是3D封装的了，也就是说，是由很多个裸片（Die）叠在一起的，就好像我们的机械硬盘把很多个盘面（Platter）叠放再一起一样，这样可以在同样的空间下放下更多的容量。

<img src="https://static001.geekbang.org/resource/image/0e/d3/0eee44535a925825b657bcac6afb72d3.jpeg" alt="">

接下来，一张裸片上可以放多个**平面**（Plane），一般一个平面上的存储容量大概在GB级别。一个平面上面，会划分成很多个块（Block），一般一个块（Block）的存储大小， 通常几百KB到几MB大小。一个块里面，还会区分很多个页（Page），就和我们内存里面的页一样，一个页的大小通常是4KB。

在这一层一层的结构里面，处在最下面的两层块和页非常重要。

对于SSD硬盘来说，数据的**写入**叫作Program。写入不能像机械硬盘一样，通过**覆写**（Overwrite）来进行的，而是要先去**擦除**（Erase），然后再写入。

SSD的读取和写入的基本单位，不是一个比特（bit）或者一个字节（byte），而是一个**页**（Page）。SSD的擦除单位就更夸张了，我们不仅不能按照比特或者字节来擦除，连按照**页**来擦除都不行，我们必须按照**块**来擦除。

而且，你必须记住的一点是，SSD的使用寿命，其实是每一个块（Block）的擦除的次数。你可以把SSD硬盘的一个平面看成是一张白纸。我们在上面写入数据，就好像用铅笔在白纸上写字。如果想要把已经写过字的地方写入新的数据，我们先要用橡皮把已经写好的字擦掉。但是，如果频繁擦同一个地方，那这个地方就会破掉，之后就没有办法再写字了。

我们上面说的SLC的芯片，可以擦除的次数大概在10万次，MLC就在1万次左右，而TLC和QLC就只在几千次了。这也是为什么，你去购买SSD硬盘，会看到同样的容量的价格差别很大，因为它们的芯片颗粒和寿命完全不一样。

### SSD读写的生命周期

下面我们来实际看一看，一块SSD硬盘在日常是怎么被用起来的。

我用三种颜色分别来表示SSD硬盘里面的页的不同状态，白色代表这个页从来没有写入过数据，绿色代表里面写入的是有效的数据，红色代表里面的数据，在我们的操作系统看来已经是删除的了。

<img src="https://static001.geekbang.org/resource/image/96/81/966e51db8354922b533e1db236337e81.jpeg" alt="">

一开始，所有块的每一个页都是白色的。随着我们开始往里面写数据，里面的有些页就变成了绿色。

然后，因为我们删除了硬盘上的一些文件，所以有些页变成了红色。但是这些红色的页，并不能再次写入数据。因为SSD硬盘不能单独擦除一个页，必须一次性擦除整个块，所以新的数据，我们只能往后面的白色的页里面写。这些散落在各个绿色空间里面的红色空洞，就好像硬盘碎片。

如果有哪一个块的数据一次性全部被标红了，那我们就可以把整个块进行擦除。它就又会变成白色，可以重新一页一页往里面写数据。这种情况其实也会经常发生。毕竟一个块不大，也就在几百KB到几MB。你删除一个几MB的文件，数据又是连续存储的，自然会导致整个块可以被擦除。

随着硬盘里面的数据越来越多，红色空洞占的地方也会越来越多。于是，你会发现，我们就要没有白色的空页去写入数据了。这个时候，我们要做一次类似于Windows里面“磁盘碎片整理”或者Java里面的“内存垃圾回收”工作。找一个红色空洞最多的块，把里面的绿色数据，挪到另一个块里面去，然后把整个块擦除，变成白色，可以重新写入数据。

不过，这个“磁盘碎片整理”或者“内存垃圾回收”的工作，我们不能太主动、太频繁地去做。因为SSD的擦除次数是有限的。如果动不动就搞个磁盘碎片整理，那么我们的SSD硬盘很快就会报废了。

说到这里，你可能要问了，这是不是说，我们的SSD硬盘的容量是用不满的？因为我们总会遇到一些红色空洞？

<img src="https://static001.geekbang.org/resource/image/e7/74/e7fcd994384145eefde614aaf3b45874.jpeg" alt="">

没错，一块SSD的硬盘容量，是没办法完全用满的。不过，为了不得罪消费者，生产SSD硬盘的厂商，其实是预留了一部分空间，专门用来做这个“磁盘碎片整理”工作的。一块标成240G的SSD硬盘，往往实际有256G的硬盘空间。SSD硬盘通过我们的控制芯片电路，把多出来的硬盘空间，用来进行各种数据的闪转腾挪，让你能够写满那240G的空间。这个多出来的16G空间，叫作**预留空间**（Over Provisioning），一般SSD的硬盘的预留空间都在7%-15%左右。

## 总结延伸

到这里，相信你对SSD硬盘的写入和擦除的原理已经清楚了，也明白了SSD硬盘的使用寿命受限于可以擦除的次数。

仔细想一想，你会发现SSD硬盘，特别适合读多写少的应用。在日常应用里面，我们的系统盘适合用SSD。但是，如果我们用SSD做专门的下载盘，一直下载各种影音数据，然后刻盘备份就不太好了，特别是现在QLC颗粒的SSD，它只有几千次可擦写的寿命啊。

在数据中心里面，SSD的应用场景也是适合读多写少的场景。我们拿SSD硬盘用来做数据库，存放电商网站的商品信息很合适。但是，用来作为Hadoop这样的Map-Reduce应用的数据盘就不行了。因为Map-Reduce任务会大量在任务中间向硬盘写入中间数据再删除掉，这样用不了多久，SSD硬盘的寿命就会到了。

好了，最后让我们总结一下。

这一讲，我们从SSD的物理原理，也就是“电容+电压计”的组合，向你介绍了SSD硬盘存储数据的原理，以及从SLC、MLC、TLC，直到今天的QLC颗粒是怎么回事儿。

然后，我们一起看了SSD硬盘的物理构造，也就是裸片、平面、块、页的层次结构。我们对于数据的写入，只能是一页一页的，不能对页进行覆写。对于数据的擦除，只能整块进行。所以，我们需要用一个，类似“磁盘碎片整理”或者“内存垃圾回收”这样的机制，来清理块当中的数据空洞。而SSD硬盘也会保留一定的预留空间，避免出现硬盘无法写满的情况。

到了这里，我们SSD硬盘在硬件层面的写入机制就介绍完了。不过，更有挑战的一个问题是，在这样的机制下，我们怎么尽可能延长SSD的使用寿命呢？如果要开发一个跑在SSD硬盘上的数据库，我们可以利用SSD的哪些特性呢？想要知道这些，请你一定要记得回来听下一讲。

## 推荐阅读

想要对于SSD的硬件实现原理有所了解，我推荐你去读一读这一篇[Understand TLC NAND](https://www.anandtech.com/show/5067/understanding-tlc-nand)。

## 课后思考

现在大家使用的数据系统里，往往会有日志系统。你觉得日志系统适合存放在SSD硬盘上吗？

欢迎在留言区写下你的思考。如果有收获，你也可以把这篇文章分享给你的朋友。


