Mysql高可用方案

本次专题是 MySQL高可用方案选型,这个专题想必有不少同窗感兴趣。html

高可用的意义以及各类不一样高可用等级相应的停机时间我就没必要多说了,直接进入主题。前端

可选MySQL高可用方案

MySQL的各类高可用方案,大可能是基于如下几种基础来部署的:node

  1. 基于主从复制;mysql

  2. 基于Galera协议;linux

  3. 基于NDB引擎;web

  4. 基于中间件/proxy;sql

  5. 基于共享存储;数据库

  6. 基于主机高可用;vim

在这些可选项中,最多见的就是基于主从复制的方案,其次是基于Galera的方案,咱们重点说说这两种方案。其他几种方案在生产上用的并很少,咱们只简单说下。centos

基于主从复制的高可用方案

双节点主从 + keepalived/heartbeat

通常来讲,中小型规模的时候,采用这种架构是最省事的。
两个节点能够采用简单的一主一从模式,或者双主模式,而且放置于同一个VLAN中,在master节点发生故障后,利用keepalived/heartbeat的高可用机制实现快速切换到slave节点。

在这个方案里,有几个须要注意的地方:

  • 采用keepalived做为高可用方案时,两个节点最好都设置成BACKUP模式,避免由于意外状况下(好比脑裂)相互抢占致使往两个节点写入相同数据而引起冲突;

  • 把两个节点的auto_increment_increment(自增起始值)和auto_increment_offset(自增步长)设成不一样值。其目的是为了不master节点意外宕机时,可能会有部分binlog未能及时复制到slave上被应用,从而会致使slave新写入数据的自增值和原先master上冲突了,所以一开始就使其错开;固然了,若是有合适的容错机制能解决主从自增ID冲突的话,也能够不这么作;

  • slave节点服务器配置不要太差,不然更容易致使复制延迟。做为热备节点的slave服务器,硬件配置不能低于master节点;

  • 若是对延迟问题很敏感的话,可考虑使用MariaDB分支版本,或者直接上线MySQL 5.7最新版本,利用多线程复制的方式能够很大程度下降复制延迟;

  • 对复制延迟特别敏感的另外一个备选方案,是采用semi sync replication(就是所谓的半同步复制)或者后面会提到的PXC方案,基本上无延迟,不过事务并发性能会有不小程度的损失,须要综合评估再决定;

  • keepalived的检测机制须要适当完善,不能仅仅只是检查mysqld进程是否存活,或者MySQL服务端口是否可通,还应该进一步作数据写入或者运算的探测,判断响应时间,若是超过设定的阈值,就能够启动切换机制;

  • keepalived最终肯定进行切换时,还须要判断slave的延迟程度。须要事先定好规则,以便决定在延迟状况下,采起直接切换或等待何种策略。直接切换可能由于复制延迟有些数据没法查询到而重复写入;

  • keepalived或heartbeat自身都没法解决脑裂的问题,所以在进行服务异常判断时,能够调整判断脚本,经过对第三方节点补充检测来决定是否进行切换,可下降脑裂问题产生的风险。

双节点主从+keepalived/heartbeat方案架构示意图见下:

MySQL双节点高可用架构

图解:MySQL双节点(单向/双向主从复制),采用keepalived实现高可用架构。

多节点主从+MHA/MMM

多节点主从,能够采用一主多从,或者双主多从的模式。
这种模式下,能够采用MHA或MMM来管理整个集群,目前MHA应用的最多,优先推荐MHA,最新的MHA也已支持MySQL 5.6的GTID模式了,是个好消息。
MHA的优点很明显:

  • 开源,用Perl开发,代码结构清晰,二次开发容易;

  • 方案成熟,故障切换时,MHA会作到较严格的判断,尽可能减小数据丢失,保证数据一致性;

  • 提供一个通用框架,可根据本身的状况作自定义开发,尤为是判断和切换操做步骤;

  • 支持binlog server,可提升binlog传送效率,进一步减小数据丢失风险。

不过MHA也有些限制

  • 须要在各个节点间打通ssh信任,这对某些公司安全制度来讲是个挑战,由于若是某个节点被黑客攻破的话,其余节点也会跟着遭殃;

  • 自带提供的脚本还须要进一步补充完善,固然了,通常的使用仍是够用的。

