`

MySQL 高可用浅析

阅读更多
摘要: 对于多数应用来说,MySQL都是作为最关键的数据存储中心的,所以,如何让MySQL提供HA服务,是我们不得不面对的一个问题。当master当机的时候,我们如何保证数据尽可能的不丢失,如何保证快速的获知master当机并进行相 ...
 
 
对于多数应用来说,MySQL都是作为最关键的数据存储中心的,所以,如何让MySQL提供HA服务,是我们不得不面对的一个问题。当master当机的时候,我们如何保证数据尽可能的不丢失,如何保证快速的获知master当机并进行相应的故障转移处理,都是需要我们好好思考的。这里,笔者将结合这段时间做的MySQL proxy以及toolsets相关工作,说说我们现阶段以及后续会在项目中采用的MySQL HA方案。
 
Replication
要保证MySQL数据不丢失,replication是一个很好的解决方案,而MySQL也提供了一套强大的replication机制。只是我们需要知道,为了性能考量,replication是采用的asynchronous模式,也就是写入的数据并不会同步更新到slave上面,如果这时候master当机,我们仍然可能会面临数据丢失的风险。
 
为了解决这个问题,我们可以使用semi-synchronous replication,semi-synchronous replication的原理很简单,当master处理完一个事务,它会等待至少一个支持semi-synchronous的slave确认收到了该事件并将其写入relay-log之后,才会返回。这样即使master当机,最少也有一个slave获取到了完整的数据。
 
但是,semi-synchronous并不是100%的保证数据不会丢失,如果master在完成事务并将其发送给slave的时候崩溃,仍然可能造成数据丢失。只是相比于传统的异步复制,semi-synchronous replication能极大地提升数据安全。更为重要的是,它并不慢,MHA的作者都说他们在facebook的生产环境中使用了semi-synchronous(这里),所以我觉得真心没必要担心它的性能问题,除非你的业务量级已经完全超越了facebook或者google。在这篇文章里面已经提到,MySQL 5.7之后已经使用了Loss-Less Semi-Synchronous replication,所以丢数据的概率已经很小了。
 
如果真的想完全保证数据不会丢失,现阶段一个比较好的办法就是使用gelera,一个MySQL集群解决方案,它通过同时写三份的策略来保证数据不会丢失。笔者没有任何使用gelera的经验,只是知道业界已经有公司将其用于生产环境中,性能应该也不是问题。但gelera对MySQL代码侵入性较强,可能对某些有代码洁癖的同学来说不合适了:-)
 
我们还可以使用drbd来实现MySQL数据复制,MySQL官方文档有一篇文档有详细介绍,但笔者并未采用这套方案,MHA的作者写了一些采用drdb的问题,在这里,仅供参考。
 
在后续的项目中,笔者会优先使用semi-synchronous replication的解决方案,如果数据真的非常重要,则会考虑使用gelera。
 
Monitor
前面我们说了使用replication机制来保证master当机之后尽可能的数据不丢失,但是我们不能等到master当了几分钟才知道出现问题了。所以一套好的监控工具是必不可少的。
 
当master当掉之后,monitor能快速的检测到并做后续处理,譬如邮件通知管理员,或者通知守护程序快速进行failover。
 
通常,对于一个服务的监控,我们采用keepalived或者heartbeat的方式,这样当master当机之后,我们能很方便的切换到备机上面。但他们仍然不能很即时的检测到服务不可用。笔者的公司现阶段使用的是keepalived的方式,但后续笔者更倾向于使用zookeeper来解决整个MySQL集群的monitor以及failover。
 
对于任何一个MySQL实例,我们都有一个对应的agent程序,agent跟该MySQL实例放到同一台机器上面,并且定时的对MySQL实例发送ping命令检测其可用性,同时该agent通过ephemeral的方式挂载到zookeeper上面。这样,我们可以就能知道MySQL是否当机,主要有以下几种情况:
 
机器当机,这样MySQL以及agent都会当掉,agent与zookeeper连接自然断开
MySQL当掉,agent发现ping不通,主动断开与zookeeper的连接
Agent当掉,但MySQL未当
上面三种情况,我们都可以认为MySQL机器出现了问题,并且zookeeper能够立即感知。agent与zookeeper断开了连接,zookeeper触发相应的children changed事件,监控到该事件的管控服务就可以做相应的处理。譬如如果是上面前两种情况,管控服务就能自动进行failover,但如果是第三种,则可能不做处理,等待机器上面crontab或者supersivord等相关服务自动重启agent。
 
使用zookeeper的好处在于它能很方便的对整个集群进行监控,并能即时的获取整个集群的变化信息并触发相应的事件通知感兴趣的服务,同时协调多个服务进行相关处理。而这些是keepalived或者heartbeat做不到或者做起来太麻烦的。
 
使用zookeeper的问题在于部署起来较为复杂,同时如果进行了failover,如何让应用程序获取到最新的数据库地址也是一个比较麻烦的问题。
 
对于部署问题,我们要保证一个MySQL搭配一个agent,幸好这年头有了docker,所以真心很简单。而对于第二个数据库地址更改的问题,其实并不是使用了zookeeper才会有的,我们可以通知应用动态更新配置信息,VIP,或者使用proxy来解决。
 
虽然zookeeper的好处很多,但如果你的业务不复杂,譬如只有一个master,一个slave,zookeeper可能并不是最好的选择,没准keepalived就够了。
 
Failover
通过monitor,我们可以很方便的进行MySQL监控,同时在MySQL当机之后通知相应的服务做failover处理,假设现在有这样的一个MySQL集群,a为master,b,c为其slave,当a当掉之后,我们需要做failover,那么我们选择b,c中的哪一个作为新的master呢?
 
原则很简单,哪一个slave拥有最近最多的原master数据,就选哪一个作为新的master。我们可以通过show slave status这个命令来获知哪一个slave拥有最新的数据。我们只需要比较两个关键字段Master_Log_File以及Read_Master_Log_Pos,这两个值代表了slave读取到master哪一个binlog文件的哪一个位置,binlog的索引值越大,同时pos越大,则那一个slave就是能被提升为master。这里我们不讨论多个slave可能会被提升为master的情况。
 
在前面的例子中,假设b被提升为master了,我们需要将c重新指向新的master b来开始复制。我们通过CHANGE MASTER TO来重新设置c的master,但是我们怎么知道要从b的binlog的哪一个文件,哪一个position开始复制呢?
 
GTID
为了解决这一个问题,MySQL 5.6之后引入了GTID的概念,即uuid:gid,uuid为MySQL server的uuid,是全局唯一的,而gid则是一个递增的事务id,通过这两个东西,我们就能唯一标示一个记录到binlog中的事务。使用GTID,我们就能非常方便的进行failover的处理。
 
仍然是前面的例子,假设b此时读取到的a最后一个GTID为3E11FA47-71CA-11E1-9E33-C80AA9429562:23,而c的为3E11FA47-71CA-11E1-9E33-C80AA9429562:15,当c指向新的master b的时候,我们通过GTID就可以知道,只要在b中的binlog中找到GTID为3E11FA47-71CA-11E1-9E33-C80AA9429562:15这个event,那么c就可以从它的下一个event的位置开始复制了。虽然查找binlog的方式仍然是顺序查找,稍显低效暴力,但比起我们自己去猜测哪一个filename和position,要方便太多了。
 
google很早也有了一个Global Transaction ID的补丁,不过只是使用的一个递增的整形,LedisDB就借鉴了它的思路来实现failover,只不过google貌似现在也开始逐步迁移到MariaDB上面去了。
 
MariaDB的GTID实现跟MySQL 5.6是不一样的,这点其实比较麻烦,对于我的MySQL工具集go-mysql来说,意味着要写两套不同的代码来处理GTID的情况了。后续是否支持MariaDB再看情况吧。
 
Pseudo GTID
GTID虽然是一个好东西,但是仅限于MySQL 5.6+,当前仍然有大部分的业务使用的是5.6之前的版本,笔者的公司就是5.5的,而这些数据库至少长时间也不会升级到5.6的。所以我们仍然需要一套好的机制来选择master binlog的filename以及position。
 
最初,笔者打算研究MHA的实现,它采用的是首先复制relay log来补足缺失的event的方式,但笔者不怎么信任relay log,同时加之MHA采用的是perl,一个让我完全看不懂的语言,所以放弃了继续研究。
 
幸运的是,笔者遇到了orchestrator这个项目,这真的是一个非常神奇的项目,它采用了一种Pseudo GTID的方式,核心代码就是这个
 
create database if not exists meta;
drop event if exists meta.create_pseudo_gtid_view_event;
delimiter ;;
create event if not exists
  meta.create_pseudo_gtid_view_event
  on schedule every 10 second starts current_timestamp
  on completion preserve
  enable
  do
    begin
      set @pseudo_gtid := uuid();
      set @_create_statement := concat('create or replace view meta.pseudo_gtid_view as select \'', @pseudo_gtid, '\' as pseudo_gtid_unique_val from dual');
      PREPARE st FROM @_create_statement;
      EXECUTE st;
      DEALLOCATE PREPARE st;
    end
;;
delimiter ;
set global event_scheduler := 1;
 
它在MySQL上面创建了一个事件,每隔10s,就将一个uuid写入到一个view里面,而这个是会记录到binlog中的,虽然我们仍然不能像GTID那样直接定位到一个event,但也能定位到一个10s的区间了,这样我们就能在很小的一个区间里面对比两个MySQL的binlog了。
 
继续上面的例子,假设c最后一次出现uuid的位置为s1,我们在b里面找到该uuid,位置为s2,然后依次对比后续的event,如果不一致,则可能出现了问题,停止复制。当遍历到c最后一个binlog event之后,我们就能得到此时b下一个event对应的filename以及position了,然后让c指向这个位置开始复制。
 
使用Pseudo GTID需要slave打开log-slave-update的选项,考虑到GTID也必须打开该选项,所以个人感觉完全可以接受。
 
后续,笔者自己实现的failover工具,将会采用这种Pseudo GTID的方式实现。
 
在《MySQL High Availability》这本书中,作者使用了另一种GTID的做法,每次commit的时候,需要在一个表里面记录gtid,然后就通过这个gtid来找到对应的位置信息,只是这种方式需要业务MySQL客户端的支持,笔者不很喜欢,就不采用了。
 
后记
MySQL HA一直是一个水比较深的领域,笔者仅仅列出了一些最近研究的东西,有些相关工具会尽量在go-mysql中实现。
 
更新
经过一段时间的思考与研究,笔者又有了很多心得与收获,设计的MySQL HA跟先前有了很多不一样的地方。后来发现,自己设计的这套HA方案,跟facebook这篇文章几乎一样,加之最近跟facebook的人聊天听到他们也正在大力实施,所以感觉自己方向是对了。
 
新的HA,我会完全拥抱GTID,比较这玩意的出现就是为了解决原先replication那一堆问题的,所以我不会考虑非GTID的低版本MySQL了。幸运的是,我们项目已经将MySQL全部升级到5.6,完全支持GTID了。
 
不同于fb那篇文章将mysqlbinlog改造支持semi-sync replication协议,我是将go-mysql的replication库支持semi-sync replication协议,这样就能实时的将MySQL的binlog同步到一台机器上面。这可能就是我和fb方案的唯一区别了。
 
只同步binlog速度铁定比原生slave要快,毕竟少了执行binlog里面event的过程了,而另外真正的slaves,我们仍然使用最原始的同步方式,不使用semi-sync replication。然后我们通过MHA监控整个集群以及进行故障转移处理。
 
以前我总认为MHA不好理解,但其实这是一个非常强大的工具,而且真正看perl,发现也还是看的懂得。MHA已经被很多公司用于生产环境,经受了检验,直接使用绝对比自己写一个要划算。所以后续我也不会考虑zookeeper,考虑自己写agent了。
 
http://it.dataguru.cn/article-7076-1.html
分享到:
评论

相关推荐

    MySQL高可用浅析

    MySQL高可用性是确保系统持续稳定运行的关键,尤其是在依赖MySQL作为数据存储中心的应用场景中。本文将探讨如何通过各种技术手段提升MySQL的高可用性,包括复制(Replication)、半同步复制(Semi-Synchronous ...

    Mysql+binlog浅析

    MySQL的binlog是数据库持久化和高可用性策略的关键部分。它记录了所有对数据库的更改,包括INSERT、UPDATE和DELETE等操作,以确保在系统崩溃或数据丢失时能够进行恢复。此外,binlog也是实现主从复制的基础,使得...

    浅析系统架构.rar (mysql开发组的一个资料)

    在《浅析系统架构》中,MySQL开发组可能会详细介绍如何设计和优化数据库系统的架构,以满足高性能、高可用性和可扩展性的需求。 MySQL作为全球广泛使用的开源关系型数据库管理系统,其架构设计至关重要。资料可能...

    浅析MySQL并行复制

    MySQL的主从复制架构旨在确保数据的一致性和高可用性。在传统的单线程复制模式中,从库的SQL_thread仅能顺序应用主库的binlog事件,导致在高TPS(每秒事务数)环境下可能出现主库与从库之间的显著延迟。为解决这个...

    MySQL服务器连接过程浅析

    创建新线程的过程可能涉及到线程缓存,如果线程池中有可用的线程,就复用它,否则创建新的线程。线程创建完成后,服务器继续等待新的连接请求,整个流程循环进行。 总结来说,MySQL服务器的连接过程涉及到多个步骤...

    浅析MySQL的WriteSet并行复制

     岁月更迭中我已经从事MySQL-DBA这个工作三个年头,见证MySQL从“基本可用”,“边缘系统可以用MySQL”,“哦操!你怎么不用MySQL”;  正所谓!“一个数据库的境遇既取决于历史的进程,取决于它的自我奋斗!”,...

    浅析mysql 语句的调度优先级及改变

    MySQL的默认的调度策略可用总结如下:· 写入操作优先于读取操作。· 对某张数据表的写入操作某一时刻只能发生一次,写入请求按照它们到达的次序来处理。· 对某张数据表的多个读取操作可以同时地进行。MySQL允许你...

    浅析电子政务网服务器系统应用的实现(2)分享.pdf

    - 整个电子政务网服务器系统设计满足用户跨平台需求,构建了三大核心集群:WEB服务器负载均衡集群、MySQL高可用数据库服务器集群和高可用负载均衡服务器集群。 - 这种架构增强了系统的稳定性和可用性,确保政务网...

    Innodb存储引擎浅析—事务系统

    ### Innodb存储引擎浅析—...通过以上分析可以看出,InnoDB存储引擎不仅提供了强大的事务处理能力,还通过一系列的优化措施,确保了系统的高可用性和数据的可靠性。这对于需要高性能、高可靠性的应用场景而言至关重要。

    云及数据库行业浅析共10页.pdf.zip

    云数据库提供了易于管理、自动备份、高可用性和可扩展性的优势,帮助企业快速响应业务需求变化。同时,数据库即服务(DBaaS)模型使得数据库的部署和运维更加简便,降低了企业运营成本。 四、行业趋势 1. 数据隐私...

    浅析动态网站建设之后台数据库的选择.pdf

    浅析动态网站建设之后台数据库的选择 动态网站建设的后台数据库选择是一个非常重要的环节,对于动态网站的正常运行和发展起着至关重要的作用。在选择后台数据库时,需要考虑多种因素,包括数据库的类型、性能、安全...

    浅析分布式管理交通平台的应用特点.pdf

    5. 富有弹性的系统架构:分布式管理交通平台采用了高可用性(HA)设计,能够在关键时刻自动恢复服务,保证系统服务的连续性。即便在硬件或操作系统故障的情况下,平台也能在规定时间内发现并恢复,确保大数据平台的...

    浅析海南省技师学院《校园办公自动化(SOA)系统》的设计.rar

    在技术实现上,可能采用Web服务(如SOAP或RESTful API)作为服务接口,使用消息队列(如RabbitMQ或Kafka)实现异步处理,数据库管理系统(如MySQL或Oracle)存储数据,以及使用Spring框架等技术进行服务开发。...

    浅析php学习的路线图

    架构设计则涉及到大型Web应用的设计和开发,如何设计可扩展、高可用的系统。 希望通过这条学习路线图,学习者能够逐渐积累足够的知识和技能,最终能够独立完成Web开发项目,并有能力找到实习工作,甚至成为一名职业...

    Postgresql中国用户大会 2016(PG大象会)所有PPT汇总.zip

    余星-平安壹钱包-浅谈PostgreSQL 高可用架构.pdf 范孝剑-阿里云-PG优化器浅析.pdf 张广舟-阿里云-ApsaraDB for Greenplum介绍.pdf 高金芳-平安科技-PostgreSQL反向代理redis.pdf 张文杰-阿里云-PostgreSQL...

    浅析springcloud 整合 zipkin-server 内存日志监控

    总的来说,SpringCloud与Zipkin-Server的集成,是构建高可用、高性能微服务系统的重要一环。通过实时监控和追踪,开发团队可以快速定位性能瓶颈,提升系统稳定性,从而提供更好的用户体验。同时,这也是一种强大的...

Global site tag (gtag.js) - Google Analytics