Date

在传统关系型数据库中有一个非常重要的特性就是high availability,简称高可用。简而言之就是如果一台服务器坏了,仍然系统要保证可用性,通常的实现方式有以下几种,

1: 使用一主一备或多备的方式来同步数据;
2: 使用共享磁阵的方式共享数据;
3: 使用分布式文件系统来保证数据的安全;

本篇博客只探讨单机数据库中的高可用,对于分布式数据库中的高可用可以到下次再探讨。

通常单机数据库采用方法1来实现high availability,一台服务器作为主机,另一台作为热备。主机实时将事务日志xlog同步给备机,备机将日志写盘后回复主机写入的位置(例如LSN,一个uint64位顺序递增数值,并假设它永远用不完),主机将事务等待队列中小于该LSN的事务全部提交。

主备复制流程如图1所示:

Note left of Primary: start transaction
Note left of Primary: flush xlog to disk
Primary->Standby: send xlog to Standby
Note right of Standby: flush xlog to disk
Standby->Primary: reply xlog location to Primary
Note left of Primary: commit transaction

使用主备方案时,通常会有一套第三方的集群管理软件来监测主备机的状态,当主机宕机时,第三方集群管理软件可以将备机升主,使业务做到不间断。 这样看是完美,然而如果第三方集群管理软件一旦与主机网络断连,误以为主机宕机,让备机升主,此时出现双主,然而由图1可知,主机开始一个事务是先刷写xlog,再发送给备机,当出现双主时,两个主机均会写下日志,此时这一对主备的xlog便出现不一致,即使重启一个主机将其设为备机也无法与新主机同步,因为已经有不一样的xlog日志了。 在PostgreSQL与MySQL数据库中经常会遇到这类问题。当主备设置为同步模式时,可以避免数据一致性的问题,因为没有备机写事务无法提交。

解决这个问题的方法有两个:

1: 修改主机写xlog的顺序,当主机将一个事务产生的xlog发送到备机后,自己再flush磁盘,这样便可以避免双主后的主备xlog不一致。
2: 将备机进行重建,重建分为两种,一种是全量重建,如果主机数据量很大时,全量重建将非常耗时,这并不符合高可用的理念;另一种是增量重建,就是将双主中不一样的xlog开始分析,以一个主机为准,将另一个主机中不一样的xlog进行undo。以PostgreSQL为例,它并没有日志undo机制,因此这个问题在PostgreSQL中一直是个难题。然而最近发布的PG9.5版本中增加了一个工具pg_rewind,可以使用增量build的方式来解决双主的问题。

Comments

comments powered by Disqus