笔者目前开发运维的存储系统的服务器都跑在SSD之上,目前单机服务器最大的SSD容量有4T之多。(公司好有钱,以前在实验室都只有机械硬盘用的~~)但SSD本身的特性与机械硬盘差距较大,虽然说在性能上有诸多优势,但是如果使用的方式方法不对,反而会事倍功半。所以笔者花时间调研了一下固态硬盘的结构与特性,并且总结了一些避免SSD写放大性能下降的法则,希望对大家有所帮助~~

1.SSD的写放大

首先我们来看看什么是写放大,写放大(Write amplification)是2008年,由英特尔和SiliconSystems在论文之中首次提出:它表现为在SSD上实际写入的数据远远大于用户写入数据。

为什么会产生这样的现象呢,我们要回归到固态硬盘原本的特性。首先固态硬盘与传统的机械硬盘不同的点在于它不能够覆盖写。所以对于已经存在数据SSD来说,一次数据的写入分为2个动作:

  • 1、擦除SSD上已有的数据。
  • 2、写入新的数据。

写入放大的问题就出了这个部分,因为SSD每次写入的最小单位为Page,每个Page是4KB大小,而每次擦除的大小单位为BlockBlock通常由64或128个Page组成。也就是说,正是由于SSD写入与擦除的单位大小不匹配,导致了写入放大。如果仅仅是写入单一Page的数据,而单个Block之中没有了空余的Page,则需要擦除一个Block的数据,之后再写入一个Block的数据。所以说,本身只需要4KB的写入,"放大"了64倍甚至是128倍!由于SSD的寿命取决于擦除次数,所以写入放大会大大影响到SSD的使用寿命

OK,了解了写入放大的现象之后,我们接下来怎么样会导致写入放大的现象呢?

  • 写入量

这点应该很好理解,由上面的阐述可以看到,如果每次对SSD的写入都是很小的量,就会产生典型的写入放大。

  • 剩余容量

通常我们使用的SSD都存在预留空间(OP)来用于给SSD的主控芯片来进行一些优化操作。其中预留空间最为核心的两项工作就是垃圾回收损耗均衡,在这里笔者简要介绍一下垃圾回收和损耗均衡。

垃圾回收

SSD中主流的垃圾回收算法与Java之中的标记清除的垃圾回收算法类似:

如上图所示,SSD首先在Block X之中写入A-D的Page页,之后继续写入到H,并且更新了A'-D',所以原先的A-D的page页成为了需要回收的垃圾。所以主控芯片会将可用数据移动到旁边的有空闲的Block Y,同时完整的擦除Block X。当剩余容量越小,垃圾回收越频发,则SSD的写入放大就越为严重。就是为什么许多手机在刚刚买来之后丝滑如顺,但是之后就越用越卡,这是因为容量越来越小了,SSD需要背锅!!(这也是笔者的64G的小米5剩余容量只有4个G了,日常使用卡如狗的部分原因~~)需要频繁进行垃圾回收的场景会导致写入放大的问题更为严重。

损耗均衡

我们知道,SSD的使用寿命等同于Block的擦写次数,目前主流使用的MLC颗粒的编程/擦写次数一般在3000 ~ 5000次左右。如果反复地编程和擦写某个Block,该Block则会先于其他Blcok损坏,导致坏块大量出现。正是因为这样的原因,SSD的主控芯片会尽可能的让每个Block的擦写次数均匀。所以损耗均衡的操作需要移动并没有新数据写入的Block,这样同样也会导致写放大的上升。

2.写放大问题的一些解决思路

了解了SSD的写放大的成因之后,我们可以『对症下药』的尝试给出一些方案来减小写放大问题来对我们线上服务的影响。

  • 批量写
    这几乎是解决磁盘io问题的通用解决方案,同样适合于传统的机械硬盘与SSD。尽量在代码逻辑之中减少随机写的次数,来避免由少量写操作引发的写放大问题,同时可以考虑通过块对齐的方式来进一步减少写入产生的写放大问题。当然这里所谓块对齐的思路在是与程序运行环境紧耦合的,程序的可移植性会大打折扣

  • 预留空间,容量告警
    这也是我们运维线上机器常用的思路,对于SSD的使用量要有一个阀值,超过我们的预设容量时,线上的程序需要给运维和开发人员告警。

  • 写压缩
    写压缩是依赖SSD的主控芯片的,部分SSD主控芯片支持写压缩。也就说接受到操作系统发送要写入20m数据,主控芯片可以通过一些流压缩或块压缩的算法压缩数据,在读取数据时,再重新进行解压。这种方式强依赖硬件,并且新的瓶颈可能会是主控芯片的压缩,解压的速度。

  • TRIM命令
    TRIM是操作系统层级的命令。操作系统利用TRIM命令来标记SSD上某个Page的数据可以回收。一旦某个Page被SSD标记为可以回收,在SSD空闲的时候SSD的主控芯片会将这些被标记的Page数据收集到同一个Block,然后共同擦除。这样每次需要写数据时,就在已经有足够空闲的Page可以写入新的数据。

上述几个思路都是在实践中可以采取的措施,其实TRIM命令需要通过Linux设置开启,这里笔者在这里介绍一下如何在Linux下开启TRIM命令:

  1. 确认Linux的内核是否大于 2.6.28,笔者这里是4.9.0的内核。

    2.调用hdparm -I /dev/sda1 命令确认SSD设备是否支持TRIM。

    3.修改/etc/fstab文件,在挂载选项之中添加discard,重启之后就开启了TRIM

3.小结