多节点主从+etcd/zookeeper

在大规模节点环境下,采用keepalived或者MHA做为MySQL的高可用管理仍是有些复杂或麻烦。
首先,这么多节点若是没有采用配置服务来管理,必然杂乱无章,线上切换时很容易误操做。
在较大规模环境下,建议采用etcd/zookeeper管理集群,可实现快速检测切换,以及便捷的节点管理。

基于Galera协议的高可用方案

Galera是Codership提供的多主数据同步复制机制,能够实现多个节点间的数据同步复制以及读写,而且可保障数据库的服务高可用及数据一致性。
基于Galera的高可用方案主要有MariaDB Galera Cluster和Percona XtraDB Cluster(简称PXC),目前PXC用的会比较多一些。

PXC的架构示意图见下:

pxc overview

(图片源自网络),图解:在底层采用wsrep接口实现数据在多节点间的同步复制。

 

pxc certification

(图片源自网络),图解:在PXC中,一次数据写入在各个节点间的验证/回滚流程。

PXC的优势

  • 服务高可用;

  • 数据同步复制(并发复制),几乎无延迟;

  • 多个可同时读写节点,可实现写扩展,不过最好事先进行分库分表,让各个节点分别写不一样的表或者库,避免让galera解决数据冲突;

  • 新节点能够自动部署,部署操做简单;

  • 数据严格一致性,尤为适合电商类应用;

  • 彻底兼容MySQL;

虽然有这么多好处,但也有些局限性:

  • 只支持InnoDB引擎;

  • 全部表都要有主键;

  • 不支持LOCK TABLE等显式锁操做;

  • 锁冲突、死锁问题相对更多;

  • 不支持XA;

  • 集群吞吐量/性能取决于短板;

  • 新加入节点采用SST时代价高;

  • 存在写扩大问题;

  • 若是并发事务量很大的话,建议采用InfiniBand网络,下降网络延迟;

事实上,采用PXC的主要目的是解决数据的一致性问题,高可用是顺带实现的。由于PXC存在写扩大以及短板效应,并发效率会有较大损失,相似semi sync replication机制。

其余高可用方案

  • 基于NDB Cluster,因为NDB目前仍有很多缺陷和限制,不建议在生产环境上使用;

  • 基于共享存储,一方面须要不太差的存储设备,另外共享存储可也会成为新的单点,除非采用基于高速网络的分布式存储,相似RDS的应用场景,架构方案就更复杂了,成本也可能更高;

  • 基于中间件(Proxy),如今可靠的Proxy选择并很少,并且没有通用的Proxy,都有有所针对,好比有的专一解决读写分离,有的专一分库分表等等,真正好用的Proxy通常要自行开发;

  • 基于主机高可用,是指采用相似RHCS构建一个高可用集群后,再部署MySQL应用的方案。老实说,我没实际用过,但从侧面了解到这种方案生产上用的并很少,可能也有些局限性所致吧;

以DBA们的聪明才智,确定还有其余我不知道的方案,也欢迎同行们间多多交流。

 

 

从 MySQL+MMM 到 MariaDB+Galera Cluster : 一个高可用性系统改造

不多有事情比推出高可用性(HA)系统以后便常常看到的系统崩溃更糟糕。对于咱们这个Rails运行机的团队来讲,这个失效的HA系统是MySQL多主复制管理器(MMM)

25081034_gj7s.png

咱们已经找寻MMM的替代品有一段时间了,几个月以前,咱们转换到了MariaDB + Galera Cluster以寻求高可用的Mysql。

MMM怎么了,Galera Cluster又有什么特别之处呢?继续阅读!

MySQL多主机复制 (MMM)基本被打破

MySQL MMM 是如何工做的:一台安装了MySQL MMM的服务器每十秒种(默认间隔)轮询一次MySQL节点, 来检查其状态。仅其中的一台服务器接收到写入器角色 - 其余的能够拥有阅读器角色。 MMM 维护了一个虚拟IP,这个IP指向拥有写入器角色的节点。

