内容来源:2017年7月22日,UCloud研发工程师王松磊在“饿了么技术沙龙【第九弹】上海研发中心·运维专场”进行《数据库高可用架构》演讲分享。IT 大咖说作为视频合作方,经主办方和讲者审阅授权发布。
阅读字数:3280 | 9分钟阅读
嘉宾演讲视频及PPT回顾:http://t.cn/EVhOCOP
摘要
分享UCloud在数据库高可用上的佳实践。首先介绍MYSQL常见的高可用方式,并分析其存在的问题,然后给出UCloud对此的思考和解决方法。
MySQL常见的数据同步方式
MySQL数据同步方式大体分为两大类,类是使用MySQL传统的异步或半同步复制协议,比较典型的有MHA+MySQL或者**Proxy+MySQL。第二类是使用分布式协议,这方面有Group Replication或Galera Cluster+MySQL。
原生的异步或半同步复制协议
首先来看下原生的异步或半同步复制协议。它通过Master的dump线程与Slave的IO线程进行交互,当binglog发生更新时,将Binlog传输到Slave,实现Master和Slave的数据同步。
然后还可以通过使用不同的拓扑结构来实现不同的功能,如master和多个Slave做数据同步,如多个master相互搭建复制。目前绝大多数的Proxy产品都是使用MySQL的原生复制作为数据同步方式。
分布式协议做数据同步
这种是近几年新兴的同步方式,它的分布式算法是通过选举的方式,解决在分布式的系统中如何就某一决议达成一致的问题。
使用分布式协力做数据同步的方式,在近两年出现了一系列开源或闭源的产品,如腾讯的phxsql、perconna和mariadbde galera插件、社区版的Group、Tidb等。分布式协议通常需要至少三节点的MySQL,相比于原生的MySQL复制提供了更可靠的保证数据一致性的方法,但是由于技术教新(相比于MySQL复制),暂时并没有替代原生复制成为成为绝大多数MySQL数据库同步方式。
MySQL双节点架构
经典的双节点架构有一个VIP接入某一个Proxy,然后下端接一主一从两个节点,从节点做一个数据总集的节点,以防止当主节点挂掉后,服务仍然可以使用,当然也可以作为备份来用。
这种架构使用binglog这种二进制日志的方式来做主从同步,采用半同步进行复制,Proxy同一时间只接入有一个节点,另外还可以根据需求选择是否使用GTID或进行拓扑结构的扩展。
当发生异常情况,例如Master发生宕机后,Proxy会将业务切换到Slave,宕机恢复后,再将业务回切并进行数据回补,或者使用恢复后的Master作为新的Slave,重新搭建复制。
MySQL复制常见问题
上图时序图可以从中间分开,左边是主节点,右边是从节点。主库任何的事务结束后都会同步到从库,保证数据的一致性。
退化为异步复制
主库在发送binglog的时候会等待从库的应答,而没有接受到应答就会出现超时问题。这就会造成下一个事务到达的时候主库就不会再应答了,也就我们说的退化,从半同步复制退化到异步复制。退化之后数据的一致性就会得不到保证。
退化的复制是可以恢复为半同步复制的。每个事务提交时,会在半同步插件记录当前记录的binglog的文件名和位置。IO线程在记录relay log完成后,会将relay log对应的主库的binglog的文件和位置发送给。Dump线程在接受应答后,会对比Slave发送的应答和半同步插件记录的内容,如果Slave发送的文件和位置要大于等于半同步插件中记录的内容,那么恢复半同步复制。
发生意外宕机
从写入binglog到通知Dump线程阶段如果发生意外宕机就会造成主库和从库数据不一致。
这种不一致只是在master完成了,但是没来得及复制slave的数据库操作。这些操作在业务看来是执行失败的数据库操作。但是在主库宕机恢复后,这些数据库操作会被recovery机制作为成功的数据库操作来处理,同时binglog是存在的,但是并没有复制到slave。
如果发生了业务切换,继续在slave执行数据库操作,那么在一些特性的场景下,如果master当即回复,可能造成复制失败的情况。
非auto_position的http://Master.info
http://Master.info记录的IO线程复制的相关信息,记录的信息与show slave status显示的IO线程相关含义相同。用于在MySQL启动时,装载复制IO线程的相关信息,保证重启后复制仍能继续进行。
对于非auto_position的http://Master.info在change master时,会记录主机的IP、端口、用户名等信息到http://master.info中,IO线程在记录relay log后更新http://master.info中的记录master的文件和位置。
当意外宕机的时候,可能发生记录了relay log但是没有更新http://master.info的情况。
非GTID的http://Relay-log.info
http://Relay-log.info记录着SQL线程复制相关信息,记录的信息与show slave status显示的SQL线程相关信息含义相同。用于在MySQL启动时装载复制的相关信息,保证重启后复制仍能够继续进行。
当发生宕机,复制重新启动后,会存在http://relay-log.info中记录的信息要晚于真正执行relay log的情况。SQL线程启动时,可能读取到已经执行过的relay.log。
这是如果开启了GTID,重复的GTID会被过滤,而没有开启,发生重复执行的情况,可能导致复制错误。
重复GTID的忽略
GTID为全局标示符,与事务一一对应的,master的事务对应的GTID不会因为复制到Slave而发生改变,级master的事务复制到slave,被sql重现后,记入Slave bining中的事务对应的GTID仍然为master的gtid。
相同的GTID对应的事务不会被重复复制到Slave,slave对于执行过的gtid也不会重复执行。
在重做主从或者误操作的情况下,由于GTID不会重复执行,所以可能会导致master和slave的数据差异。
复制问题的解决方法
退化为异步复制的解决方案
异步复制阶段的宕机问题是主要因素,解决这一问题的主要思路是减少异步复制的存在时间。
可以采用增加半同步的超时时间,牺牲一定的可用性来保障数据的一致性。也可以通过增加新复制通道,只记录文件和位置,并且不退化,只重连,保证复制正常的情况下一直存在一条半同步复制。增加异步和同步共存的复制方式也是一个方案。
发生意外宕机解决方案
针对这一问题,应该避免进行重复的操作,以及在MySQL-5.6以前的版本使用自增ID。对于recovery机制进行优化,通过配置或者其他方式连接原slave,读取master宕机时的复制进度。记录binglog的树屋,如果没有同步到Slave,仍然事务回滚,回滚后对binglog做truncate处理,另外还需对删除的binglog做日志记录。
http://Master.info和Relay_log.log
这里主要是解决宕机恢复后复制起点问题。建议尽量使用GTID作为复制的依据,取代较早的文件和位置,slave宕机恢复后,对relay log、binglog和当前复制的进度做较完善的校检。
重复GTID的忽略
这方面大多是人为造成的。所以建议在重做主从后,做完整的复制进度检查,增加简单的审计表,对敏感的操作做记录,如reset master、change master等,并对比master和slave的敏感操作记录。
今天的分享就到这里,喜欢本次分享请给我点赞~谢谢大家!有什么问题可以在评论区讨论。
编者:IT大咖说,转载请标明版权和出处