MySQL高可用方案

      高可用架构对于互联网服务基本是标配,不管是应用服务仍是数据库服务都须要作到高可用。虽然互联网服务号称7*24小时不间断服务,但多多少少有一些时候服务不可用,好比某些时候网页打不开,百度不能搜索或者没法发微博,发微信等。通常而言,衡量高可用作到什么程度能够经过一年内服务不可用时间做为参考,要作到3个9的可用性,一年内只能累计有8个小时不可服务,而若是要作到5个9的可用性,则一年内只能累计5分钟服务中断。因此虽然说每一个公司都说本身的服务是7*24不间断的,但实际上能作到5个9的屈指可数,甚至根本作不到,国内互联网巨头BAT(百度,阿里巴巴,腾讯)都有由于故障致使的停服问题。对于一个系统而言,可能包含不少模块,好比前端应用,缓存,数据库,搜索,消息队列等,每一个模块都须要作到高可用,才能保证整个系统的高可用。对于数据库服务而言,高可用可能更复杂,对用户的服务可用,不只仅是能访问,还须要有正确性保证,所以讨论数据库的高可用方案时,通常会同时考虑方案中数据一致性问题。今天这篇文章主要讨论MySQL数据库的高可用方案,介绍每种方案的特性以及优缺点,本文是对各类方案的总结,但愿抛砖引玉,和你们一块儿讨论。html

1.基于共享存储的方案SAN
方案介绍:SAN(Storage Area Network)简单点说就是能够实现网络中不一样服务器的数据共享,共享存储可以为数据库服务器和存储解耦。使用共享存储时,服务器可以正常挂载文件系统并操做,若是服务器挂了,备用服务器能够挂载相同的文件系统,执行须要的恢复操做,而后启动MySQL。共享存储的架构以下:前端

优势:
1.能够避免存储外的其它组件引发的数据丢失。
2.部署简单,切换逻辑简单,对应用透明。
3.保证主备数据的强一致。
限制或缺点:
1.共享存储是单点,若共享存储挂了,则会丢失数据。
2.价格比价昂贵。mysql

2.基于磁盘复制的方案 DRBD
方案介绍:DRBD(Distributed Replicated Block Device)是一种磁盘复制技术,能够得到和SAN相似的效果。DBRD是一个以linux内核模块方式实现的块级别同步复制技术。它经过网卡将主服务器的每一个块复制到另一个服务器块设备上,并在主设备提交块以前记录下来。DRBD与SAN相似,也是有一个热备机器,开始提供服务时会使用和故障机器相同的数据,只不过DRBD的数据是复制存储,不是共享存储。DRBD的架构图以下:linux


优势:
1.切换对应用透明
2.保证主备数据的强一致。
限制或缺点:
1.影响写入性能,因为每次写磁盘,实质都须要同步到网络服务器。
2.通常配置两节点同步,可扩展性比较差
3.备库不能提供读服务,资源浪费web

3.基于主从复制(单点写)方案
      前面讨论的两种方案分别依赖于底层的共享存储和磁盘复制技术,来解决MYSQL服务器单点和磁盘单点的问题。而实际生产环境中,高可用更多的是依赖MySQL自己的复制,经过复制为Master制做一个或多个热副本,在Master故障时,将服务切换到热副本。下面的几种方案都是基于主从复制的方案,方案由简单到复杂,功能也愈来愈强大,实施难度由易到难,各位能够根据实际状况选择合适的方案。
3.1.keepalived/heartbeat
方案介绍:
      keepalived是一个HA软件,它的做用是检测服务器(web服务器,DB服务器等)状态,检查原理是模拟网络请求检测,检测方式包括HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK等,对于DB服务器而言,主要就是IP,端口(TCP_CHECK),但这可能不够(好比DB服务器ReadOnly),所以keepalived也支持自定义脚本。keepalived基于VRRP协议来实现高可用,每一个服务器所在机器会部署启动一个keepalived服务,多个keepalived服务中有一个Master,Master定时向其它各个Slave keepalived服务发送心跳包(当不发送心跳包时,则认为主挂了,须要从新选主),全部的服务器配置指向同一个VIP,正常状况下,应用访问VIP时,即访问的是master配置指向的真实IP;而若是master所在keepalived服务挂了,则基于VRRP协议会从新选一个keepalived Master来提供服务,在这种状况下,若是master上的DB正常,并且上面有长链接,则会形成双写。keepalived经过监听来确认服务器的状态,若是发现服务器故障,则将故障服务器从系统中剔除(经过关掉自身的keepalived服务实现),keepalived的高可用架构以下图,分别在主、从服务器上安装keepalived的软件,并配置一样的VIP,VIP层将真实IP屏蔽,应用服务器经过访问VIP来获取DB服务。当Master故障时,keepalived感知,并将Slave提高主,继续提供服务对应用层透明。sql


