社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  DATABASE

MySQL高可用架构案例篇:UCloud最佳实践

IT大咖说 • 5 年前 • 510 次点击  

MySQL高可用架构案例篇:UCloud最佳实践

内容来源:2017年7月22日,UCloud高级研发工程师王松磊在“饿了么技术沙龙【第九弹】上海研发中心·运维专场”进行《数据库高可用架构》演讲分享。IT 大咖说(微信id:itdakashuo)作为独家视频合作方,经主办方和讲者审阅授权发布。

阅读字数:3280 | 9分钟阅读

嘉宾演讲视频及PPT回顾:suo.im/2obXuQ

摘要

分享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的Master.info

Master.info记录的IO线程复制的相关信息,记录的信息与show slave status显示的IO线程相关含义相同。用于在MySQL启动时,装载复制IO线程的相关信息,保证重启后复制仍能继续进行。

对于非auto_position的Master.info在change master时,会记录主机的IP、端口、用户名等信息到master.info中,IO线程在记录relay log后更新master.info中的记录master的文件和位置。

当意外宕机的时候,可能发生记录了relay log但是没有更新master.info的情况。

非GTID的Relay-log.info

Relay-log.info记录着SQL线程复制相关信息,记录的信息与show slave status显示的SQL线程相关信息含义相同。用于在MySQL启动时装载复制的相关信息,保证重启后复制仍能够继续进行。

当发生宕机,复制重新启动后,会存在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做日志记录。

Master.info和Relay_log.log

这里主要是解决宕机恢复后复制起点问题。建议尽量使用GTID作为复制的依据,取代较早的文件和位置,slave宕机恢复后,对relay log、binglog和当前复制的进度做较完善的校检。

重复GTID的忽略

这方面大多是人为造成的。所以建议在重做主从后,做完整的复制进度检查,增加简单的审计表,对敏感的操作做记录,如reset master、change master等,并对比master和slave的敏感操作记录。



今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/JobRHGI2Kk
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/12545
 
510 次点击