You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
14 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 17 | 存储篇:如何根据性能优缺点选择最合适的存储系统?
你好,我是庄振运。
前面两讲我们讨论了CPU和内存今天我们讨论第三个重要的主题存储系统。现在是大数据时代这些数据终归要保存到各种存储系统里面以供读写和分析因此讨论存储系统的性能问题就很有必要了。
狭义上的存储往往是硬件比如磁盘、磁带还有固态硬盘。而广义上的存储系统除了指硬件的硬盘还包括基于网络的存储系统比如SANStorage Area Network, 存储区域网络和NAS存储Network Attached Storage网络接入存储
各种存储系统各有优缺点,尤其是性能和成本,所以对不同的需求,我们要选择最合适的存储系统。
我们首先讲存储系统最重要的三大性能指标IOPS、访问延迟和带宽然后讲传统硬盘HDDHard Disk Drive的性能。因为传统硬盘的特性相对简单直白毕竟业界已经用了几十年了。这之后再讲固态硬盘的性能固态硬盘就是SSD也叫Flash。相对于传统硬盘SSD的内部工作原理很不一样这也就导致它们的性能特性大相径庭。 最后,我们再延伸到基于网络的存储系统,并且介绍几个常用的和存储相关的工具。
## 存储系统的三大性能指标
一个存储系统的性能最主要的是三个:**IOPS**、**访问延迟**、**吞吐率/带宽**。这三个指标其实是互相关联和影响的,但是我们一般还是分开来衡量。
**IOPS**Input/Output Per Second即每秒钟能处理的读写请求数量这是衡量存储性能的主要指标之一。每个IO的请求都有自己的特性比如读还是写是顺序读写还是随机读写IO的大小是多少等。
什么是顺序读写呢就是访问存储设备中相邻位置的数据随机读写呢则是访问存储设备中非相邻位置的数据。对随机读写进行性能衡量时一般假定IO大小是4KB。
既然IO有这些特点所以我们讨论存储系统IOPS性能的时候经常需要更加具体的描述。比如顺序读IOPS、随机写IOPS等。
IOPS的数值会随这样的参数不同而有很大的不同这些参数的变化包括读取和写入的比例、其中顺序读写及随机读写的比例、读写大小、线程数量及读写队列深度等。此外系统配置等因素也会影响IOPS的结果例如操作系统的设置、存储设备的驱动程序特点、操作系统后台运行的作业等。
**访问延迟**Access Time和**响应时间**Response Time指的是从发起IO请求到存储系统把IO处理完成的时间间隔常以毫秒ms或者微妙us为单位。对这一性能指标我们通常会考虑它的平均值和高位百分数比如P99、P95。
**吞吐率**Throughput或者带宽Bandwidth衡量的是存储系统的实际数据传输速率通常以MB/s或GB/s为单位。一般来讲IOPS与吞吐率是紧密相关的它们之间的关系是吞吐率等于IOPS和IO大小的乘积。
这个也很容易理解比如对一个硬盘的读写IO是1MB硬盘的IOPS是100那么硬盘总的吞吐率就是100MB/s。需要强调的是这里IO的具体特性很重要比如是顺序还是随机IO大小等。
还有一点要注意,有些存储系统会因为其**IO队列深度增加**而获得更好的IO性能比如吞吐率会升高平均访问延迟会降低。
这是为什么呢这是因为存储系统的IO队列处理机制可以对IO进行重新排序从而获得好的性能。比如它可以合并几个相邻的IO把随机IO重新排序为顺序IO等。
## HDD传统硬盘的性能
我们先从你熟知的传统硬盘开始讨论。对于传统硬盘,我们应该比较熟悉它的内部是如何操作的。
简单来说当应用程序发出硬盘IO请求后这个请求就会进入硬盘的IO队列。如果前面有其他IO那么这个请求可能需要排队等待。当轮到这个IO来存取数据时磁头需要机械运动到数据存放的位置这就需要磁头寻址到相应的磁道并旋转到相应的扇区然后才是数据的传输。所以讨论硬盘IO的性能时需要充分考虑这一点。
我们有时候需要把**硬盘响应时间**和**硬盘访问时间**分开对待。它们之间的关系是硬盘响应时间除了包括访问时间外还包括IO排队的延迟如下图所示。
![](https://static001.geekbang.org/resource/image/03/19/030b5f050f8230d70654dd1df78c3119.png)
我们如果拿起一块硬盘仔细看看,硬盘上面往往会标注后面三个参数,分别是平均寻址时间、盘片旋转速度,以及数据传输速度,这三个参数就可以提供给我们计算上述三个步骤的时间。
平均寻址时间一般是几个毫秒。平均旋转时间可以从硬盘转动速度RPM来算出。因为每个IO请求平均下来需要转半圈那么如果硬盘磁头每分钟转一万圈10K RPM转半圈就需要3毫秒。
要注意的是硬盘上面标注的数据传输速度参数往往是最大值实际的数据传输时间要取决于IO的大小。
对于一块普通硬盘而言我们前面讲常用的性能数字时也提过随机IO读写延迟就是8毫秒左右IO带宽大约每秒100MB而随机IOPS一般是100左右。
硬盘的技术也在发展现代的硬盘也有很多变种。比如采用了多磁头技术或者几块硬盘组成磁盘阵列这样的整体IO性能也会相应地提升。
## SSD固态硬盘的技术背景
讲完了传统硬盘我们接着看看固态硬盘——SSD。SSD的内部工作方式和HDD大相径庭我们来了解一下。
### 单元Cell、页面Page、块Block
当今的主流SSD是基于NAND的它是将数字位存储在单元中。每个SSD单元可以存储一位SLCSingle Level Cell单级单元、两位MLC多级单元、三位TLC三级单元甚至四位QLC
SSD的特点是对SSD单元的每次擦除都会降低单元的寿命因此每一个单元只能承受一定数量的擦除。所以不同的SSD就有这几方面的考虑和平衡。单元存储的位数越多制造成本就越少SSD的容量也就越大。但是耐久性擦除次数也会降低。所以高端的SSD比如企业级的基本都是基于SLC的。
一个页面包括很多单元典型的页面大小是4KB。页面也是读写的最小存储单位。我们知道HDD可以直接对任何字节重写和覆盖但是对SSD而言不能直接进行上述的“覆盖”操作。SSD的一个页面里面的所有单元一旦写入内容后就不能进行重写必须和其它相邻页面一起被整体擦除、重置。
在SSD内部多个页面会组合成**块**。一个块的典型大小为512KB或1MB也就是大约128或256页。块是擦除的基本单位每次擦除都是整个块内的所有页面都被重置。
### I/O和垃圾回收Garbage Collection
我们总结一下对SSD的IO操作一共有三种类型**读取**、**写入**和**擦除**。读取和写入是以页为单位的,也就是说最少也要读取写入一个页面。
IO写入的延迟具体取决于磁盘的历史状态因为如果SSD已经存储了许多数据那么对页的写入有时需要移动已有的数据这种情况下写入延迟就比较大。但多数情况下读写延迟都很低一般在微秒级别远远低于HDD。
擦除是以块为单位。擦除速度相对很慢通常为几毫秒。所以对同步的IO请求发出IO的应用程序可能会因为块的擦除而经历很大的写入延迟。为了尽量地减少这样的场景发生一块SSD最好保持一定数量的空闲块这样可以保证SSD的写入速度足够快。
SSD内部有垃圾回收GC机制它的目的就在于此就是不断回收不用的块进行擦除从而产生新的空闲块来备用。这样可以确保以后的页写入能快速分配到一个全新的页。
![](https://static001.geekbang.org/resource/image/b3/6e/b3e76cd89e5471b21900c489f839396e.png)
### 写入放大Write Amplification, or WA
这是SSD相对于HDD的一个缺点即实际写入SSD的物理数据量有可能是应用层写入数据量的多倍。
这是因为一方面页级别的写入需要移动已有的数据来腾空页面来写入。另一方面GC的操作,也会移动用户数据来进行块级别的擦除。
所以对SSD真正的写操作的数据肯定比实际写的数据量大这就是写入放大。因为一块SSD只能进行有限的擦除次数也称为编程/擦除P/E周期所以写入放大效用会缩短SSD的寿命。
### 耗损平衡Wear Leveling
对每一个块而言一旦擦除造成的损耗达到最大数量该块就会“死亡”再也不能存储数据了。对于SLC类型的块P/E周期的典型数目是十万次对于MLC块P/E周期的数目是一万而对于TLC块则可能是几千。为了确保整块SSD的容量、性能和可靠性SSD内部需要对整个SSD的各块做平衡尽量在擦除次数上保持类似。
SSD控制器具有这样一种机制也叫“耗损平衡”来实现这一目标。在损耗平衡操作时数据在各个块之间移动以实现均衡的损耗。但是这种机制也有害处就是会对前面讲的写入放大推波助澜。
## SSD的性能和应用程序的设计
性能方面SSD的IO性能相对于HDD来说IOPS和访问延迟提升了上千倍吞吐率也是提高了几十倍。但是SSD的缺点也很明显。主要有三个缺点
1. 贵;
2. 容量小;
3. 易损耗。
好消息是,随着技术的发展,这三个缺点近几年在弱化。
如今越来越多的应用程序采用SSD来减轻I/O性能瓶颈。许多测试和实践的结果都表明与HDD相比采用SSD带来了极大的应用程序性能提升。
但是我想强调的一点是在大多数采用SSD的部署方案中SSD仅被视为一种“更快的HDD”并没有真正发挥SSD的潜力。
我为什么这么说呢因为尽管使用SSD作为存储时应用程序可以获得更好的性能但是这些收益主要归因于**SSD提供的更高的IOPS和带宽**。
但是SSD除了提供这些之外它还有其它特点比如易损耗以及其独特的内部机制。如果应用程序的设计能充分考虑SSD的内部机制设计出对SSD友好的应用程序就可以更大程度地优化SSD从而进一步提高应用程序性能也可以延长SSD的寿命并降低运营成本。关于这方面我后面会有一讲专门讨论。
## 基于网络的存储系统
我们前面讨论了存储硬件,这些存储硬件可以直接安装在服务器上,构成单机系统。和单机系统和场景相对应,也有很多非单机使用的场景。
在非单机使用的场景里这些存储硬件也被包装在各种基于网络的存储系统里。这样的存储系统也有很多种比如DAS、NAS和SAN。
DASDirected Attached Storage是直连式存储。这是以服务器为中心的存储系统存储设备直接通过I/O总线连在服务器主机上。这种存储一般运行SATA或者SAS等协议可以让网络的客户端直接使用。
NASNetwork Attached Storage是网络接入存储。在NAS存储结构中存储系统不再通过I/O总线只属于某个特定的服务器而是通过网络接口直接与网络相连。NAS提供的是文件服务器的功能比如NFS和CIFS供客户通过网络访问。
SANStorage Area Network是存储区域网络。SAN是一种以网络为中心的存储系统通常有高性能专用网络比如光纤来支持运行iSCSI等协议。
## 工具
最后,我们看看常用的存储系统性能监测和测试工具。存储系统的测试和监控命令工具非常多,下面简单介绍几个。
Linux系统上可以采用fio工具进行各种组合的IO测试。这些组合包括读写比例、随机还是顺序读写、IO大小等等。
IOMeter也是不错的测试磁盘性能的工具比如可以测试I/O的传输速度和平均的I/O响应时间。
IOZone是一个文件系统基准测试工具可以测试不同的操作系统中文件系统的读写性能。
Bonnie++是基于Linux平台的开源磁盘IO测试的工具可以用它来测试磁盘和文件系统的I/O性能。
hdparm可以用来作跳过文件系统的纯硬件操作测试。
iostat这个工具可以查看进程发出IO请求的数量、系统处理IO请求的耗时、磁盘的利用率等也可以分析进程与操作系统的交互过程中IO方面是否存在瓶颈。
## 总结
![](https://static001.geekbang.org/resource/image/a9/b3/a946f03c8cee8ac2a5ed4e0b875716b3.png)
存储系统,顾名思义,是用来存放我们各种程序和服务的数据。随着现代互联网服务的大数据化,几乎所有的业务都离不开存储系统的支持。
各种存储系统的基础是传统硬盘或者固态硬盘,这两种硬盘在成本、性能、大小方面各有千秋。我想起了宋代有首诗叫《雪梅》,里面比较了白雪和梅花的优缺点:
“梅须逊雪三分白,雪却输梅一段香。”
这句诗用来形容传统硬盘和固态硬盘的关系还挺合适的。
在实际使用中我们要注意它们的性能优缺点从而适当来作取舍。比如如果系统对IOPS或者延迟要求很高恐怕只有SSD才能满足要求。反之如果数据量极大需要降低成本那么只能选择磁盘或者磁带系统了。
## 思考题
你对SSD这种新型存储了解多少你公司里面有没有系统使用SSD它们碰到的性能问题有哪几个方面运维和开发人员是怎么一起解决这些问题的
欢迎你在留言区分享自己的思考,与我和其他同学一起讨论,也欢迎你把文章分享给自己的朋友。