• 【Linux】系统 之 RAID


    本人从事DBA相关的工作,最近遇到了IO抖动伴随shread running抖动的情况,主机宕机重启后备库及下游解析binlog出现损坏的案例,向一些有经验的同事咨询学习,其中最大的嫌疑是:raid卡问题,今天带各位一起走进raid卡的世界

    1. RAID卡是什么,为什么会用到RAID卡
    2. RAID卡的缓存与磁盘自带的缓存的关系
    3. 使用RAID卡应该注意的事项

    了解MySQL的你,一定不会对InnoDB的事务日志陌生,InnoDB使用日志来减少提交事务时的开销,因为日志中记录了事务,就无须在每个事务提交时把缓冲池的脏块刷新(flush)到磁盘中,并且事务修改的数据通常会映射到表空间的随机位置,所以刷新这些变更需要很多的随机I/O,InnoDB用日志把随机I/O变成顺序I/O。一旦日志安全写到磁盘,事务就持久化了,即使变更没写到数据文件。如果一些糟糕的事情发生了(例如断电了),InnoDB可以重放日志并且恢复已经提交的事务。

    日志缓冲必须被刷新到持久化存储,以确保提交的事务完全被持久化了,在这里不得不提到一个控制日志刷新的频繁程度的变量:innodb_flush_log_at_trx_commit,其配置对于 MySQL 的性能有很大影响。

    set @@global.innodb_flush_log_at_trx_commit=xxx;

    1. 当取值为 0 时,log buffer 会每秒写入到日志文件并刷写(flush)到磁盘。但每次事务提交不会有任何影响,也就是 log buffer 的刷写操作和事务提交操作没有关系。在这种情况下,MySQL性能最好,但如果 mysqld 进程崩溃,通常会导致[最后 1s]的日志丢失。
    2. 当取值为 1 时,每次事务提交时,log buffer 会被写入到日志文件并刷写到磁盘。这也是默认值。这是最安全的配置,但由于每次事务都需要进行磁盘I/O,所以也最慢。
    3. 当取值为 2 时,每次事务提交会写入日志文件,但并不会立即刷写到磁盘,日志文件会每秒刷写一次到磁盘。这时如果 mysqld 进程崩溃,由于日志已经写入到系统缓存,所以并不会丢失数据;在操作系统崩溃的情况下,通常会导致最后 1s 的日志丢失。
    

    如图:

    上面说到的「最后 1s」并不是绝对的,有的时候会丢失更多数据。有时候由于调度的问题,每秒刷写(once-per-second flushing)并不能保证 100% 执行。对于一些数据一致性和完整性要求不高的应用,配置为 2 就足够了;如果为了最高性能,可以设置为 0。有些应用,如支付服务,对一致性和完整性要求很高,所以即使最慢,也最好设置为 1.

    以上的所有的阐述都讲了redo log相关的策略,是InnoDB特有的,同样重要的参数还有sync_binlog 控制MySQL 的二进制日志(binary log)同步到磁盘的频率。

    set @@global.sync_binlog=xxx;

    1. 如果 autocommit 开启,每个语句都写一次 binary log,否则每次事务写一次。
    2. 默认值是 0,不主动同步,而依赖操作系统本身不定期把文件内容 flush 到磁盘。
    3. 设为 n 时,MySQL server 在binary log 每写入 n 次后,刷写到磁盘。
    设为 1 最安全,在每个语句或事务后同步一次 binary log,即使在崩溃时也最多丢失一个语句或事务的日志,但因此也最慢。大多数情况下,对数据的一致性并没有很严格的要求,所以并不会把 sync_binlog 配置成 1. 为了追求高并发,提升性能,可以设置为 100 或直接用 0. 而和 innodb_flush_log_at_trx_commit 一样,对于支付服务这样的应用,还是比较推荐 sync_binlog = 1.
    

    讲到这个似乎有点偏题,但是又不得不向各位交代。

    了解清楚“把日志缓冲写到日志文件”和“把日志刷新到持久化存储”之间的不同是很重要的,在大部分的操作系统中,把缓冲写到日志只是简单的把数据从InnoDB的内存缓冲转移到了操作系统的缓冲,也是在内存中,并没有真正的持久化,与此相反,把支持刷新到持久化存储意味着InnoDB请求操作系统把数据刷出缓存,并确认确实写入到磁盘了。这是一个阻塞I/O的调用,知道数据被完全写入才完成,因为写数据到磁盘是相当慢的操作,作为数据库,尤其是高并发,对性能要求比较高,一定是接受不了的,换个角度看,对于写的实时性并不如读的实时性那么高,只要保证写进去就好。

    高性能事务处理需要的最佳配置是把innodb_flush_log_at_trx_commit设置为1且把日志文件放到一个有电池保护的写缓存的RAID卷中,终于看到了我们今天要讲的内容!!!。这兼顾了安全和速度。

    我们看到了在持久化设备磁盘前面还有一层RAID卷,日志文件写入到RAID就默认是写道磁盘了,这里包括 redo log 和 binary log 一旦RAID有问题,I/O性能会收到影响,并且数据都有可能丢失。

    接下来我们正式进入正题

    RAID卡是什么,为什么会用到RAID卡

    为了简化问题,各位可以把RAID当做是磁盘CACHE,其主要的两大功能:预读和回写

    1. 预读
    CACHE预读提高了计算机系统中的硬盘读的功能,尤其是在读取含有大量文件碎片的文件时。具有良好预读功能的RAID卡能在看起来很随机的读访问中,识别出读取磁盘的规律, 通过这个规律提前将系统要读取的数据放在CACHE中。
    预读的两种方式:
    Read Ahead 
    由于硬盘数据经常是以一族连续的硬盘扇区组织起来的,所以有时侯如把系统所请求的扇区随后的一个扇区里的数据 同时读进来是有价值的。对于数据文件的读取有利,特别是系统CPU的性能低时。
    Pre-Fetch
    当RAID卡发现系统要读的是先前已经读过的数据时,在 这一次,便将这一个数据块的数据写到CACHE里。对于程序文件的读取有利 。
    
    2. 回写
    回写是通过暂时将数据存在CACHE里,从而推迟将数据写到慢设备(如硬盘、磁带机)的一种工作方式。数据将在随后的时间,硬盘闲置的时候写到硬盘中。写的时候也是统一将CACHE内的尚未写出的数据按照数据块的在硬盘中的BLOCK序号写入,这样可以提高写的效率。 
    回写需要加电池给CACHE供电,以免数据在写到硬盘之前系统断电导致硬盘数据丢失。 
    

    增加CACHE大小对于预读来说,为系统提供了更多的来自CACHE的可供读取的记录。 对于回写来说,允许控制卡保存更多的记录留待后期写磁盘。特别是对于电梯式回写,使得连续的回写段之间有更近的间隔,降低硬盘写操作的平均访时间并提高了吞吐率。

    写策略
    1. 通写
    所有数据在以命令完成状态返回到计算机之前,直接写到硬盘。
    2.回写
    可大幅度提高性能。但回写具有一定的数据危险性。在突然断电的情况下,会丢失存于Cache尚未写入硬盘的数据。
    

    RAID卡工作在写策略为THROUGH时,缓存大小对RAID卡的性能影响很小,只有当写策略改为BACK时,缓存的作用才会发挥出来。

    RAID卡的缓存与磁盘自带的缓存的关系

    RAID卡是否有(启用)缓存对“随机读写”性能有巨大的影响。中高端的RAID卡都有缓存(价格也高)。 那么RAID卡的缓存与磁盘自带的缓存是如何设置的?

    戴尔服务器的perc H710 RAID卡有512M缓存,并带电池。
    建立阵列的时候(raid5),关于RAID卡缓存的默认选项是:
    读取策略:自适应 
    写策略:回写 
    磁盘高速缓存策略:禁用 
    
    属性解释:
    读取策略:一般要启用,采用预读取策略,可提高“随机读取”性能。第二次读取相同数据时可以命中缓存。
    写策略:
    一般要启用"回写",操作的是RAID卡上的缓存。
    写入数据时先写入到缓存就算写入成功了,然后RAID卡控制器再把多个写IO合并为一个写IO一次性写入磁盘,提高“随机写入”的性能。
    因为RAID卡带电池,机房停电时,电池可给缓存供电72小时。缓存中的数据不会丢失。
    另外,如果没有给缓存接电池,默认“写缓存”是不被启用的(除非强行设定为“没有电池也启用写缓存”)。
    
    磁盘高速缓存策略: 
    操作的是磁盘自带的高速缓存。 做RAID时,一般要禁用,防止机房停电时磁盘自带缓存中的数据丢失。磁盘可不带电池。
    RAID卡控制器可控制磁盘自带的缓存是否启用。
    家用台试机(未使用RAID卡)在windows操作系统中有选项可以控制磁盘自带的缓存是否启用(默认启用)。
    

    使用RAID卡应该注意的事项

    影响RAID卡性能的因素很多,其中可调因素主要有RAID卡缓存(CACHE)大小、写策略(WRITE POLICY)、读策略(READ POLICY)、条带的大小(STRIPE SIZE)。

    • RAID策略
    1. 开启 Write Back,提高写效率
    2. 开启 Bad BBU Write Back
    默认情况下,如果 Raid 卡电池坏掉,Raid 卡会自动将 Write Back 切换到 Write Through,这个时候 I/O 就会变慢
    开启 Bad BBU Write Back 的情况下,如果电池坏掉,那么 I/O 依然得到保障,但是带来了丢失数据的风险。假如此时机器断电,而 Cache 中的数据没有电池(BBU)的保护,数据就丢失了。
    相比于机器断电,Raid 卡电池充放电会更常见,因此开启 Bad BBU Write Back 保证 I/O 速度。
    3. 关闭读操作使用 Cache
    因为 Raid 卡 Cache 容量有限,为了保证写 Cache 的使用,因此关闭读 Cache
    4.关闭磁盘本身 Cache
    因为使用 Raid 卡 Cache,因此关闭磁盘 Cache
    5.开启 Adaptive ReadAhead
    ReadAhead 是预读,而预读仅仅对顺序磁盘 I/O 有性能提升,因此将其关闭。
    Adaptive ReadAhead 是自适应读,自动决定是否预读
    按照以上描述设置后,MySQL服务器的 Current Cache Policy 理应如下:
    
    Adapter 0-VD 1(target id: 1): Cache Policy:WriteBack, ReadAdaptive, Direct, Write Cache OK if bad BBU
    
    从左至右逗号隔开的次,分别对应上文中的 1,5,3,2 的设置结果
    
    • 充放电

    DELL服务器的Riad卡都有可充电池的特性,这块可充电电池,在不使用时,也会有微弱的放电现象,当它的电量放电到低到一定程度时,Raid卡控制器就会对电池进行一次“放电”,将剩余的电量放掉,然后再进行一次“充电”。这其实是一种对“电池”保护机制,以及对Raid阵列卡可用性提供保障的机制。

    但是问题就出在这个放电、充电的过程上:

    默认情况下,当RAID卡的电池的电量低于某阈值时,RAID卡固化程序认为此时的电池是不可用的,为了保证数据的安全,会禁用RAID的“缓存”,这种默认的机制本来是合情合理的,没有什么可“质疑”的。问题是,当RAID的缓存被禁用之后,RAID的I/O能力会大幅度下降。对于高I/O的应用来说,这种下降,有可能是致命的,可能会导致系统I/O阻塞,raid放电时(一秒以内),cache会禁写,cache策略由WB-》WT转化,会带来io抖动,目前无解。我的猜测:为了保证cache数据不丢的风险,并没有使用机器供电。构架不良的系统,有可能会被这个“故障点”(正在充放电的设备上的应用)拖死,简直太要命了!!!

    • BBU坏了
    • No-Battery Write Cache: Enabled 及Write Back ok if Bad BBU的情况下,如果电池坏掉,那么I/O依然得到保障,但是带来了丢失数据的风险。即使机器没有断电,Cache中的数据一旦没有电池(BBU)的保护,数据就丢失了,集团采用此策略,以数据丢失换取故障风险,单份数据集不建议开启此策略,OB的多份数据写成功的解决了这个问题。
    • No-Battery Write Cache: Disabled 情况下cache会禁写,cache策略由WB-》WT转化,遇到业务高峰,极有可能达到io瓶颈,造成故障。

    公司在做断电演练的时候,没有全部raid卡writethrough,出现binlog文件损坏的问题,也出现过一台机器block corrupt。后期会设置为 NoCachedBadBBU ,当设置为NoCachedBadBBU,那么只要BBU电池坏了,或者电量不足,就会自动转换为WT模式,来避免 BBU 损坏导致的数据丢失。 write through 对性能影响的初步实验结果是,会导致 rt 平均增加 5ms,load 和 iowait 也有显著提高 load 0.44 -> 2.4, cpu iowait 0.1->4。

    • 系统crash或者掉电

    BBU能够保障机器数据不丢失,等到机器重启上电后立刻刷盘,一般可以保证数小时的数据存储,这也是BBU的唯一作用。

    机房的市电都是经过ups然后才到实际机器上的,当发生机房断电时,ups的存在可以让机器无感知仍旧工作,但不能保证30分钟以上,此时需要工作人员尽快启动柴油机发电,这也是为什么机房距离加油站较近的原因。

    总结&反问

    1. 设置合适的RAID卡策略保证数据的安全性的同时最大化性能,我们真的可以保证数据不丢?数据不丢不意味着数据不会损害,不代表有用。如commit后,刷新事务数据时,事务需要保证完整性,但是刷到一半时断电,内存数据丢失,事务并没有完整持久化,此时会丢失一个事务。当刷binary log时同样导致已经传输到备库或者下游的数据没有及时持久化,这些文件都会损害,但最起码raid保证了持久化的数据不丢。
    2. RAID卡策略并不是唯一的,可以根据不同的业务场景选择,如No-Battery Write Cache的cache,当性能重要选择打开,数据安全更重要是选择关闭。

    案例分享

    1、现象描述 在2015-12-07 21:28 收到 thread_running 357的告警

    首先DB的tps和qps并没有什么特别变化,lor也是正常

    查看IO发现异常,在21:28的时候await很高

    查看raid日志

    基本可以确定这次的thread_running 飙高的原因是:raid卡充放电,导致raid卡缓存失效,io变慢。

    参考

    磁盘CACHE的两大功能

    RAID卡的缓存与磁盘自带的缓存的关系

    Dell服务器Raid卡电池策略调整

    MySQL服务器Raid卡Cache策略的设置总结

    MegaCLI Scripts and Commands

  • 相关阅读:
    Ubuntu安装Oracleclient远程连接数据库
    解决报错:Unable to process Jar entry [org/springframework/jmx/export/annotation/*****]
    解决报错:The import javax.servlet.annotation cannot be resolved
    解决导入MAVEN项目报错Dynamic Web Module 3.1 requires Java 1.7 or newer.
    python批量下载链接图片
    thrax的安装
    cmake下载与使用(含cmake安装包)
    NFA转换为DFA
    杂记
    attention机制
  • 原文地址:https://www.cnblogs.com/zhiqian-ali/p/5079164.html
Copyright © 2020-2023  润新知