我们都听说过RAID,也经常作为SQL DBA、开发人员或构架师在工作中讨论RAID。但是,其实我们很多人都对RAID的原理,等级,以及RAID是如何影响SQL Server性能并不甚了解。
本篇文章就是为了补上这一课。
磁盘构架
今天的磁盘,和70年代45rpm(转/分钟)的唱片机很像(你还能记得吗?),仅仅是一个有着轴(磁道)旋转的媒体(面)并将数据存入称之为扇区的磁盘段。
就像唱片机那样,磁盘驱动器拥有一个摆臂来控制针(在这里可以称之为”磁头”)来访问数据。但对于磁盘来说,并不像唱片机那样只读,而是既可以读又可以写。
为了从特定的扇区读或者写数据,磁盘必须进行旋转然后摆臂移动使得磁头移动到垂直于指定扇区的正上方以访问数据。
这个过程就是基本的输入/输出操作的过程(I/O)。
IOPS
IOPS这个术语也是被经常拿出来装X的,但同样,对这个术语真正理解的人并不多。
很多人都明白IOPS是Input Output Operations per Second的缩写,但是将这个定义转换为实际的概念对于某些人就有点难了。
对IOPS基本的理解是对满足特定输入输出请求的平均时间的一种衡量。
这里重点需要知道这个度量标准是基于读取0字节的文件,这仅仅是为了统计和标准化的目的因为一个磁盘扇区大小并不同。
物理磁盘的限制
磁盘会有一些物理限制会限制磁盘能达到的IOP级别。这个限制是磁道寻址时间(seek time)和旋转延迟(rotational latency)。
磁道寻址时间是为了使得磁头可以移动到所要读的扇区,移动摆臂所花费的平均时间。
旋转延迟是为了使磁头读取盘面特定位置旋转磁盘所话费的时间(通常为毫秒级)。
单位IOP所花的时间公式如下:
单位IOP时间=磁道寻址时间+旋转延迟
所以,通过这个公式我们就可以轻松计算给定磁盘的最大IOPS。
而每秒的IOPS数字也是我们最感兴趣的,公式如下:
1秒/磁道寻址时间+旋转延迟。
我们来看如下例子:
转速 | 15000 |
平均磁道寻址时间 | 2.9ms |
平均旋转延迟 | 1.83ms |
我们可以用公式计算IOPS了:
IOPS = 1/(2.9ms + 1.83ms)
= 1/(4.73ms)
= 1/(0.00473)
= 211 IOPS
我们可以看到,这个磁盘的IOPS为211(并不是很惨)。
假如我们想要节省更多的钱,我们再来看一个磁盘的例子以及和上面磁盘的区别:
转速 | 7200 |
平均磁道寻址时间 | 10ms |
平均旋转延迟 | 2.1ms |
通过公式可以看到这个磁盘的最大IOPS:
IOPS = 1/(10ms + 2.1ms)
= 1/(12.1ms)
= 1/(0.0121)
= 82 IOPS
这个7200转的磁盘的最大IOPS为82。
通过对比可以看到上面两个磁盘的性能上的巨大差异,这也不难理解为什么同样的容量价格会差这么多。
此外,文档显示如果你使用磁盘到其IOPS峰值,会产生请求队列而造成延迟(一个在SQL Server中非常邪恶的词汇,像躲避瘟疫一样躲避它)。
而我看过的大多数文档建议IOP保持在最大IOPS的80%左右。所以我们上面讨论的第一个磁盘的最大IOPS是211如果服务于超过168的IOPS就会开始显出延迟的征兆了。
现在我已经知道了单独一个磁盘可以达到的IOPS数字,那么下一件事就是要满足生产环境下的SQL Server实例需要多少IOPS?
我获取这些数据仅仅通过在生产环境下查看PerfMon工具的physical disk: Disk Transfers/Sec 计数器。
这个数字是:
驱动 | 平均IOPS | 最大IOPS |
数据和索引 | 2313 | 16,164 |
日志 | 81.5 | 1,127 |
TempDB | 141 | 2,838 |
通过上面的数据看到,我们的快速磁盘仅仅能处理168的IOPS,所以结论是一个磁盘无论如何也无法满足上面的IOPS要求。
所以解决这个问题的唯一办法是使用某种机制来调整多个磁盘满足上述需求。
如果我们有100个300GB 15k SAS驱动器,我们不仅获得了30TB的存储量,还获得了16800的IOPS。
如果我们使用前面例子中较慢的磁盘,为了达到16800 IOPS,我们需要205块这样的驱动器,这使得我们需要比使用快速磁盘花更多的钱($20,000 vs $20,500),听上去很讽刺,不是吗?
RAID的必要性
现在,我们需要一堆磁盘来满足我们的速度或是容量需求,所以我们需要某种机制来将工作负载加到多个磁盘,实现这个目的的主要手段就是RAID。
RAID代表"Redundant Array <of> Inexpensive Disks"(译者注:这是最开始的定义,后来行业标准将I改为Independant,难道这是因为Inexpensive这个词妨碍了他们收取更多的钱?),RAID提供了将一堆磁盘连接起来使得逻辑上变为1个的方法。
基于你如何串联你的磁盘,RAID可以提供容错性—当磁盘阵列中有一个磁盘崩溃时数据不会丢失。
此外,因为串联了多个磁盘,我们可以消除单个磁盘的IOPS限制,更多的磁盘意味着更多的IOPS,就是这么简单。
RAID级别
RAID只为了两个目的:1)通过提高IOPS提高性能 2)提供容错。更高的容错性意味着更低的磁盘性能,同样,高性能方案也会降低容错性。
根据容错性和性能的目标配置RAID就是所谓的RAID层级。RAID是对常用的RAID阵列的一种分裂,常见的RAID级别为:RAID0,RAID1,RAID5,RAID1+0,RAID0+1。
根据你对RAID级别的选择,你需要付出所谓的”RAID代价”。某些RAID级别需要重复写入两次数据来保证容错性,但这样会牺牲性能。此外,因为重复写入数据还需要更多的磁盘空间。RAID代价会大大提高你的RAID方案的成本。
为了明白RAID对于你的系统的影响和收益,熟悉常见的RAID级别和它们的实现原理变得非常重要。
RAID 0
第一个,也是最基本的RAID级别是RAID 0.RAID 0强调为了解决IO的限制而将数据写入到磁盘阵列中。如果IO希望写100MB的数据,RAID0会将100MB数据写入到磁盘阵列的每个磁盘中。
这种方式大大减少了每个磁盘的负载,并且减少了旋转延迟(每个磁盘不再需要转和原来一样的圈数就能满足请求)。
虽然RAID0大大提高了IO性能,但没有提供任何容错措施,这意味着如果磁盘阵列中的某一块磁盘崩溃,则整个磁盘阵列中的数据全部丢失。
因为RAID0并没有提供任何容错措施,所以在生产环境中RAID0几乎不被使用。
还有一点值得注意的是,由于RAID0磁盘阵列中的每个磁盘都用于存储数据,所以没有任何磁盘空间的损失,比如使用RAID0,10个300GB的磁盘就会有3TB的可用存储空间,这意味着没有损失磁盘空间的RAID代价。
RAID 1
RAID1也被称为”镜像”,因为其通过一个镜像磁盘来保证容错性。在镜像集中的每个磁盘都会有一个镜像磁盘,RAID 1写入的每一笔数据都会分别在两个磁盘中各写一份。这意味着任何一个磁盘除了问题,另一个磁盘就会顶上。用户的角度来看并不知道出现了磁盘崩溃。
RAID 1需要付出写入时的性能代价。每个写入IOP需要运行两次,但是对于读来说却会提升性能,因为RAID控制器对于大量数据请求会从两个磁盘中读取。
RAID 5
RAID 5也被称为”Striping With Parity)”,这种方式既可以通过磁盘分割(Striping raid0)来提高性能,也可以通过奇偶性(Parity)来提供容错,当一个磁盘崩溃后,奇偶数据可以通过计算重建丢失的数据。
虽然奇偶性是实现容错的一种不错的方式。但是从磁盘写入来说代价高昂。也就是说对于每一个IOP写请求,RAID5需要4个IOPS。
为什么需要这么高写入代价的过程如下:
读取原始数据(1 iop)
读取当前奇偶数据(1 iop)
比较当前数据和新写入请求
基于数据差异计算新的奇偶值
写入新数据(1 iop)
写入新的奇偶值(1 iop)
RAID 1+0
RAID 1+0 和其名字所示那样,融合了RAID 0(磁盘分割)和RAID1(镜像)。这种方式也被称为:分割镜像。
RAID 1+0 由于将数据分割到多个磁盘中使得并且不像RAID5那样有奇偶效验码,所以写入速度非常快。
但写入速度还是会有影响因为需要重复写入镜像盘,但仍然,写入速度还是非常的快。
而对于RAID 1+0 存储的代价等同于RAID1 (镜像),在RAID1+0中只有一半的磁盘空间可以用于存储数据。
RAID 0+1
RAID 0+1 和RAID1 +0 是很像,它们都是通过磁盘分割和镜像来实现目的。他们的区别更加学术化,这里我们假设他们一样。
RAID 0+1和 RAID 1+0所付出的代价是一样的。
其它RAID级别(2,3,4,6,DP等)
还有一些其它不常见的非标准RAID层级,RAID 2,3,4,6和RAID DP都和RAID5类似,他们都是通过分割和某种奇偶校验来提供性能上和容错。这些类似RAID 5的RAID层级的区别仅仅是它们如何写入奇偶数据。它们之中有些是通过保留一个磁盘来存储奇偶数据,还有一些是将奇偶数据分布到多个磁盘当中等等。如果需要,你可以去做这些研究,但对于我来说,我都称它们为”RAID 5”
还有一个值得讨论的非标准的RAID级别是RAID DP,DP的是”Dual Parity”的缩写,这和RAID 5很像但其将奇偶数据写入两次,这对于写入来说代价高昂,写入代价被提高到了6(每一次IO写请求需要6 IOPS)
RAID 比较
选择合适的RAID层级并不容易,需要考虑多方面因素:成本,性能和容量。
下表总结了每个标准RAID层级的好处和坏处。
RAID Level | Fault Tolerance | Read Performance | Write Performance | RAID Write Penalty | Cost |
0 | None | Good | Excellent | 1 | Excellent |
1 | Good | Good | Good | 2 | Fair |
5 | Fair | Good | Poor | 4 | Good |
1+0 | Excellent | Excellent | Excellent | 2 | Poor |
DP | Good | Good | Terrible | 6 | Good |
SQL存储推荐
SQL Server文件 | RAID级别 |
操作系统和SQL二进制文件 | RAID 1 |
数据和索引 | RAID 1+0 (如果预算不允许可以使用RAID 5) |
日志 | RAID 1+0 |
TempDB | RAID 1+0 |
备份 | RAID 5 |
其它考虑因素
当需要计划你的IO子系统和SQL文件分布以及RAID层级时,你需要多考虑其它因素。
RAID控制器
RAID可以通过2种方式实现:软件实现和硬件实现。
在软件RAID配置中,操作系统管理RAID级别以及多磁盘之间的IO负载。
在硬件RAID配置中,物理上会有一个硬件作为RAID控制器。
通常来说,硬盘RAID解决方案会更健壮,灵活和强大。根据你对RAID控制器的预算,你能获得对应预算的配置选项。
比如,某些RAID控制器仅仅提供一个RAID层级(比如RAID5),一些更昂贵的RAID控制其提供了缓存功能。缓存可以用于缓存读取操作,写入操作以及它们两者。更好的RAID控制器甚至提供了对于读取和写入分配缓存的百分比选项。
缓存对于SQL Server来说非常重要,尤其是对于写来说。无论是何种RAID级别,都没有读取性能上的代价,所有的RAID层级都提高了读取数据的速度。而写入才是RAID的代价,你可以通过RAID缓存来缓存所有的写入操作,这极大的提高了写入性能。通常来说,有缓存的RAID控制器都带有电池,这使得即使断电,缓存的数据也不会丢失。
记住,SQL Server本身非常善于缓存读取,所以使用昂贵的RAID控制器中的缓存来缓存读取并没有什么意义。
虚拟化
还有一个值得考虑的因素是虚拟化,无论你喜欢与否,我们已经步入了虚拟化的世界。在VMWare环境下部署生产环境下的SQL Server实例变得越来越普遍。
虚拟化也影响RAID和IO方面,根据你使用的虚拟化产品,当你选择RAID级别时就需要考虑更多的因素,比如,VM是如何和存储系统交互的。
总结
很明显,我们还有一些信息没有讨论到,RAID对于SQL Server性能和容错的重要性不言而喻。
我希望本篇文章能够帮你理解RAID是如何影响你的SQL Server的性能。作为一个DBA或是数据库构架师来说,你必须明白当前RAID配置有着怎样的性能和容错性。