引言:
AliCloudDB HA系统是为阿里云 mysql,sqlserver,pgsql 三大数据库提供实例高可用的一整套技术方案,确保系统能够在故障中快速恢复。同时HA 也满足日常运维管理中涉及到主备切换的需求。由于mysql 在业内使用最为广泛,所以本系列先介绍mysql实例高可用的相关技术。基本架构:
目前使用最为广泛的实例架构是采用一主一备 share-nothing 的结构。数据链路支持RLB + dbnode 与 RLB + proxy + dbnode 两种。为简便起见,本文以proxy 链路,引擎为innodb 的实例为例介绍。
主备同步模式支持半同步,与异步两种方式,强同步在mysql5.7中将被支持。
这里简要介绍下三种同步方式的区别:
异步模式:主库收到commit 请求后,依次执行:写redo log prepare,写入binlog,写redo log commit,返回客户端成功。
半同步模式:主库收到commit 后,依次执行 redo log prepare,写binlog/发往备库(两个步骤并行),等待备库回复收到ack,redo log commit,给用户回复成功。
强同步模式:主库收到commit 后,依次执行 redo log prepare,写binlog/发往备库(并行),等待备库fsync到磁盘后,redo log commit ,给用户恢复成功。
以上步骤中,写入redo log 步骤受参数innodb_flush_log_at_trx_commit 影响。 分为0,1,2三种设置,具体含义这里不再赘述。写入binlog 步骤受 sync_binlog 参数影响,具体数字含义,也不再赘述。在两个参数双1 条件下,数据最为安全可靠,性能略有下降。本文假设我们都是设置在双1条件下。
健康检测与切换类型:
健康检测:
HA 使用update 语句对mysql 实例分别通过VIP,物理IP进行检测,这样检测的优点是可以检测从VIP到用户实例主库的整条链路的可用性,同时配合备库的io线程的健康状况,避免HA到用户主库网络故障情况下,主库实例健康时的误判。
HA 每次update 成功时,HA都将主库的时间戳记录到HA当中,同时更新主备库的心跳表,让备库同步主库写入的时间戳,当发生切换时,对比HA中与实例备库中保存的时间戳,可以得到备库大致的延迟。作为主备延迟的判断依据之一。
当实例发生连接超时,连接重置,更新超时,socket超时时都被称作故障切换。
普通切换
当发生mysql实例版本升级,规格升级,刷新实例参数等情况时,需要对实例做主备切换。切换基本步骤如下:
- 预检查主备延迟,如果延迟较大,那么直接退出切换,等待下次切换。
- 如果延迟在一定范围内,那么进入切换流程,调用proxy api 切换VIP 指向备库。Proxy 此时会hold 住用户新的连接和请求,不会访问备库(桥接)。关于桥接的具体详情可以参考proxy 技术方案的文章。
- kill 主库连接,设置read_only参数为ON。等待主库瞬间连接上来的事务结束。
- 读取主库master binlog 的位点信息,等待备库同步到该位点,由于之前进行过预等待所以此步骤不会等待很长时间,根据实际运行中数据观察可以控制在数秒以内。
- 备库打开read_only 为OFF
- 调用proxy api 放开用户连接的请求。整个切换过程不会超过10S,用户会感觉到服务器卡住一小段时间后,恢复正常。
故障切换
mysql实例发生故障的环节可能多种多样,这里仅以主备库采用异步复制模式,并且主库所在主机故障导致的切换为例来讲解基本的故障恢复流程,其他类型的故障后面会再综合介绍。
- 当主库自身发生故障时,HA连接主机后,返回的错误类型是连接超时,或者收到主库返回的rst包,那么进入切换流程。
- 检查备库延迟自身SQL线程延迟,如果有延迟,那么不切换,等待备库应用relaylog。
- 当备库SQL线程没延迟后,尝试连接主库,获取主库master binlog,如果能够获取,那么就等待备库跟上主库到该位点。如果不能获取(一般都是如此),那么对比主备库时间戳,如果时间戳在一定范围内(主备可能存在数据不一致),那么根据用户指定的策略决定是否切换。
A, 如果用户指定可用性优先,那么HA会将用户连接切换至备库,数据可能丢失,已经通报给用户。
B, 如果用户指定可靠性优先,那么不会切换VIP,人工介入重启主库或主实例,或拷贝redo log,修复数据,确保主备一致后,提供服务。
由于异步模式在有主备IO线程延迟情况下可能存在数据丢失,我们数据库内核组专门开发了double binlog 复制方式,用于专门判断在切换时是否存在数据丢失,如果存在,那么可靠性优先条件下不切换,可用性优先条件下可以切换。
在用户指定了半同步模式下,也有可能导致主备数据不一致,但是不会引起数据丢失(数据丢失的定义是用户commit 后收到成功的回复,但是数据库内没有该数据。对于执行超时,或者执行异常,客户端认为是unknown状态,那么数据库可以选择丢弃该事务,或者应用该事务)。Semi-sync条件下,主备故障切换后,备库按照新主库备份集来重新搭建,确保主备数据一致。
其他故障切换:
以上图中各处都有可能发生故障,那么对于不同的故障情况,都要分别逐一考虑,目前HA从整体上已经保证了以上各种故障条件下,可以在用户指定策略下按预期切换。考虑篇幅过长,每种情况的分析放在下次分享中,这里暂不作介绍。
HA 自身高可用与高可靠
HA 通过多台机器采用多MASTER结构平衡负载,每台HA负责该region的一部分实例,并动态平衡,同时如果有一台HA发生故障,那么其他HA机器会争抢该dead HA所负责实例,然后再次平衡负载,实现方法既可以很简单,也可以很复杂, ha 这里由于考虑多单元部署的成本问题,使用metaDB中一个表作为负载均衡器,使用另外一张表作为HA心跳表,同时metaDB 使用一主多备方案,避免单点故障。整体上解决了HA 自身的高可用问题。
总结:
本片主要简单讨论了HA for mysql 异步复制条件下基本切换流程, 没有介绍各种切换方式的优缺点及各种讨论,以及半同步条件,for mssql, for pgsql 条件下的切换,业内其他厂商如何解决数据库可靠性与可用性问题的相关内容。敬请期待。