问题在于轮询:若是MySQL每十分钟轮询,那么若是写入器节点在检查的间歇出现故障怎么办?若是你设置了HA你可能正处理着许多事务 - 在MMM检测到写入器节点不正常以前,可能已经有成千上万的事务失败了。更糟糕的是,若是存在一种内部问题:复制失败在先,事务失败在后,那么你要把写入器角色转到其余节点上吗?可是其余节点不必定符合原始的写入器节点。

减小轮询间隔到1秒也不能修正这个问题-大型数据库可能在每秒内运行许多事务。

所以轮询是根本问题,并且超出了根本问题范围。没法控制的MySQL MMM常常产生难以恢复的问题。Baron Swartz在Percona的MySQL大神上对MMM的缺陷有以下描述:

简要地来讲,MMM产生的宕机时间比它要防止的宕机时间更长。所以它是一个低可靠性的工具,不是高可靠性的工具。它可让你连续几天以7X24小时的工做方式从宕机的机器里提取数据,并放回到服务器上,这只会致使系统真正的很是严重的一塌糊涂。所以,MMM赋予词语"cluset-f__k"新的意义。

尽管MMM存在缺陷,然而它至少是对MySQL进行高可靠性的一次突破。然而时间改变了一切。甚至MySQL MMM的建立者也说到了要更改的时候了。Baron有关MMM的博客日志有Alexey's的以下评论:

我是MMM的最初的做者,我彻底赞成你的意见。每次我试图给集群添加HA的时候,我都会想起MMM,并且须要亲自去尝试,由于我只是不肯定这个工具的我所作的配置。并且市场上没有其余软件能够可靠地作这项工做。

那么,为何Galera是最好的MySQL HA解决方案呢?

咱们的Galera Cluster设置仍然使用轮询来作健康检测——这比MMM好在哪里呢?

答案在于主从复制怎样是运做的。对于标准版的MySQL,对master的写操做被记录于一个二进制的日志。Slave会在以后复制二进制日志中的查询。查询在写服务器上运行与在其它节点上运行时刻之间,老是会有一个延迟。它是异步的

MySQL异步复制有下面的问题:

  • slave服务器的数据集老是落后于master服务器。

  • MySQL复制很慢——它从二进制日志回访事务。

对于Galera,事务是在它们被提交以前被全部节点确认。若是一个事务在一个节点失败了,那个节点将马上从群集中移除。换句话说,Galera主从复制是同步的。你 永远也不会丢失事务——没有延迟 (并且Galera的 基于行的复制大约要快5倍速)。

Galera集群是局内人

MySQL MMM 是一个局外者—— 对于服务器上实际在发生的事情它是“哑的”。它只作一种检测,并且那就是它所知道的所有该如何反应的事情。

Galera集群是一个“局内人”,所以对每一个节点的内部状态要更机灵,而且不须要人工干预就能够作正确的事情(例如,一个节点同步或未同步,成为一个donor(节点处于为新节点准备或传输集群全量数据状态,对客户端不可用),等等——所有都是自动的)。

当写入节点失败的时候会发生什么呢?

因为用一个Galera集群能够写进任意节点,咱们仍是选择尽可能减小潜在的死锁和只在一个节点写入。为此,咱们使用HAProxy:咱们拥有一个前端供“写入者”节点,另外一个前端供读出以供全部节点实现余额查询。“写入者”经过单个节点发送请求,而其余的节点做为备份。

若是HAProxy检测到“写入者”节点不正常,它当即提拔备份节点中的一个做为“写入者”。MySQL的MMM在这种状况下一般会关掉全部节点之间的通话——HAProxy不会如此。当“写入者”后台更新的时候,咱们可能会丢失一部分请求,但它不会致使不一致的数据集经过服务器,这比瘫痪更糟糕。

咱们不会自动修复失败的节点,不过这没有关系。我主要关注点是确保一个正常的节点在执行写入,HAProxy是作这个的。

修复失效的节点(并让它做为一个新的节点处于在线状态)

当一个节点在标准的MySQL复制的时候失效,你将在再次进行复制的时候把大量的负载集中在一台服务器上(这台服务器不只仅要进行读和写,并且还要承接来自innodbbackupex的负载)。

使用Galera,你可让其中一个节点离线(所以你至少须要三个节点)。这时这个节点就成为供给者节点-对它的写操做将被阻塞。这个节点就经过rsync传输自身的数据给失效的节点(或者新的节点)。而后,供给者节点和失效节点经过辅助队列运行查询而与其余节点保持同步。

