mha高可用master failover数据补齐过程--源码级别

1.master failover not gtid

复制代码
传统方式复制master failover图


 具体过程
复制代码
Phase 1: Configuration Check Phase
    1.init_config(): # 初始化配置
    2.MHA::ServerManager::init_binlog_server: # 初始化binlog server
    3.check_settings()
        a. check_node_version(): # 查看MHA的版本
        b. connect_all_and_read_server_status(): # 检测确认各个Node节点MySQL是否可以连接  
        c. get_dead_servers(),get_alive_servers(),get_alive_slaves():# 再次检测一次node节点的状态  
        d. print_dead_servers(): # 是否挂掉的master是否是当前的master  
        e. MHA::DBHelper::check_connection_fast_util : # 快速判断dead server,是否真的挂了,如果ping_type=insert,不会double check  
        f. MHA::NodeUtil::drop_file_if($_failover_error_file|$_failover_complete_file): # 检测上次的failover文件    
        g. 如果上次failover的时间在8小时以内,那么这次就不会failover,除非配置了额外的参数   
        h. start_sql_threads_if(): # 查看所有slave的Slave_SQL_Running是否为Yes,若不是则启动SQL thread
            
    4.is_gtid_auto_pos_enabled(): # 判断是否是GTID模式

Phase 2: Dead Master Shutdown Phase..
    1.force_shutdown($dead_master):
        a.stop_io_thread(): # stop所有slave的IO_thread  
        b.force_shutdown_internal($dead_master):
          b_1. master_ip_failover_script: # 如果有这个脚本,则执行里面的逻辑(比如:切换vip)
          b_2. shutdown_script:# 如果有这个脚本,则执行里面的逻辑(比如:Power off 服务器)
            
Phase 3: Master Recovery Phase..
    Phase 3.1: Getting Latest Slaves Phase..
        * check_set_latest_slaves()
            a. read_slave_status(): # 获取所有show slave status 信息
            b. identify_latest_slaves(): # 找到最新的slave是哪个
            c. identify_oldest_slaves(): # 找到最老的slave是哪个
    
    Phase 3.2: Saving Dead Master’s Binlog Phase..
        * save_master_binlog($dead_master);
            -> 如果dead master可以ssh,那么
                b_1_1. save_master_binlog_internal:# 用node节点save_binary_logs脚本拷贝相应binlog到manager  
                    diff_binary_log # 生产差异binlog日志
                b_1_2. file_copy: # 将差异binlog拷贝到manager节点的 manager_workdir目录下
                
            -> 如果dead master不可以ssh
               b_1_3. # 那么差异日志就会丢失    
    
    Phase 3.3: Determining New Master Phase..
        b. 如果GTID auto_pos没有打开,调用find_latest_base_slave()
            b_1. find_latest_base_slave_internal: # 寻找拥有所有relay-log的最新slave,如果没有,则failover失败  
                    b_1_1. find_slave_with_all_relay_logs: 
                            b_1_1_1. apply_diff_relay_logs: # 查看最新的slave是否有其他slave缺失的relay-log 
                            
        c. select_new_master: # 选举new master
            c_1. MHA::ServerManager::select_new_master: 
               #If preferred node is specified, one of active preferred nodes will be new master.
               #If the latest server behinds too much (i.e. stopping sql thread for online backups), we should not use it as a new master, but we should fetch relay log there
               #Even though preferred master is configured, it does not become a master if it's far behind
               get_candidate_masters(): # 获取配置中候选节点
               get_bad_candidate_masters(): # 以下条件不能成为候选master
                   # dead server
                   # no_master >= 1
                   # log_bin=0
                   # oldest_major_version=0
                   # check_slave_delay: # 检查是否延迟非常厉害(可以通过设置no_check_delay忽略)
                       {Exec_Master_Log_Pos} + 100000000 # 只要binlog position不超过100000000 就行 
                       
        选举流程: 先看candidate_master,然后找 latest slave, 然后再随机挑选
        
    Phase 3.3(3.4): New Master Diff Log Generation Phase..
        * recover_master_internal
            recover_relay_logs: # 判断new master是否为最新的slave,如果不是,则生产差异relay logs,并发送给新master
            recover_master_internal: # 将之前生产的dead master上的binlog传送给new master
            
    Phase 3.4: Master Log Apply Phase..
        * apply_diff:
            a. wait_until_relay_log_applied:  # 直到new master完成所有relay log,否则一直等待  
            
            b. 判断Exec_Master_Log_Pos == Read_Master_Log_Pos, # 如果不等,那么生产差异日志:
                save_binary_logs --command=save 
                
            c. apply_diff_relay_logs --command=apply:# 对new master进行恢复    
                c_1. exec_diff:Exec_Master_Log_Pos和Read_Master_Log_Pos的差异日志 # 这是在应用new master自己还未执行的relay log
                c_2. read_diff:new master与lastest slave的relay log的差异日志 # 这是应用拥有最多dead master的slave的relay log, 因为new master不一定是拥有dead master最多的数据。
                c_3. binlog_diff:lastest slave与daed master之间的binlog差异日志 # 
                
        * 如果设置了master_ip_failover_script脚本,那么会执行这里面的脚本(一般用来漂移vip)
        * disable_read_only(): 允许new master可写
                