优势:
1. 安装配置简单
2. Master故障时,Slave快速切换提供服务,而且对应用透明。
限制或缺点:
1.须要主备的IP在同一个网段。
2.提供的检测机制比较弱,须要自定义脚原本肯定Master是否能提供服务,好比更新心跳表等。
3.没法保证数据的一致性,原生的MySQL采用异步复制,若Master故障,Slave数据可能不是最新,致使数据丢失,所以切换时要考虑Slave延迟的因素,肯定切换策略。对于强一致需求的场景,能够开启(semi-sync)半同步,来减小数据丢失。
4.keepalived软件自身的HA没法保证。数据库

3.2.MHA
方案介绍:MHA(Master High Availability)是一位日本MySQL大牛用Perl写的一套MySQL故障切换方案,来保证数据库的高可用,MHA经过从宕机的主服务器上保存二进制日志来进行回补,能在最大程度上减小数据丢失。MHA由两部分组成:MHA Manager(管理节点)和MHA Node(数据节点)。MHA能够单独部署在一台独立的机器上管理多个master-slave集群,MHA Node运行在每台MySQL服务器上,主要做用是切换时处理二进制日志,确保切换尽可能少丢数据。MHA Manager会定时探测集群中的master节点,当master出现故障时,它能够自动将最新数据的slave提高为新的master,而后将全部其余的slave从新指向新的master,整个故障转移过程对应用程序彻底透明。MHA的架构以下:缓存


MHA failover过程:
a.检测到 Master 异常,进行一系列判断,最后肯定 Master 宕掉;
b.检查配置信息,罗列出当前架构中各节点的状态;
c.根据定义的脚本处理故障的 Master,VIP漂移或者关掉mysqld服务;
d.全部 Slave 比较位点,选出位点最新的 Slave,再与 Master 比较并得到 binlog 的差别,copy 到管理节点;
e.从候选节点中选择新的 Master,新的 Master 会和位点最新的 Slave 进行比较并得到 relaylog 的差别;
f.管理节点把 binlog 的差别 copy 到新 Master,新 Master 应用 binlog 差别和 relaylog 差别,最后得到位点信息,并接受写请求(read_only=0);
g.其余 Slave 与位点最新的 Slave 进行比较,并得到 relaylog 的差别,copy 到对应的 Slave;
h.管理节点把 binlog 的差别 copy 到每一个 Slave,比较 Exec_Master_Log_Pos 和 Read_Master_Log_Pos,得到差别日志;
i.每一个Slave应用全部差别日志,而后 reset slave 并从新指向新 Master;
j.新 Master reset slave 来清除 Slave 信息。服务器

优势:
1. 代码开源,方便结合业务场景二次开发
2. 故障切换时,能够修复多个Slave之间的差别日志,最终使全部Slave保持数据一致,而后从中选择一个充当新的Master,并将其它Slave指向它。
3. 能够灵活选择VIP方案或者全局目录数据库方案(更改Master IP映射)来进行切换。
缺点:
1.没法保证强一致,由于从故障Master上保存二进制日志并不老是可行,好比Master磁盘坏了,或者SSH认证失败等。
2.只支持一主多从架构,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当master,一台充当备用master,另一台充当从库。
3.采用全局目录数据库方案切换时,须要应用感知变化,所以对应用不透明,所以要保持切换对应用透明,依然依赖于VIP。
4.不适用于大规模集群部署,配置比较复杂。
5.MHA管理节点自己的HA没法保证。微信

3.3.基于zookeeper的高可用
方案介绍:
      从前面的讨论能够看到,不管是keepalived方案仍是MHA方案,都没法解决HA软件自身的高可用问题,由于HA自己是单点。那么若是将HA也引入多个副本呢?那么又带来新的问题,1.HA软件之间如何保证强同步。2.如何确保不会有多个HA同时进行切换动做。这两个问题实质都分布式系统一致性问题,为此,能够为HA软件引入相似Paxos,Raft这样的分布式一致性协议,保证HA软件的可用性。zooKeeper是一个典型的发布/订阅模式的分布式数据管理与协调框架,经过zookeeper中丰富的数据节点类型进行交叉使用,配合watcher事件通知机制,能够方便地构建一系列分布式应用涉及的核心功能,好比:数据发布/订阅,负载均衡,分布式协调/通知,集群管理,Master选举,分布式锁和分布式队列等。zookeeper是一个很大话题,你们能够google去找更多的信息,我这里主要讨论zookeeper如何解决HA自身可用性问题。架构图以下:


图中每一个MySQL节点上面部署了一个HA client,用于实时向zookeeper汇报本地节点的心跳状态,好比主库crash,经过修改zookeeper(如下简称zk)上的节点信息,来通知HA。HA节点在zk上注册监听事件,当zk节点发生变化时会自动让HA感知,HA节点能够部署一个或多个,主要用于容灾。HA节点之间经过zookeeper服务来实现数据的一致性,经过分布式锁保证多个HA节点不会同时对一个主从节点进行切换。HA自己是无状态的,全部MySQL节点状态信息所有保存在zookeeper服务器上,切换时,HA会对MySQL节点进行复检,而后切换。咱们看看引入zookeeper后的切换流程:
a.HA client 检测到 Master 异常,进行一系列判断,最后肯定 Master 宕掉;
b.HA client 删除 Master在zk上的节点信息;
c.因为监听机制,HA会感知到有节点被删除;
d.HA对MySQL节点进行复检,好比创建链接,更新心跳表等
e.确认异常后,则进行切换。