到此为止,笔者聊了聊SSD写放大的成因,并且针对SSD写放大的成因,提出了一些解决的思路和方法,希望大家能有所收获,在生产环境之中能够更好的『调教好』SSD~~~

大数据小视角5:探究SSD写放大的成因与解决思路的更多相关文章

  1. 大数据小视角1:从行存储到RCFile

    前段时间一直在忙碌写毕设与项目的事情,很久没有写一些学习心得与工作记录了,开了一个新的坑,希望能继续坚持写作与记录分布式存储相关的知识.为什么叫小视角呢?因为属于随想型的内容,可能一个由小的视角来审视 ...

  2. 大数据小视角4:小议Lambda 与 Kappa 架构,不可变数据的计算探索

    这个系列文章之前因为私事荒废了很久,继续更新--之前与老大谈论架构时,老大和我聊了聊分布式数据处理之中的Lambda结构,之前在<Designing Data-Intensive Applica ...

  3. 大数据小视角2:ORCFile与Parquet,开源圈背后的生意

    上一篇文章聊了聊基于PAX的混合存储结构的RCFile,其实这里笔者还了解一些八卦,RCfile的主力团队都是来自中科院的童鞋在Facebook完成的,算是一个由华人主导的编码项目.但是RCfile仍 ...

  4. 大数据小视角3:CarbonData,来自华为的中国力量

    连续两篇文章都聊了不同的存储格式,这篇我们继续深入来看看在存储格式的演变之上有什么新的"黑科技".华为公司在2016年开源了类parquet的列存格式:CarbonData,并且贡 ...

  5. 大数据小项目之电视收视率企业项目09--hive环境搭建

    Hive是一个数据仓库基础工具在Hadoop中用来处理结构化数据.它架构在Hadoop之上,总归为大数据,并使得查询和分析方便.并提供简单的sql查询功能,可以将sql语句转换为MapReduce任务 ...

  6. 大数据小项目之电视收视率企业项目08--》MapReduce编写之Wordcount

    编程规范 (1)用户编写的程序分成三个部分:Mapper,Reducer,Driver(提交运行mr程序的客户端) (2)Mapper的输入数据是KV对的形式(KV的类型可自定义) (3)Mapper ...

  7. 大数据项目中js中代码和java中代码(解决Tomcat打印日志中文乱码)

    Idea2018中集成Tomcat9导致OutPut乱码找到tomcat的安装目录,打开logging.properties文件,增加一行代码,覆盖默认设置,将日志编码格式修改为GBK.java.ut ...

  8. (第1篇)什么是hadoop大数据?我又为什么要写这篇文章?

    摘要: hadoop是什么?hadoop是如何发展起来的?怎样才能正确安装hadoop环境? 这些天,有很多人咨询我大数据相关的一些信息,觉得大数据再未来会是一个朝阳行业,希望能尽早学会.入行,借这个 ...

  9. Storm 实战:构建大数据实时计算

    Storm 实战:构建大数据实时计算(阿里巴巴集团技术丛书,大数据丛书.大型互联网公司大数据实时处理干货分享!来自淘宝一线技术团队的丰富实践,快速掌握Storm技术精髓!) 阿里巴巴集团数据平台事业部 ...

随机推荐

  1. Eclipse通用设置

    分类 Eclipse分为64位.32位,安装版.免安装版 查看Eclipse版本信息 Help - About Eclipse - Installation Details

  2. mysql 原理~ 乐观锁和悲观锁

    一 简介:今天咱们来聊聊悲观锁和乐观锁 二 悲观锁  1 定义   在关系数据库管理系统里,悲观并发控制(又名“悲观锁”,Pessimistic Concurrency Control,缩写“PCC” ...

  3. 当WebView运行在特权进程时抛出安全异常,Hook方式解决方案(包含对Android 8.0的处理)

    1.问题起源报错语句是:java.lang.UnsupportedOperationException: For security reasons, WebView is not allowed in ...

  4. 深入剖析ThreadLocal实现原理以及内存泄漏问题

    关于ThreadLocalMap<ThreadLocal, Object>弱引用问题: 当线程没有结束,但是ThreadLocal已经被回收,则可能导致线程中存在ThreadLocalMa ...

  5. oracle修改日期格式

    查看默认的日期格式 select * from v$nls_parameters; 更改 alter session | system (范围) set xxxx=“yyyy-mm-dd” ;

  6. jQuery的end() 方法

    定义和用法 end() 方法结束当前链条中的最近的筛选操作,并将匹配元素集还原为之前的状态. 语法 .end() 详细说明 大多数 jQuery 的遍历方法会操作一个 jQuery 对象实例,并生成一 ...

  7. Windows和Mac上NodeJS和Express的安装

    一.安装NodeJS,官网上下载,https://nodejs.org/en/ 直接下一步安装就行了. 打开命令行工具,输入 node -v 则会出现node的版本,则成功了. 下面我们介绍如何安装e ...

  8. python3之requests

    1.requests简介 requests是通过urllib3实现自动发送HTTP/1.1请求,它能轻松的实现cookies,登陆验证,代理设置等操作. Python内置的urllib模块,用于访问网 ...

  9. MR运动静止用户区分

    1.客户端打开菜单[MR]-[MR室内室外判定设置] 设置主小区是室外站且主小区信号比较强时RSRP门限 2.设置"上报数据用户临小区切换次数门限设置"值为15 mysql中t_m ...

  10. oracle 存储过程 clob 字段 调试

    clob 没法直接赋值调试,可以新建一个存储过程,赋值给clob字段,然后调试