第21章 高可用性
本章将为读者介绍单点故障的处理策略,以及单点故障最为主流的解决方案:MySQL数据库切换。
21.1 概述
可用性定义为系统保持正常运行时间的百分比,高可用可以理解为系统可用时间的百分比很高,也就是说服务可用的时间很高,数据没有丢失,也没有其他异常。
比如,一个未预热的数据库突然承受大流量的冲击,最开始的阶段,响应时间可能会很长,这个时候很难说服务可用。
我们一般用百分比来表示可用性,举例如下。
99.999%的可用性表示全年5分钟故障时间。
99.99%的可用性表示全年1小时故障时间。
99.9%表示全年8小时故障时间。
提高可用性的成本可能会很高,其策略也可能会很复杂,
因此我们需要尽可能地平衡“停机”(downtime)成本和减少“停机”时间的成本,衡量系统失败的概率和所造成的损失,对比投入的成本,不要过度设计。
我们可以分解系统的关键部分和非关键部分,这样可以让你更好地设计可用性策略,因为提高一个小系统的可用性会更容易。
有时我们为了架构简单,不得不 保留“单点”,那么我们可以使用更可靠的硬件和主机来尽量减少风险。
一般影响数据库服务可用性的主要因素是硬件、网络故障或性能问题、软件Bug等。
如果使用了读写分离的架构,还可能因为复制延时或复制错误导致从库的数据滞后,数据不一致,这也会对可用性造成影响。
生产人员的误操作,比如误删除了数据库文件和数据库表,都可能导致数据库服务的可用性下降。
针对如上的影 响因素,我们可以制定如下的一些措施,以提高可用性。
1)上线或升级新的软硬件之前,充分做好测试验证。
2)制定合理的备份策略,并定期恢复验证。
3)严格按照流程规范操作数据库,隔离生产环境和测试、开发环境。
4)架构力求简单、可靠,因为复杂的策略可能导致维护和处理问题变得困难,也很难实现高可用策略,记住,解决复杂问题的最好方法就是让复杂的问题不再出现。
5)做好监控,尽量在问题爆发之前就能预警。
6)应回顾和分析故障事件,尽量避免故障的再次发生。
高可用不仅仅是技术的问题,也是管理的问题,有正确的流程、规范和步骤,有良好的文档,有训练有素的维护人员,才可以减少故障发生的概率,并能在故障发生后快速恢复。

