实际上MySQL数据库就是个软件,大家都知道,他其实就是用编程语言写的一套数据库管理软件而已,底层就是磁盘 来存储数据,基于内存来提升数据读写性能,然后设计了复杂的数据模型,帮助我们高校的存储和管理数据。 所以MySQL数据库软件都是安装在一台linux服务器上的,然后启动MySQL的进程,就是启动了一个MySQL数据库 MySQL运行过程中,他需要使用CPU、内存、磁盘和网卡这些硬件,但是不能直接使用,都是通过调用操作系统提供 的接口,依托于操作系统来使用和运行的,然后linux操作系统负责操作底层的硬件。

    所以之前我们已经把MySQL层面的磁盘读写操作讲完了,同时也把Linux操作系统层面的存储系统的原理讲完了,上 一讲不就讲到Linux操作系统的存储系统把IO请求交给机器上的存储硬件了么? 那么今天我们接着来讲讲存储硬件这块的东西。 一般来说,很多数据库部署在机器上的时候,存储都是搭建的RAID存储架构,其实这个RAID很多人以为非常的深奥, 确实这个概念比较难以理解,而且说深了其实里面的技术含量很高,但是如果简单说一下,也是每个人都能理解的。 说白了,RAID就是一个磁盘冗余阵列,什么意思呢?

    假设我们的服务器里的磁盘就一块,那万一 一块磁盘的容量不够怎么办?此时是不是就可以再搞几块磁盘出来放在服 务器里 现在多搞了几块磁盘,机器里有很多块磁盘了,不好管理啊,怎么在多块磁盘上存放数据呢? 所以就是针对这个问题,在存储层面往往会在机器里搞多块磁盘,然后引入RAID这个技术,大致理解为用来管理机器 里的多块磁盘的一种磁盘阵列技术! 有了他以后,你在往磁盘里读写数据的时候,他会告诉你应该在哪块磁盘上读写数据,
    image.png

    有了RAID这种多磁盘阵列技术之后,我们是不是就可以在一台服务器里加多块磁盘,扩大我们的磁盘存储空间了? 当我们往磁盘里写数据的时候,通过RAID技术可以帮助我们选择一块磁盘写入,在读取数据的时候,我们也知道从哪 块磁盘去读取。 除此之外,RAID技术很重要的一个作用,就是他还可以实现数据冗余机制 所谓的数据冗余机制,就是如果你现在写入了一批数据在RAID中的一块磁盘上,然后这块磁盘现在坏了,无法读取 了,那么岂不是你就丢失了一波数据?如下图所示
    image.png
    所以其实有的RAID磁盘冗余阵列技术里,是可以把你写入的同样一份数据,在两块磁盘上都写入的,这样可以让两块 磁盘上的数据一样,作为冗余备份,然后当你一块磁盘坏掉的时候,可以从另外一块磁盘读取冗余数据出来,这一切 都是RAID技术自动帮你管理的,不需要你操心

    所以RAID技术实际上就是管理多块磁盘的一种磁盘阵列技术,他有软件层面的东西,也有硬件层买的东西,比如有 RAID卡这种硬件设备。具体来说,RAID还可以分成不同的技术方案,比如RAID 0、RAID 1、RAID 0+1、RAID2,等等,一直到RAID 10, 很多种不同的多磁盘管理技术方案。 大家如果有兴趣的,可以自行去搜索对应的资料学习里面的技术细节,但是对于我们来说,这篇文章点到为止 大家只要了解一下RAID这种多磁盘冗余阵列技术的基本思想就可以了,我们毕竟不是专门讲解存储这块的。

    服务器使用多块磁盘组成的RAID阵列的时候,一般会有一个RAID卡,这个RAID卡是带有一个缓存的,这个缓存不是 直接用我们的服务器的主内存的那种模式,他是一种跟内存类似的SDRAM,当然,你大致就认为他也是基于内存来存 储的吧! 然后我们可以把RAID的缓存模式设置为write back,这样的话,所有写入到磁盘阵列的数据,先会缓存在RAID卡的缓 存里,后续慢慢再写入到磁盘阵列里去,这种写缓冲机制,可以大幅度提升我们的数据库磁盘写的性能。

    我们看下图,他说的就是这个RAID卡的缓存机制。
    image.png

    那么现在有一个问题来了,假设突然断电了,或者是服务器自己故障关闭了,那么是不是这个RAID卡的缓存里的数据 会突然丢失?那你MySQL写入磁盘的数据不就没了吗?

    所以正是因为如此,为了解决这个问题,RAID卡一般都配置有自己独立的锂电池或者是电容,如果服务器突然掉电 了,无法接通电源了,RAID卡自己是基于锂电池来供电运行的,然后他会赶紧把缓存里的数据写入到阵列中的磁盘上
    image.png

    但是锂电池是存在性能衰减问题的,所以一般来说锂电池都是要配置定时充放电的,也就是说每隔30天~90天(不同 的锂电池厂商是不一样的),就会自动对锂电池充放电一次,这可以延长锂电池的寿命和校准电池容量。 如果你要是不这么做的话,那么可能锂电池用着用着就会发现容量不够了,可能容纳的电量在你服务器掉电之后,都 没法一次性把缓存里的数据写回磁盘上去,那就会导致数据丢失了! 所以在锂电池充放电的过程中,RAID的缓存级别会从write back变成write through,我们通过RAID写数据的时候, IO就直接写磁盘了,如果写内存的话,性能也就是0.1ms这个级别,但是直接写磁盘,就性能退化10倍到毫秒级了! 所以说,对于那些在生产环境的数据库部署使用了RAID多磁盘阵列存储技术的公司来说,通常都会开启RAID卡的缓存 机制,但是此时就一定要注意这个RAID的锂电池自动充放电的问题,因为只要你用了RAID缓存机制,那么锂电池就必 然会定时进行充放电去延长寿命,保证服务器掉电的时候可以把缓存数据写回磁盘,数据不会丢失。 所以这个时候一旦RAID锂电池自动充放电,往往会导致你的数据库服务器的RAID存储定期的性能出现几十倍的抖动, 间接导致你的数据库每隔一段时间就会出现性能几十倍的抖动!

    所以对于这样的一个使用了RAID 10架构的服务器,他必然内部是有一个锂电池的,然后这个锂电池的厂商设定的默 认是30天进行一次充放电,每次锂电池充放电就会导致RAID写入时不经过缓存,性能会急剧下降,所以我们发现线上 数据库每隔30天就会有一次剧烈性能抖动,数据库性能下降了10倍。 当时为了排查这个问题,我们使用linux命令查看了RAID硬件设备的日志,这个具体什么命令不说了,因为你用不同的 厂商的RAID设备,这个命令实际上是不一样的,发现RAID就是每隔30天有一次充放电的日志,所以就是由于这个定 期的充放电导致了线上数据库的性能定期抖动! 那么后续如何解决这个问题呢?对于RAID锂电池充放电问题导致的存储性能抖动,一般有三种解决方案:
    给RAID卡把锂电池换成电容,电容是不用频繁充放电的,不会导致充放电的性能抖动,还有就是电容可以支持透明充 放电,就是自动检查电量,自动进行充电,不会说在充放电的时候让写IO直接走磁盘,但是更换电容很麻烦,而且电 容比较容易老化,这个其实一般不常用

    手动充放电,这个比较常用,包括一些大家知道的顶尖互联网大厂的数据库服务器的RAID就是用了这个方案避免性能抖动,就是关闭 RAID自动充放电,然后写一个脚本,脚本每隔一段时间自动在晚上凌晨的业务低峰时期,脚本手动触发充放电,这样可以避免业务高 峰期的时候RAID自动充放电引起性能抖动

    充放电的时候不要关闭write back,就是设置一下,锂电池充放电的时候不要把缓存级别从write back修改为write through,这个也是可以做到的,可以和第二个策略配合起来使用