设计 SSD(固态硬盘)友好的程序

前言

为了提升我们的软件性能,我们有多种方法,如合理的数据结构、优秀的算法,还有非常重要的一点就是:依据软件所依附的硬件自身特性,设计能最大限度发挥硬件性能的软件。根据计算机内存快但无法持久化,硬盘可以持久化但是慢的特性,我们设计了「缓存」这一策略来提升性能;根据硬盘随机读写慢但顺序读写快这一特性,Kafka 用自己独特的方式来实现高吞吐量的队列。如今,由于 SSD 出色的性能以及逐渐降低的价格,有逐步代替 HDD(传统硬盘)的趋势,而我们之前的大部分程序是基于 HDD 开发的,并不能最好的发挥 SSD 的性能,因此,我们有必要了解 SSD 的特性,以及如何写更适合于 SSD 的程序。

SSD 介绍

SSD 是用固态电子存储芯片阵列而制成的硬盘,由控制单元和存储单元(FLASH芯片、DRAM芯片)组成。SSD 的每个数据位保存在由浮栅晶体管制成的闪存单元里。SSD整个都是由电子组件制成的,没有像硬盘那样的移动或者机械的部分。SSD 的内部架构如下:


SSD 内部架构

1. 使用寿命

SSD 的数据保存在浮栅晶体管中,浮栅晶体管使用电压来实现每个位的读写和擦除。写晶体管有两个方法:NOR 闪存和 NAND 闪存。目前大多数制造商都采用 NAND 闪存,NAND 闪存模块的一个重要特征是,他们的闪存单元是损耗性的,因此它们有一个寿命。衡量寿命的单位是 PE周期(program/erase cycles)

2. 性能

下图是 SSD 与其他存储介质的性能对比:

SSD 与其他存储介质的性能对比

其中 SLC、MLC、TLC 可以理解为不同类型的 SSD,下面会有介绍。

2. 存储结构

SSD 存储结构分为单元、页、块三层,下面依次介绍:

  • 单元(cell):单元是 SSD 存储的最小单位,由于采用的闪存类型不同,各类闪存中的单元能存储的数据也不同,目前有三种闪存单元类型:

    • 单层单元(SLC),这种的晶体管只能存储 1 个比特但寿命很长。
    • 多层单元(MLC),这种的晶体管可以存储 2 个比特,但是会导致增 加延迟时间和相对于SLC减少寿命。
    • 三层单元(TLC),这种的晶体管可以保存 3 个比特,但是会有更高的延迟时间和更短的寿命。
  • 页(page):页由许多单元组成,是我们读写 SSD 的最小单位,大多数硬盘的页大小是 2KB、4KB、8 KB 或 16 KB。当我们读 SSD 的数据时,最少读取一页(就算我们只需要 1 字节的数据);当我们写数据时,就算只需要写 1 字节,也会写一页,因此存在写入放大的问题。页不能被重复写

  • 块(block):块由许多页组成,是数据擦除的最小单元,大多数SSD每个块有128或256个页。这即表示一个块的大小可能在 256 KB 到 4 MB 之间。之前我们说过,页不能被重复写,要修改页的数据,必须先将页所在的块擦除,然后再重新写入新值(块中其他叶需要缓存然后再写入)。

3. 数据更新

由于 SSD 不支持数据覆盖写入,因此对于数据的更新,只能将老的数据标记为过期,在另外一个空闲的地方写入更新后的值。具体操作如下图:


数据更新过程

由上图我们可知,更新一个已有数据的流程如下:

  1. 将老的数据所在的页(PPN=0)标记为过期
  2. 在空闲页(PPN=3)写入新值 x'
  3. 当垃圾回收程序检测到该块(Block 1000)中存在过期数据(PPN=0),准备将其回收。而数据的擦除是以块为单位的,因此,需要先将 Block 1000 中有效的数据拷贝到另外一个空闲块(Block 2000),然后再将 Block 1000 擦除。

4. 损耗均衡

由于 SSD 存储单元的擦除次数是有限的,而擦除的最小单位是块,所以需要有一个机制来平衡各块的擦除次数,从而使整个 SSD 的各部分损耗更加均衡,这一机制称为损耗均衡。通过该技术,存储数据会在不同的块之间移动,以避免对同一块的频繁擦除。

5. 内部并行

因为物理限制的存在,异步 NAND 闪存 I/O 总线无法提供32-40 MB/s以上的带宽。由于一块 SSD 是由多个存储芯片组成的,因此我们可以通过并行读写多个存储芯片的方式来提升 SSD I/O 的性能。

SSD 内部将不同芯片中的多个块称为一个簇(clustered block),一次数据写入可以并行的写入到簇中的不同块中。如下图中,一次数据写入可以拆封成多个并行写入的任务,写入到黄色虚线框的簇中。

clustered block 并行写入

6. 垃圾回收

上面我们已经讲到,SSD 中的数据是不能被重复写的,必须先擦除然后再写,而擦除的速度非常慢(通常为毫秒级),SSD控制芯片会执行垃圾回收操作,即回收使用过的块,确保后续写操作能够快速分配到可用的块。