21.2 单点故障
单点故障(SPOF)指某个系统的一部分,如果它停止工作了,将会导致整个系统停止工作。
在我们的架构设计中,要尽量避免单点故障。
要避免单点故障,我们首先应找到可能导致整个系统失效的关键的组件,综合评估,在满足我们可用性的要求下,应该如何避免单点故障,或者减少单点故障爆发的可能性。
一般我们靠增加冗余的方式来解决单点故障,冗余的级别和方式不一。
从设备的角度,我们可以对主机的单个组件进行冗余,比如使用多个网卡,我们也可以对整个主机所有的关键部件进行冗余,
在更高的级别上,我们可以对整个主机进行冗余,或者对整个IDC机房进行冗余。
从组织管理的角度,我们还可以对维护数据 =库的人员进行冗余。
MySQL的主从架构本质上也是增加一个冗余的从节点来提高可用性。
如下将详细介绍一些常用的解决单点故障的技术。
1)使用负载均衡软硬件设备,比如对于一组读库,我们可以在前端放置一个负载均衡设备,以解决后端某个从库异常的故障,你可能还需要考虑负载均衡设备自身的高可用性。
2)使用共享存储、网络文件系统、分布式文件系统或复制的磁盘(DRBD)。
传统的数据库产品,如Oracle RAC使用的是基于SAN的共享存储存放数据,数据库的多个实例并发访问共享存储存取数据,
应用通过配置在数据库主机上的虚拟 IP访问数据库,如果某个数据库主机宕机,其他数据库实例接管虚拟IP,那么应用仍然可以访问到数据库。
MySQL官方介绍了一个实现网络RAID的方案DRBD。也有人使用网络文件系统NFS或分布式文件系统存储共享的数据库文件。
使用共享存储是比较传统的做法,由于成本比较高,且共享存储自身可能也会成为单点,因此互联网架构中很少使用这类方案,
有些人为了确保主库数据的安全性,把二进制日志存放到共享存储中,这也是一种可以接受的做法。
使用网络RAID,即DRBD虽然是可行的,但现实中用得并不多,主要原因在于目前的SSD已经足够快了,
DRBD自身会成为整个系统的瓶颈,而且会导致主机的浪费,因为只有一半的主机可用。因此作为折中的方案,可以只用DRBD复制二进制日志。
笔者没有使用过NFS存储共享的数据库文件,网络文件系统难以实现高吞吐,NFS更适用的场景是存放一些共享的备份文件。
有些人选择使用分布式文件系统来存放数据库文件,由于分布式文件系统本身的复杂性,你需要考虑它的维护成本及团队人员的技能等因素,
如果传统的方法可以存放数据文件,那么不建议使用这 么一个“笨重”的方案。
3)基于主从复制的数据库切换。
目前MySQL使用最多的高可用方案是MySQL数据库主从切换,
也就是说,基于主从复制的冗余,通过对主库增加一个或多个副本(备库),在发生故障的情况下,把生产流量切换到副本上,以确保服务的正常运行。
随着主机性能的发展,基于主机之间的高可用是主流也是趋势。21.3节会详细基于主从复制的数据库切换。