一旦这两个节点回归到同步状态,HAProxy将自动的标记它们为启动状态,而后把它们添回道前端。

Galera集群也支持普通的MySQL,所以咱们为何不切换到MariaDB?

切换到MariaDB的理由既有技术缘由也有政治缘由:

  • 易于移植:首先,MariaDB是MySQL的随手可得的替代品。从MySQL 5.1移植到MariaDB,只有Galera服务器5.6能够运行。

  • 性能:咱们有几个包含索引的在性能方面存在问题的查询,后面经过使人惊讶的移植来”修补“这方面的问题。MariaDB彷佛更适合于复杂查询和链接,而Rails上的Ruby也因处理复杂的查询和链接而扬名。MariaDB更适合作查找索引的整个工做,并且正如我前面所说,许多使人烦恼的查询如今已经提速了。咱们彷佛看不到两者在内存使用上有任何使人吃惊的区别。我指望Galera能更多的使用内存,不过若是这么作了,那么Galera就没有任何值得关注的地方了。

  • 社团:MariaDB有很大的驱动力,并且与MySQL相比增长了更多的功能。Oracle对MySQL将来倾注了大量的心血,而MariaDB看起来也存活了好长时间-甚至谷歌正在切换到MariaDB

咱们会再作一次?

绝对地。咱们没有看到有什么缘由不切换到 MariaDB 和 Galera Cluster。

监控 Galera Cluster

25081035_S1or.png

监控 Galera 的一件伟大的事情是它是分层的 - 咱们能够很容易地监视栈的每一部分。咱们使用 Scout 来监视,那意味着咱们仅仅须要去使用下列插件:

  • MariaDB Galera Cluster - 安装在每个 Galera Cluster 结点上去获取关键指标(本地状态,连通性,等)。

  • HAProxy - 为每个代理安装(写入器一次,读取器一次)。

  • URL Monitoring - 检测和 HAProxy 检测的相同的状态URL来决定结点的健康。

TL;DR

直到最近, MySQL MMM 是添加高可用性到 MySQL 的最好的(但坏了的)途径。Galera Cluster 最终为 MySQL 增长了真实的高可用性,主要多亏同步复制。

 

MariaDB做为Mysql的一个分支,在开源项目中已经普遍使用,例如大热的openstack,因此,为了保证服务的高可用性,同时提升系统的负载能力,集群部署是必不可少的。

MariaDB Galera Cluster 介绍

MariaDB集群是MariaDB同步多主机集群。它仅支持XtraDB/ InnoDB存储引擎(虽然有对MyISAM实验支持 - 看wsrep_replicate_myisam系统变量)。

主要功能:

  • 同步复制

  • 真正的multi-master,即全部节点能够同时读写数据库

  • 自动的节点成员控制,失效节点自动被清除

  • 新节点加入数据自动复制

  • 真正的并行复制,行级

  • 用户能够直接链接集群,使用感觉上与MySQL彻底一致

优点:

  • 由于是多主,因此不存在Slavelag(延迟)

  • 不存在丢失事务的状况

  • 同时具备读和写的扩展能力

  • 更小的客户端延迟

  • 节点间数据是同步的,而Master/Slave模式是异步的,不一样slave上的binlog多是不一样的

技术:

Galera集群的复制功能基于Galeralibrary实现,为了让MySQL与Galera library通信,特别针对MySQL开发了wsrep API。

Galera插件保证集群同步数据,保持数据的一致性,靠的就是可认证的复制,工做原理以下图: 

当客户端发出一个commit的指令,在事务被提交以前,全部对数据库的更改都会被 write-set 收集起来,而且将write-set 纪录的内容发送给其余节点。

write-set 将在每一个节点进行认证测试,测试结果决定着节点是否应用write-set更改数据。

若是认证测试失败,节点将丢弃 write-set ;若是认证测试成功,则事务提交。

1 安装环境准备