设计 SSD 友好的程序

针对上述介绍的 SSD 特性,在开发程序时我们可以做一些针对性的设计,以提高 SSD 的性能,还有延长 SSD 的使用寿命。

1. 对齐写入

SSD 数据写入的最小单元是页,因此,如果我们写入的数据小于页大小,会有两个危害:

  • 空间浪费:如果想再次利用页中的空闲部分,必须擦除所处的整个块
  • 读取效率低:一次读取读到的有效数据少,读相同数据需要更多次读操作

对齐写入指一次数据写入是页大小的整数倍,如果数据不够足,可以先缓冲在内存中,例如 Twitter 的 fatcache 就是凑够了1MB 才会写 SSD。

2. 相关的数据一起写

相关的数据一起写指的是对于经常被一起访问的数据,写的时候尽量一次同时写入,这样做有两个层面的好处:

  • 由于读写的最小单位是页,相关的数据写在一页上,数据读的时候效率高
  • 由于 SSD 存在内部并行的特性,一次将大量(簇大小的整数倍)相关的数据同时写入,内部会优化并行写入到各个存储芯片,读的时候也能并行读取,可以提升读的性能
3. 将冷热数据分开写

将冷热数据分开写主要是防止由于冷热数据范围频率不同而导致的写入放大,如果将冷热数据写一起,将会有两个层面的缺点:

  • 如果冷热数据在同一个页上:数据块小于16KB或不对齐16KB时,更新热数据不得不读改写冷数据。
  • 如果冷热数据在同一个块上:垃圾回收热数据时,不得不搬移并重写冷数据。
4. 缓存热数据

我们知道 SSD 对于数据更新,只能通过擦除-写入的方式,对于非常高频变化的数据,要对数据所在块进行频繁的擦除-写入,对整体性能会有较大影响。所以建议对热数据进行程序的缓存,而不是写入磁盘。

5. 读写分离

混合的小读写交叉的工作负载会妨碍内部缓存和预读取机制正常工作,并会导致吞吐量下降。最好的办法是避免同时发生的读操作和写操作,并将其以一个接一个的大数据块的形式实现,数据块大小推荐和簇大小相同。举个例子,如果要更新1000个文件,你可以遍历文件逐一读写,但会很慢。如果一次读取1000个文件然后一次写回1000个文件将会好很多。

6. 避免长时间大数据写入

SSD 内部存在异步垃圾回收进程,一般情况下不会影响正常的 I/O,但是如果长时间大数据写入,可能存在垃圾回收速度跟不上写入速度的情况,导致写入请求需要等待垃圾回收进程擦除块,影响性能。

7. 避免就地(in-place)更新优化

由于HDD在查找数据时又寻道时间,为了避免寻道产生的延迟,应用程序常常被优化成就地更新。但这个优化对于 SSD 并不适用,因为 SSD 没有寻道时间,且不支持覆盖写,更新数据必须先擦除,再写入,所以就地更新反而会造成性能下降,下图是 SSD 与 HDD 就地更新的性能对比:


HDD 和 SSD 随机更新和就地更新 qps
8. 对于大的(大于簇的大小)读写操作,单线程比多线程好

造成这个现象的原因就是我们上面说到过的 SSD 存在内部并行的机制。

  • 对于大的写入,由于内部并行机制的存在,单线程也能达到多线程的性能,并且,一个大的单线程写入比并发写入延迟时间更短。因此,在可用的时候,使用单线程大写入是最好的。
  • 对于大的读取,单线程读不仅可以依靠内部并行机制达到多线程读同样的性能,而且可以更好的使用预读取机制,因此比多线程并发读更优。
9. 对于小数据的读写,多线程比单线程好

如果数据太小且没办法进行合并后读写,就无法使用其内部并行机制,因此多线程更优。

总结

本文分析了一些 SSD 的特性,以及针对这些特性,我们应该如何设计更适合于 SSD 的程序。SSD 是提升磁盘性能的利器,目前看也大有替代传统 HDD 的趋势,因此建议广大工程师都对其有所了解。当然,SSD 目前也在快速的发展之中,可能有些特性会随着发展而改变,希望大家能及时同步最新知识。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容

  • 简介 SSD(Solid State Drives),俗称固态硬盘,相对原来主轴旋转,并无机械部分,主要由SS...
    mysia阅读 4,930评论 0 10
  • MySQL技术内幕:InnoDB存储引擎(第2版) 姜承尧 第1章 MySQL体系结构和存储引擎 >> 在上述例子...
    沉默剑士阅读 7,392评论 0 16
  • 今天是我的20岁生日,虽然过得并没什么特别,但是还是觉得这是我生命中一个非常重要的时刻,想要记录下此刻的心情。 想...
    苔花小姐阅读 196评论 1 0
  • 1. 雯雯部门最近碰到一个事,不大,但后果比较严重。 2. 一开始,雯雯心里也很不好受,虽然不是自己直接造成的,但...
    文晓玲阅读 1,500评论 12 10
  • 无论人生哪一个阶段,都必须要努力,不能停歇。不然跟不上大家进步的步伐。
    站在十字路口阅读 139评论 0 0