21.3 MySQL数据库切换
基于数据库复制架构的切换是目前MySQL高可用的主流解决方案。
我们把数据库成双成对地设置成主从架构,应用平时只访问主库,如果主库宕机了,从库可以替补使用,且满足一定的条件,那么我们可以把应用的流量切换到从库,使服务仍然可用。
由于数据库切换依赖的是MySQL的主从复制架构,所以你需要深刻了解MySQL的复制原理和机制,确保MySQL的同步一直是可用的。
你需要尽可能地保证数据已经同步到了从库,以免丢失数据。
数据库可以配置成主从架构,也可以配置成主主架构。我们建议使用主从架构,这是最稳健、最可靠的方案。
有些人把数据库配置成主主架构的原因是,他们认为这样做可以更便于切换及回切。
配置成主主架构的时候,你需要小心处理主键冲突等复制问题,在从库上进行操作时需要非常小心,因为错误的操作也会同步到主库。
配置成主主架构只是为了方便切换,现实中,仍然需要确保仅有一个主库提供服务,另一个节点可作为备用。
除了单点故障,有时我们也可以为了其他目的进行切换,比如在大表中修改表结构,为了避免影响业务,临时把所有流量切换到从库。这种情况下,配置成主主架构会更方便。
为了简化容量管理,以确保切换数据库流量之后,数据库主机能够正常提供服务,应该确保主备机器的软硬件配置尽量一致。
由于数据库从库的数据一般并未“预热”,热点数据也没有被加载到内存,所以在进行流量切换的初始时刻,可能会难以接受其性能,你可以预先运行一些SQL预热数据。
对于写入事务比较多的业务,在发生故障的情况下进行主从切换,可能会丢失数据和导致主从不一致,
一般情况下,互联网业务的可用性会高于数据一致性,丢失很少的事务是可以接受的。
一些数据也是允许丢失的,比如丢失一些评论是可以接受的,如果需要绝对的不能丢失数据,那么你的方案的实现成本会很高,
比如为了确保不丢失主库的日志,你可能需要共享存储来存储主库的日志,还可能需要使用全同步或半同步的技术确保数据的变更已经被传送到了从库。
对于数据库的切换,我们有如下的一些方式。
1)通过修改程序的配置文件实现切换。
程序配置文件里有数据库的路由信息,我们可以修改程序的配置文件实现数据库流量的切换,在大多数情况下,我们需要重启应用。
比如JAVA服务,默认配置下,我们需要重新启动应用服务。在服务非常多的情况下,也有把数据库配置信息存储在数据库中的。
2)修改内网DNS。
我们可以在生产环境中配置内网DNS,通过修改内网DNS指向的数据库服务器的IP,实现主库在故障情况下的切换,这种方式,往往也需要重启应用服务。
由于内网DNS可能不归属于DBA团队掌控,DNS服务器的维护和高可用也需要成本,而且更改内网DNS也需要时间,所以这种方式用得比较少。
3)修改主机的hosts文件。
/etc/hosts里可以配置与数据库服务器的域名对应的IP,但是还不够理想。而且在有很多应用服务器的时候,维护一份统一的hosts文件的成本也会比较高。
4)一些能够实现高可用的工具集,如MHA、MMM,它们用于监控数据库节点的存活状况,通过修改配置文件或漂移主库IP的方式来实现数据库的高可用。
MMM通过漂移虚拟IP的方式处理单点故障,但许多生产实践证明,其作为一套自动切换方案并不是很可靠,如果需要使用,建议只使用手动切换的功能。
MHA是 Perl编写的一套MySQL故障切换工具,支持通过修改全局配置和漂移虚拟IP两种方式处理单点故障,已经在许多生产环境中得到了验证,是值得考虑的方案。
你也可以自己编写脚本监控数据库节点的可用性,漂移虚拟机IP实现切换,
需要留意的是,漂移IP的方式存在一个缺陷,其严重依赖硬件的可靠性,需要主机、 网络设备的配合工作。
在生产环境中,可能会因为网络硬件的原因导致虚拟IP不能正常漂移。
5)对于大规模的数据库集群,需要更智能地处理单点切换,应该尽量不依赖自己无法控制的因素,我们可以使用独立的Proxy代理的方式实现单点切换。
所有的流量都经过Proxy,Proxy智能地处理后端的数据库主节点宕机故障,需要留意的是,你还需要处理好Proxy自身的高可用性。
实现Proxy的成本很高,一些互联网公司已经有自己成熟的数据库Proxy。
理论上,Proxy是可以代理本地IDC的流量的,也可以代理其他IDC的数据库流量,但由于网络延时和安全的考虑,一般建议仅代理本地IDC的流量。
如果需要配置跨IDC的数据库切换,更可靠的方案是,在应用层切换流量,也就是说,让用户去访问正常IDC的应用服务器。
6)通过客户端、框架配合实现单点切换,相对于使用Proxy的方式,这种方式更轻量级。

21.4 跨IDC同步
有时我们需要部署IDC级别的冗余,在另一个IDC中部署数据库的从库,由于网络层的不稳定,你很难实现很高的可用性,除非你对数据的延时和数据的一致性要求不高。
你需要意识到,距离越远,网络越不可靠;中间的环节越多,网络越不可靠,所以尽量不要进行跨越数据中心的实时操作。
如果部署了跨IDC的数据库访问,比如部署了读写分离的架构,在一个IDC中集中地处理所有的写请求,把读请求分担到各个IDC,
那么你需要在应用层友好地处理网络异常,或者复制问题导致的复制延时问题,如果有比较多的远程写入,那么还需要处理网络问题导致的写入失败。
不仅仅是主从同步,只要距离足够远,网络质量就难以得到保证,就需要留意同步对应用的影响,
你可能需要尽可能地减少节点之间的数据交互,及时调度用户访问其他节点,甚至使用专用的高质量网络。

小结:
本章主要介绍了MySQL保障高可用的方案,MySQL主从复制几乎是所有高可用方案的基础。
读者应该熟悉MySQL的复制原理。
对于跨IDC的数据同步,许多人可能没有意识到它的局限性,DBA应该尽量避免在生产环境中出现这种架构。

05-11 22:43