Phase 4: Slaves Recovery Phase..
    # recover_slaves_internal

    Phase 4.1: Starting Parallel Slave Diff Log Generation Phase..     
        recover_all_slaves_relay_logs: # 生成Slave与New Slave之间的差异日志,并将该日志拷贝到各Slave的工作目录下

    Phase 4.2: Starting Parallel Slave Log Apply Phase..
        * recover_slave: # 对每个slave进行恢复,跟以上Phase 3.4: Master Log Apply Phase中的 apply_diff一样
        * change_master_and_start_slave:# 重新指向到new master,并且start slave
        
Phase 5: New master cleanup phase..
    # reset_slave_on_new_master
    在new master上执行reset slave all;
复制代码

 总结:

复制代码
生成差异binlog:
    如果dead master可以ssh:
        传统方式复制通过node节点上的save_binary_logs脚本从dead master上保存binlog,通过生成差异binlog日志,将差异binlog拷贝到manager节点的 manager_workdir目录下  
        
    如果dead master不可以ssh
        那么差异日志就会丢失,也就是会丢失数据。
        
选主:
    以下条件不能成为候选master
        # dead server
        # no_master >= 1
        # log_bin=0
        # oldest_major_version=0
        # check_slave_delay

生成差异relay log:
    判断new master是否为最新的slave,如果不是,则生产差异relay logs,并发送给新master
    2.将之前生产的dead master上的binlog传送给new master
复制代码

 pass

复制代码

2.master failover gtid

复制代码
gtid复制方式 mha failover 流程图

具体过程

复制代码
Phase 1: Configuration Check Phase
    1.init_config(): # 初始化配置
    2.MHA::ServerManager::init_binlog_server: # 初始化binlog server
    3.check_settings()
        a. check_node_version(): # 查看MHA的版本
        b. connect_all_and_read_server_status(): # 检测确认各个Node节点MySQL是否可以连接  
        c. get_dead_servers(),get_alive_servers(),get_alive_slaves():# 再次检测一次node节点的状态  
        d. print_dead_servers(): # 是否挂掉的master是否是当前的master  
        e. MHA::DBHelper::check_connection_fast_util : # 快速判断dead server,是否真的挂了,如果ping_type=insert,不会double check  
        f. MHA::NodeUtil::drop_file_if($_failover_error_file|$_failover_complete_file): # 检测上次的failover文件    
        g. 如果上次failover的时间在8小时以内,那么这次就不会failover,除非配置了额外的参数   
        h. start_sql_threads_if(): # 查看所有slave的Slave_SQL_Running是否为Yes,若不是则启动SQL thread
            
    4.is_gtid_auto_pos_enabled(): # 判断是否是GTID模式