安装MariaDB集群至少须要3台服务器(若是只有两台的话须要特殊配置,请参照官方文档

在这里,我列出试验机器的配置:

操做系统版本:centos7

node4:10.128.20.16 node5:10.128.20.17 node6:10.128.20.18

以第一行为例,node4为 hostname ,10.128.20.16为 ip ,在三台机器修改 /etc/hosts 文件,个人文件以下:

10.128.20.16 node4
10.128.20.17 node5
10.128.20.18 node6

为了保证节点间相互通讯,须要禁用防火墙设置(若是须要防火墙,则参照官方网站增长防火墙信息设置)

在三个节点分别执行命令:

systemctl stop firewalld

而后将 /etc/sysconfig/selinux 的 selinux 设置成 disabled ,这样初始化环境就完成了。

2 安装 MariaDB Galera Cluster

[root@node4 ~]# yum install -y mariadb mariadb-galera-server mariadb-galera-common galera rsync
[root@node5 ~]# yum install -y mariadb mariadb-galera-server mariadb-galera-common galera rsync
[root@node6 ~]# yum install -y mariadb mariadb-galera-server mariadb-galera-common galera rsync

3 配置 MariaDB Galera Cluster

初始化数据库服务,只在一个节点进行

[root@node4 mariadb]# systemctl start mariadb
[root@node4 mariadb]# mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user.  If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none):
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.

Set root password? [Y/n]
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] n
 ... skipping.

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] n
 ... skipping.

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!

关闭数据库,修改 /etc/my.cnf.d/galera.cnf

[root@node4 mariadb]# systemctl stop mariadb
[root@node4 ~]# vim /etc/my.cnf.d/galera.cnf

修改如下内容:

[mysqld]
......
wsrep_provider = /usr/lib64/galera/libgalera_smm.so
wsrep_cluster_address = "gcomm://node4,node5,node6"
wsrep_node_name = node4
wsrep_node_address=10.128.20.16
#wsrep_provider_options="socket.ssl_key=/etc/pki/galera/galera.key; socket.ssl_cert=/etc/pki/galera/galera.crt;"

提示:若是不用ssl的方式认证的话,请把 wsrep_provider_options 注释掉。

将此文件复制到node五、node6,注意要把 wsrep_node_name 和 wsrep_node_address 改为相应节点的 hostname 和ip。

4 启动 MariaDB Galera Cluster 服务

[root@node4 ~]# /usr/libexec/mysqld --wsrep-new-cluster --user=root &

观察日志:

[root@node4 ~]# tail -f /var/log/mariadb/mariadb.log

150701 19:54:17 [Note] WSREP: wsrep_load(): loading provider library 'none'
150701 19:54:17 [Note] /usr/libexec/mysqld: ready for connections.
Version: '5.5.40-MariaDB-wsrep'  socket: '/var/lib/mysql/mysql.sock'  port: 3306  MariaDB Server, wsrep_25.11.r4026

出现 ready for connections ,证实咱们启动成功,继续启动其余节点:

[root@node5 ~]# systemctl start mariadb
[root@node6 ~]# systemctl start mariadb

能够查看 /var/log/mariadb/mariadb.log,在日志能够看到节点均加入了集群中。

警告:--wsrep-new-cluster 这个参数只能在初始化集群使用,且只能在一个节点使用。

5 查看集群状态

咱们能够关注几个关键的参数:

wsrep_connected = on 连接已开启

wsrep_local_index = 1 在集群中的索引值

wsrep_cluster_size =3 集群中节点的数量

wsrep_incoming_addresses = 10.128.20.17:3306,10.128.20.16:3306,10.128.20.18:3306 集群中节点的访问地址

6 验证数据同步

咱们在 node4 上新建数据库 galera_test ,而后在 node5 和 node6 上查询,若是能够查询到 galera_test 这个库,说明数据同步成功,集群运行正常。

[root@node4 ~]# mysql  -uroot  -proot  -e  "create database galera_test"
[root@node5 ~]# mysql  -uroot  -proot  -e  "show databases"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| galera_test        |
| mysql              |
| performance_schema |
+--------------------+
[root@node6 ~]# mysql  -uroot  -proot  -e  "show databases"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| galera_test        |
| mysql              |
| performance_schema |
+--------------------+

至此,咱们的 MariaDB Galera Cluster 已经成功部署。

 

http://www.javashuo.com/article/p-rlqgdmcw-k.html