完全屬於我自己的Blog,運行在我的路由器H218N上.記錄著我想記錄的文字.

05月 10

基于复制的MySQL高可用技术

双Master

双Master是非常常用的高可用拓扑结构。两个Master互相复制数据以保持同步,因为是对称的,所以设置起来非常简单。而双主架构又可细分为Active-Passive模式和Active- Active模式。它们都常常搭配共享存储使用,或者低成本的DRBD技术,可以理解为“网络的RAID”实现。

双主Active-Passive架构

Active-Passive模式的拓扑架构示意图如下:

Active- Passive模式

两台Master彼此互为镜像,并且binlog二进制文件存储在共享磁盘之上。这意味着主Master到备Master的切换速度很快,而且Slave也不需要将binlog的文件和位置进行调整,唯一需要做的便这是CHANGE MASTER了。
在Active-Passive模式的双主架构中,最需要注意的便是脑裂(split-brain syndrome)问题了。造成脑裂很有可能是主Master发生故障进入修复期,此时备Master接管服务。不幸的是心跳线或监听服务也发生了故障,那么当主Master完成修复回来时,备Master无法洞悉这一情况,那么将出现两个Master同时运行,那么很有可能出现数据更新的冲突,导致Slave复制出现脏数据。因此,将竭尽全力避免脑裂的发生。值得庆幸的是DRBD内置已经以优雅的方式解决了脑裂split-brain syndrome问题,而共享存储则依赖于该产品自身的处理方式。

双主Active-Active架构

双Master的Active-Active也很常见,该设计常常用于解决地理位置不同,又想保证快速的响应。例如研发部门在深圳,销售部门在北京,那么对于研发立项的数据自然需要Master架设在深圳,而对于市场用户信息的数据自然需要Master架设在北京。深圳的Master提供研发立项的更新写入服务,并维护了市场用户信息拷贝;而北京的Master提供了市场用户信息的更新写入服务,并维护了研发立项数据的拷贝。因此,避免脑裂问题,实现双Master的Active-Active的一个可行方案便是分配不同的数据库(或者不同的表)给不同的Master。
其示意图如下:

Active- Active

MySQL的半同步模式(Semisynchronous Replication)

我们知道在5.5之前,MySQL的复制其实是异步操作,而不是同步,也就意味着允许主从之间的数据存在一定的延迟,MySQL当初这样设计的目的可能也是基于可用性的考虑,为了保证master不受slave的影响,并且异步复制使得master处于一种性能最优的状态:写完binlog后即可提交而不需要等待slave的操作完成。这样存在一个隐患,当你使用slave作为备份时,如果master挂掉,那么会存在部分已提交的事务未能成功传输到slave的可能,这就意味着数据丢失!

在MySQL5.5版本中,引入了半同步复制模式(Semi-synchronous Replication)能够成功(只是相对的)避免上述数据丢失的隐患。在这种模式下:master会等到binlog成功传送并写入至少一个slave的relay log之后才会提交,否则一直等待,直到timeout(默认10s)。当出现timeout的时候,master会自动切换半同步为异步,直到至少有一个slave成功收到并发送Acknowledge,master会再切换回半同步模式。结合这个新功能,我们可以做到,在允许损失一定的事务吞吐量的前提下来保证同步数据的绝对安全,因为当你设置timeout为一个足够大的值的情况下,任何提交的数据都会安全抵达slave。

mysql5.5 版本支持半同步复制功能(Semisynchronous Replication),但还不是原生的支持,是通过plugin来支持的,并且默认是没有安装这个插件的。不论是二进制发布的,还是自己源代码编译的,都会默认生成这个插件,一个是针对master 的一个是针对slave的,在使用之前需要先安装这俩plugins。
在Master上执行

install plugin rpl_semi_sync_master soname 'semisync_master.so';

在所有Slave上执行

install plugin rpl_semi_sync_slave soname 'semisync_slave.so';

在初次加载插件后,MySQL会将该插件记录到系统表mysql.plugin中,下次启动时系统则会自动加载该插件了,无需再次执行上面的命令。

在my.cnf配置文件里,加入

rpl_semi_sync_master_enabled = 1 /*这行加到Master的配置文件*/
rpl_semi_sync_slave_enabled = 1/*这行加到所有Slave的配置文件*/

这样以后启动MYSQL时会自动开启半同步复制。

循环复制

循环数据库镜像,就是多个数据库A、B、C、D等,对其中任一个数据库的修改,都要同时镜像到其它的数据库里。
出于地理位置的原因,使用循环复制设置3个或更多的服务器的复制是相当实用的.
例如 为整个欧洲用户提供移动电话的运营商的案例.
由于手机用户漫游颇多,可以很方便地为客户注册手机,因此,通过在欧洲的一些战略要低放置数据中心,就有可能快速验证通话数据,也可以在本地注册新的通话.这些更改可以被复制到环中心的所有服务器,最终所有服务器将有准确的计费信息.
在这种情况下,循环复制是一个完美的设置:所有的用户数据都被放置到所有的站点,并且允许在所有的数据中心进行数据更新.

Slave提升的修订

因为Slave往往落后于Master,所以Slave提升的传统方法在大多数情况下是不够用的.
解决方法在以后再说,先说说Master宕机后,slave之间的同步.

对没有提升为master的slave执行以下步骤:

  1. 弄清它执行的最后一个事务.

2.找出被提升的slave的二进制日志中的事务.
3.从被提升的slave上取得事务的binlog位置.
4.未被提升的slave从被提升的slave上的位置开始复制.

为了将每个slave上的最新的事务于被提升的slave的二进制日志中的事件相对应,需要为每个事务加标签,不论谁实行该事务,它都需要被唯一标识,
因此master上的每个事务都可以在被提升的slave的二进制日志中找到.这中类型的标签,成为 global transaction ID.

标签的处理方式主要有两种:

1.扩展应用程序代码来执行必要的语句.
2.调用一个存储过程来执行每个提交并在程序中写标签.

恢复步骤:

  1. 停止slave,获取最后的global transaction ID.
  2. 选择有最高global transaction ID的slave,提升为master.
  3. 使用show master logs ,得到将要被提升的slave 的master位置,同时得到slave的二进制日志.(show master logs 的最后一行于在show master status 中看到的应该是一样的)
  4. 使被提升的slave联机,让其接受更新.
  5. 连接被提升的slave,找到 与未被提升的slave最新的global transaction ID对应的文件位置,记录下来.
  6. 使用步骤5获取到的信息,将未被提升的slave连接到被提升的slave,开始复制.

标签:MySQL, 高可用

还不快抢沙发

添加新评论