Phase 2: Dead Master Shutdown Phase..
    1.force_shutdown($dead_master):
        a.stop_io_thread(): # stop所有slave的IO_thread  
        b.force_shutdown_internal($dead_master):
          b_1. master_ip_failover_script: # 如果有这个脚本,则执行里面的逻辑(比如:切换vip)
          b_2. shutdown_script:# 如果有这个脚本,则执行里面的逻辑(比如:Power off 服务器)
            
Phase 3: Master Recovery Phase..
    Phase 3.1: Getting Latest Slaves Phase..
        * check_set_latest_slaves()
            a. read_slave_status(): # 获取所有show slave status 信息
            b. identify_latest_slaves(): # 找到最新的slave是哪个
            c. identify_oldest_slaves(): # 找到最老的slave是哪个
    
    Phase 3.2: Saving Dead Master’s Binlog Phase..
        * save_master_binlog($dead_master);
            -> 如果dead master可以ssh,那么
                b_1_1. save_master_binlog_internal:# 用node节点save_binary_logs脚本拷贝相应binlog到manager  
                    diff_binary_log # 生产差异binlog日志
                b_1_2. file_copy: # 将差异binlog拷贝到manager节点的 manager_workdir目录下
                
            -> 如果dead master不可以ssh
               b_1_3. # 那么差异日志就会丢失    
    
    Phase 3.3: Determining New Master Phase..
        b. 如果GTID auto_pos没有打开,调用find_latest_base_slave()
            b_1. find_latest_base_slave_internal: # 寻找拥有所有relay-log的最新slave,如果没有,则failover失败  
                    b_1_1. find_slave_with_all_relay_logs: 
                            b_1_1_1. apply_diff_relay_logs: # 查看最新的slave是否有其他slave缺失的relay-log 
                            
        c. select_new_master: # 选举new master
            c_1. MHA::ServerManager::select_new_master: 
               #If preferred node is specified, one of active preferred nodes will be new master.
               #If the latest server behinds too much (i.e. stopping sql thread for online backups), we should not use it as a new master, but we should fetch relay log there
               #Even though preferred master is configured, it does not become a master if it's far behind
               get_candidate_masters(): # 获取配置中候选节点
               get_bad_candidate_masters(): # 以下条件不能成为候选master
                   # dead server
                   # no_master >= 1
                   # log_bin=0
                   # oldest_major_version=0
                   # check_slave_delay: # 检查是否延迟非常厉害(可以通过设置no_check_delay忽略)
                       {Exec_Master_Log_Pos} + 100000000 # 只要binlog position不超过100000000 就行 
                       
        选举流程: 先看candidate_master,然后找 latest slave, 然后再随机挑选
        
    Phase 3.4 New Master Diff Log Generation Phase..
      * recover_master_gtid_internal:
          wait_until_relay_log_applied: # 候选master等待所有relay-log都应用完  
          # 如果候选master不是最新的slave:
              $latest_slave->wait_until_relay_log_applied($log): # 最新的slave应用完所有的relay-log
              change_master_and_start_slave : # 让候选master同步到latest master,追上latest slave
              # 获取候选master此时此刻的日志信息,以便后面切换
        
          # 如果候选master是最新的slave:
              # 获取候选master此时此刻的日志信息,以便后面切换    
            
          save_from_binlog_server:
              # 如果配置了binlog server,那么在binlogsever 能连的情况下,将binlog 拷贝到Manager,并生成差异日志diff_binlog(save_binary_logs --command=save)
            
          apply_binlog_to_master:
              Applying differential binlog:#  应用差异的binlog到new master

        
Phase 4: Slaves Recovery Phase..
    Phase 4.1: Starting Slaves in parallel..
        * recover_slaves_gtid_internal:
            change_master_and_start_slave: # 因为master已经恢复,那么slave直接change master auto_pos=1 的模式就可以恢复  
            gtid_wait:# 用此等待同步全部追上
            
Phase 5: New master cleanup phase..
    # reset_slave_on_new_master
    在new master上执行reset slave all;
复制代码

 

 



pass
复制代码

 

 

 

pass

 

posted @   thep0st  阅读(99)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类
点击右上角即可分享
微信分享提示