咱们再看看这种架构下,是否能保证HA自身的高可用
(1).若是HA-client自己挂了,MySQL节点正常?
HA-Client管理的MySQL节点没法与zookeeper保持心跳,zk服务将节点删除,HA会感知到这种变化,准备尝试一次切换,切换前,会进行复检,复检时发现MySQL节点是OK的,则不会切换。
(2).MySQL节点与zookeeper的网络断了,那么表现如何?
因为HA-Client与节点在同一台主机,所以HA-client没法再定时向zk汇报心跳,zk会将对应的MySQL节点信息删除,HA尝试复检,依然失败,则进行切换。
(3).HA挂了,表现如何?
因为HA无状态,而且有多个副本,所以一个HA挂了,不会对整个系统形成影响。

优势:
1. 保证了整个系统的高可用
2. 主从的强一致依赖于MySQL自己,好比半同步,或者外围工具的回补策略,相似MHA。
3. 扩展性很是好,能够管理大规模集群。
缺点:
1.引入zk,整个系统变得复杂。

4.基于Cluster(多点写)方案
     第3节讨论的方案基本是目前业内使用的主流方案,这类方案的特色是,单点写。虽然咱们能够借助中间件进行分片(sharding),可是对于同一份数据,依然只容许一个节点写,从这个角度来讲,上面的方案是伪分布式。下面讨论的两种方案算是真正分布式,同一个数据理论上能够在多个节点写入,相似于Oracle的RAC,EMC的GreenPlum这种分布式数据库。在MySQL领域,主要提供了2种解决方案:基于Galera的PXC和NDB Cluster。MySQL Cluster实现基于NDB存储引擎,使用不少局限性,而PXC是基于innodb引擎,虽然也有局限性,但因为目前innodb使用很是普遍,因此有必定的参考价值。目前据我所知,去哪儿公司在他们的生产环境中使用了PXC方案。PXC(Percona XtraDB Cluster)的架构图以下:

优势:
1.准同步复制
2.多个可同时读写节点,可实现写扩展,较分片方案更进一步
3.自动节点管理
4.数据严格一致
5.服务高可用
缺点:
1.只支持innodb引擎
2.全部表都要有主键
3.因为写要同步到其它节点,存在写扩大问题
4.很是依赖于网络稳定性,不适用于远距离同步

5.基于中间件proxy的方案
     准确地来讲,中间件与高可用没有特别大的关系,由于切换都是在数据库层完成,但引入中间层后,使得对应用更透明。在引入中间件以前,全部的方案,基本都依赖于VIP漂移机制,或者不依赖于VIP又不能保证对应用透明。经过加入中间件层,能够同时实现对应用透明和高可用。此外中间层还能够作sharding,方便写扩展。proxy的方案不少,好比mysql自带的mysql-proxy和fabric,阿里巴巴的cobar和tddl等。咱们以fabric为例,其架构图以下:


      应用都请求 Fabric 链接器,而后经过使用 XML-RPC 协议访问 Fabric 节点, Fabric 节点依赖于备用存储 (backing store),里面存储整个 HA 集群的元数据信息。链接器读取 backing store 的信息,而后将元数据缓存到 cache,这样作的好处就是减小每次创建链接时与管理节点交互所带来的开销。Fabric 节点可管理多个 HA Group,每一个 HA Group 里有一个 Primary 和多个 Secondary(slave),当 Primary 异常的时候会从 Secondary 中选出最合适的节点提高为新 Primary,其他 Secondary 都将从新指向新 Primary。这些都是自动操做,对业务是无感知的,HA 切换以后还须要通知链接器更新的元数据信息。
优势:
1.切换对应用透明
2.可扩展性强,方便分片扩展
3.能够跨机房部署切换

缺点:
1.是一个比较新的组件,没有不少实际应用场景
2.没有解决强一致问题,主备强一致性依赖于MySQL自身(半同步),以及回滚回补机制。

总结
     以上介绍了目前MySQL几种典型的高可用架构,包括基于共享存储方案,基于磁盘复制方案和基于主从复制的方案。对于主从复制方案,分别介绍了keepalived,MHA以及引入zookeeper的方案。对于每种方案,都从持续可用,数据强一致性,以及切换对应用的透明性进行说明。我的以为基于MySQL复制的方案是主流,也很是成熟,引入中间件和引入zookeeper虽然能将系统的可用性作地更好,可支撑的规模更大,但也对研发和运维也提出了更高的要求。所以,在选择方案时,要根据业务场景和运维规模作抉择。

参考文档
http://hedengcheng.com/?p=892
http://imysql.cn/tag/pxc
http://www.cnblogs.com/gomysql/p/3675429.html
http://www.2cto.com/database/201407/319748.html
http://chuansong.me/n/2250351
http://blog.csdn.net/lichangzhen2008/article/details/44708227