美文网首页
MySQL:MGR节点上线恢复简析

MySQL:MGR节点上线恢复简析

作者: 重庆八怪 | 来源:发表于2021-12-21 11:55 被阅读0次

    仅仅作为自己的学习笔记,不做其他用途。


    一、恢复的主要阶段

    实际上节点的加入会经历几个主要的流程

    • 发起一个Control_notification调用Gcs_xcom_control::retry_do_join连接到种子节点,
      发送加入的请求给xcom线程,xom线程检测到有节点加入后,然后由xcom线程下发Global_view_notification给各个节点(包括加入节点)表示有节点申请加入。
    • 各个节点收到Global_view_notification的消息后,获取本节点的一些信息,比如本节点执行的gtid信息、视图更新后的节点信息等。完成后发送一个信息给xcom线程
      (Cargo_type::CT_INTERNAL_STATE_EXCHANGE)
    • xcom线程下发Data_notification ,交由xcom engine线程处理,主要就是安装视图
    1. 对于现有节点而言,主要更新视图信息,将加入节点的状态更改为recovery
    2. 对于加入节点而言,也是先将自己的状态设置为recovery然后进行恢复。
    • 加入节点恢复完成后,会发送online消息给各个节点,各个节点将节点状态状态
      设置为online。

    在加入的过程中视图版本会加1,由于view change event会封装在一个事务里面,因此
    GTID也会加1,封装的过程主要处于Certification_handler::handle_event中对于view change event的处理。

    二、加入阶段数据恢复的简图

    这里我们主要看看加入节点的恢复流程,这里主要涉及到3个线程的协同工作,用图表示:

    未命名文件.jpg

    本处小结:

    • clone插件只有在GTID差值超过group_replication_clone_threshold参数设置或者恢复库需要的GTID已经在所有节点都清理了才会启用
    • 节点处于recovery状态是比较早的,如果其中流程出错,看到的视图信息依旧是recovery,比如选择donor节点恢复出现问题,这是常见的。
    • 节点上线依赖参数group_replication_recovery_complete_at的设置,默认设置为TRANSACTIONS_APPLIED,如果有大量的事务应用,那么节点上线可能推迟,因此加入节点选择低峰期进行
    • incoming队列的缓存的是否如果过多,可能出现问题。因此加入节点选择低峰期。

    三、代码部分笔记

    
    Gcs_xcom_control::process_control_message
      视图版本+1
      ->Gcs_xcom_control::install_view
        根据新的节点信息建立新的视图
       ->Plugin_gcs_events_handler::on_view_changed
        ->Plugin_gcs_events_handler::handle_joining_members
         -> is_joining == ture
           先学习这个分支
           ->状态在恢复当中 MEMBER_IN_RECOVERY
           update_member_status(
            new_view.get_joined_members(), Group_member_info::MEMBER_IN_RECOVERY,
            Group_member_info::MEMBER_OFFLINE, Group_member_info::MEMBER_END);
           
           ->设置super read only  如果设置出错
           enable_server_read_mode(PSESSION_DEDICATED_THREAD)
           ->如果是多主需要考虑自增是否符合要求
           new_view.get_members().size() > auto_increment_increment
            挂起applier通道----->applier通道处于挂起状态
           ->根据下发的view id进行View_change_packet的构建,并且推送给
             applier通道的pipeline 进行处理 Applier_module.add_view_change_packet 
             View_change_packet *view_change_packet = new View_change_packet(view_id);
             applier_module->add_view_change_packet(view_change_packet);
           ->进行恢复方式的选择
            ->是否使用clone
              recovery_strategy = remote_clone_handler->check_clone_preconditions();
              ->这里根据参数来判定,到底是使用clone还是recovery的方式
           ->如果是clone则新建clone线程
             remote_clone_handler->clone_server 先不考虑clone
           ->如果是recovery则新建recovery线程
             recovery_module->start_recovery(new_view.get_group_id().get_group_id(),new_view.get_view_id().get_representation())
             启动恢复线程,加入的是group id和view id
             见下面的流程
             
    
    进行恢复
    Recovery_module::start_recovery
       ->初始化group_name和view_id
         this->group_name = group_name;
         recovery_state_transfer.initialize(rec_view_id); 
       ->启动新线程
         ->launch_handler_thread
          ->handler->recovery_thread_handle()
          实际调用为Recovery_module::recovery_thread_handle
            ->step0
              
            ->step1
              applier_module->wait_for_applier_complete_suspension(&recovery_aborted);
              等待applier线程的SQL线程应用完现有的relay log的事务,等待是通过收到的GTID
              为最终等待的GTID,完成后进入下一步
            ->step2
              如果只有一个节点,直接进入上线流程,跳过步骤3
            ->step3
              进行recovery流程
              recovery_state_transfer.state_transfer(stage_handler); 
              ->establish_donor_connection
                建立donor的连接
               ->选择donor节点?这里看的和前期看的不同,需要确认
                 这里暴露了一些构建的方法,比如必须是online。
               ->尝试连接donor节点,并且进行不同的报错
                 initialize_donor_connection
               ->进行恢复
                 start_recovery_donor_threads
                 这里带入了view_id,也就是进行恢复结束的位置为view change event的来到
                 ->donor_connection_interface.start_threads(true, true, &view_id, true);
            ->step4     
               ->applier_module->awake_applier_module();
                 唤醒apllier通道继续应用缓存的event,这里前面挂起了applier通道,只是event和消息
                 缓存到了incoming队列。!!!!
               ->Recovery_module::wait_for_applier_module_recovery
                 等待上线,开启循环
                 while (!recovery_aborted && applier_monitoring)
                 ->获取incoming 队列大小
                   applier_module->get_message_queue_size();
                 ->获取每秒恢复应用事务的数量
                 ->如果参数设置为 cerify,则上线条件为
                   ->恢复期间认证为0则继续进行处理
                     根据需要认证的事务总数和已经认证的事务数量进行统计,其中已经认证的事务数量在Certifier::certify的末尾进行增加。
                 ->如果参数设置为applier,则上线条件为
                   ->1.如果剩余需要过pipeline流程的事务,数量少于每秒恢复的事务数量,说明已经很少了,下一秒即可执行完成
                   ->2.如果incoming队列为0 、每秒恢复的事务数量为0 、applier的SQL线程处于空闲状态了
                     如果满足上面其中一个1个条件,进入等待,等待为接受的GTID全部应用完成。
                 ->如果不满足上面的条件则进行循环等待
                   否则进行睡眠 incoming队列大小有关,但最大睡眠 为 100*5000 微秒
                   
             ->step5 
              ->发送节点恢复完成的消息
               notify_group_recovery_end();
               这个消息是发给xcom的,因此是全员消息,应该是通知各个节点更改本节点状态为online
             ->step7
               终止recovery线程
                 
                 
                
                 
    applier_module->add_view_change_packet(view_change_packet);       
       xcom engine推送view change packet给 applier进行pipeline处理
        
    Applier_module::applier_thread_handle
       -> packet_application_error = apply_view_change_packet((View_change_packet *)packet, fde_evt, cont);
        -> Applier_module::apply_view_change_packet
          -> Applier_module::inject_event_into_pipeline
            ->Event_cataloger::handle_event
              ->Event_handler::next
                ->Certification_handler::handle_event
                  -> Certification_handler::extract_certification_info
                    ->Certification_handler::log_view_change_event_in_order
                      ->Certification_handler::inject_transactional_events
                         生成一个gtid事务,包含事务的所有event,并且会分配gtid
                         ->Event_handler::next
    

    参考:
    https://zhuanlan.zhihu.com/p/40627399

    相关文章

      网友评论

          本文标题:MySQL:MGR节点上线恢复简析

          本文链接:https://www.haomeiwen.com/subject/mtcxqrtx.html