MHA フェイルオーバーとオンライン スイッチングのコード分析 少し前に、私の同僚の Shen Longxing が MHA フェイルオーバーとオンライン スイッチングのコード フローをコンパイルしました。彼の同意を得て、ここに転送します。以下本文ですこの記事はMySQL5.5をベースにしているため、GTID関連の内容は含みません。 MHA のマスター/スレーブ切り替えプロセスは、フェイルオーバーとローテーションの 2 つのタイプに分かれており、前者は元のマスターがダウンしているときに適用され、後者はオンラインに切り替えるときに使用されます。以下に、 フェイルオーバー処理プロセスについて説明します MHA::MasterFailover::main() ->do_master_failover フェーズ 1: 構成チェックフェーズ ->check_settings: check_node_version: MHA バージョン情報の表示 connect_ all _and_read_server_status: それぞれを確認ノードの MySQL インスタンスに接続できるかどうか get_dead_servers/get_alive_servers/get_alive_slaves: 各ノードの生存状態と停止状態を再確認します start_sql_threads_if: Slave_SQL_Running が Yes であるかどうかを確認し、そうでない場合は SQL スレッドを開始します フェーズ 2: デッド マスター シャットダウン フェーズ: 私たちにとって、唯一の機能は IO スレッドを停止することです -> Force_shutdown($dead_master): stop_io_thread: すべてのスレーブ IO スレッドが停止します (マスターが停止します) force_shutdown_internal (実際には、設定ファイル内の master_ip_failover_script/shutdown_script を実行することですが、そうでない場合は実行されません): master_ip_failover_script: VIP が設定されている場合は、最初に VIP を切り替えます shutdown_script: シャットダウン スクリプトが設定されている場合、 を実行します フェーズ3:マスターリカバリフェーズ ->フェーズ3.1:最新のスレーブの取得フェーズ(最新のスレーブを取得) read_slave_status:各スレーブのバイナリログファイル/位置を取得します check_slave_status : 「SHOW SLAVE STATUS」を呼び出して、スレーブの次の情報を取得します: Slave_IO_State、Master_Host、 Master_Port、Master_User、 Slave_IO_Running、Slave_SQL_Running、 Master_Log_File、 Pos、 Relay_Master_Log_File、Last_Errno、 Last_Error、Exec_Master_Log_Pos、 Relay_Log_File、Relay_Log_Pos、 Seconds_Behind_Master、Retrieved_Gtid_Set、 Executed_Gtid_Set、Auto_Position Replicate_Do_DB、Replicate_Ignore_DB、Replicate_Do_Table、 Replicate_Ignore_Table、Replicate_Wild_Do_Table、 Replicate_Wild_Ignore_Table identify_latest_slaves : 各スレーブのMaster_Log_File/Read_Master_Log_Posを比較して最新のスレーブを見つけます identify_oldest_slaves: 各スレーブのMaster_Log_File/Read_Master_Log_Posを比較して最も古いスレーブを見つけます -> フェーズ 3 2: デッド マスターのビンログの保存フェーズ : save_master_binlog: デッド マスターが ssh 経由で接続できる場合は、次のブランチに移動します: save_master_binlog_internal: (ノード ノードの save_binary_logs スクリプトを使用してコピーを作成します)デッドマスター上) save_binary_logs --command=save - -start_file=mysql-bin.000281 --start_pos=107 --binlog_dir=/opt/mysql/data/binlog --output_file=/opt/mha/log /saved_master_binlog_from_10.27.177.245_3306_20160108211857.binlog --handle_raw_binlog=1 -- disable_log_bin=0 --manager_version=0.55 generate_diff_binary_log: concat_all_binlogs_from : dump_binlog: binmodeを使用して、binlogファイルをターゲットファイルにダンプするだけですread dump_binlog_header_fde : 0からposition-1まで読み取ります dump_binlog_from_pos: 位置から開始して、binlogファイルをターゲットファイルにダンプします file_copy: ファイルコピーは、上記で生成されたbinlogファイルをmanager_workdirディレクトリにコピーすることです管理ノードの デッドマスターが ssh 経由でログインできない場合、スレーブと同期していないマスター上の txn が失われます -> フェーズ 3.3: 新しいマスターフェーズを決定する find_latest_base_slave: find_latest_base_slave_internal: pos_cmp( $old est_mlf, $oldest_mlp, $latest_mlf, $latest_mlp ) 最新/最も古いスレーブのバイナリの位置が同じかどうかを判断します。同じです、そこにリレーログを同期する必要はありません apply_diff_relay_logs --command=find --latest 最新のスレーブに最も古いリレーログが欠落しているかどうかを確認し、欠落している場合は続行します。そうでない場合は、フェイルオーバーが失敗します。これは非常に簡単で、ファイル/位置が見つかるまで逆の順序で最新のスレーブのリレー ログ ファイルを読み取ることです。 Select_new_master: 新しいマスターを選択します。新しいマスターになります 最新のサーバーがあまりにも遅れている場合(つまり、オンラインバックアップのSQLスレッドを停止する場合)、 それを新しいマスターとして使用すべきではなく、リレーログを取得する必要があります 。マスターは設定されていますが、大幅に遅れている場合はマスターになりません。 get_candidate_masters: は設定ファイル内でcandidate_master>0で設定されたノードです get_bad_candidate_masters: # 次のサーバーは設定できませんmaster: # - デッドサーバー # - conf ファイル (つまり、DR サーバー) に no_master を設定します # - log_bin が無効になります # - メジャー バージョンが最も古くありません # - レプリケーションの遅延が大きすぎます (スレーブとマスター間のビンログ位置のギャップが 100000000 を超えています) 最新のリレー ログ イベントを受信した候補マスター スレーブから検索します 見つからない場合: すべてのcandidate_masterスレーブから検索 見つからない場合: 最新のリレーログイベントを受信したすべてのスレーブから検索 見つからない場合: すべてのスレーブから検索 -> フェーズ 3.4: 新しいマスター差分ログ生成フェーズ recover_relay_logs: 新しいマスターが最新のスレーブであるかどうかを確認します。そうでない場合は、apply_diff_relay_logs -- コマンドを使用して差分ログを生成します。 そしてそれを新しい新しいマスターに送信しますrecover_master_internal:3.2で生成されたdaedマスターのバイナリログを新しいマスターに送信します ->フェーズ3.5:マスターログ適用フェーズ Recovery_slave:apply_diff : 0. wait_until_relay_log_applied、新しいマスターがリレーログの実行を完了するまで待ちます1. Exec_Master_Log_Pos == Read_Master_Log_Pos,を決定します。等しくない場合は、save_ を使用します。 binary_logs --command=保存先差分ログを生成します2. apply_diff_relay _logs コマンドを呼び出し、新しいマスターがリカバリを実行します: 2.1 リカバリログは 3 つの部分に分かれています: exec_diff: Exec_Master_Log_Pos と Read_Master_Log_Pos の差分 read_diff: 新しいマスターと最後のスレーブのリレー ログの差分 binlog_diff: daed マスターとの最新のスレーブ ビンログの差分実際、apply_diff_relay_logs は、回復するために mysqlbinlog コマンドを呼び出すことです//If vip が設定されている場合、vip のフェイルオーバーを実行するには master_ip_failover_script を呼び出す必要があります フェーズ 4: スレーブ回復フェーズ->フェーズ 4.1: 並列スレーブ差分ログ生成フェーズの開始スレーブ間の差分ログを生成しますおよび新しいスレーブを選択し、ログを各スレーブの作業ディレクトリにコピーします。 -> フェーズ4.2: 並列スレーブログ適用フェーズの開始recover_slave: フェーズ3.5と同じように各スレーブを回復しますchange_master_and_start_slave: CHANGE MASTER TO コマンドでこれらを変更しますスレーブは新しい新しいマスターを指し、最終的にレプリケーションを開始します (スレーブの開始) フェーズ 5: 新しいマスターのクリーンアップ フェーズreset_slave_on_new_master 新しいマスターのクリーンアップは実際にはスレーブ情報をリセットします。元のスレーブ情報をキャンセルします。この時点で、マスターフェールオーバープロセス全体が完了します rotate処理 mha:: masterrotate :: main()-> do_master_online_switch:フェーズ1:fase - >識別_orig_masterconnect_alle_and_read_server_status : connect_check: まず接続チェックを実行して、各サーバーの MySQL サービスが正常であることを確認します connect_and_get_status: MySQL インスタンスのserver_id/mysql_version/log_bin.. およびその他の情報を取得します このステップにも重要な役割があります。現在のマスターノードを取得します。 show smile status を実行すると、 出力が空の場合、現在のノードがマスター ノードであることを意味します。 validate_current_master: マスターノードの情報を取得し、構成が正しいかどうかを判断します サーバーが停止しているかどうかを確認し、停止している場合はローテーションを終了します マスターが生きているかどうかを確認し、停止している場合はローテーションを終了します check_repl_priv: サーバーがダウンしているかどうかを確認しますユーザーはレプリケーション権限を持っています monitor_advisory_lock を取得して、現在マスター上で他の監視プロセスが実行されていないことを確認します 実行: SELECT GET_LOCK('MHA_Master_High_Availability_Monitor', ?) AS Value failover_advisory_lock を取得して、現在スレーブ上で他のフェイルオーバー プロセスが実行されていないことを確認します 実行: SELECT GET_LOCK('MHA_Master_High_Availability_Failover', ?) AS Value check_replication_health: 実行: SHOW SLAVE STATUS のステータスを確認します: current_slave_position/has_replication_problem その中で、has_replication_problem は具体的に次の内容をチェックします: IO スレッド/SQL スレッド/Seconds_Behin d_マスター(1s) get_running_ update_threads: show processlist を使用して、現在更新を実行しているスレッドがあるかどうかを確認し、存在する場合は switch を終了します ->identify_new_master set_latest_slaves: 現在のスレーブ ノードはすべて最新のスレーブです select_new_master: 新しいマスター ノードを選択します。 優先ノードが指定されている場合、アクティブな優先ノードの 1 つが新しいマスターになります。 最新のサーバーが遅れすぎる場合 (オンライン バックアップの SQL スレッドを停止するなど)、 新しいマスターとして使用すべきではなく、リレーをフェッチする必要があります。そこにログを記録することをお勧めしますマスターは設定されていますが、大幅に遅れている場合はマスターになりません。 get_candidate_masters: 就是配置文件中配置了candidate_master>0の节点 get_bad_candidate_masters: # 次のサーバーはマスターになれません: # - デッドサーバー # - conf ファイル (つまり、DR サーバー) で no_master を設定します # - log_bin が無効です # - メジャー バージョンが最も古くありません # - レプリケーションの遅延が大きすぎます (スレーブとマスターの binlog 位置の差距離大≧ 100000000) 候補マスターのスレーブから検索しています最新のリレー ログ イベントを受信しました 見つからない場合: すべての Candidate_master スレーブから検索します 見つからない場合: 最新のリレー ログ イベントを受信したすべてのスレーブから検索します 見つからない場合: すべてのスレーブから検索します フェーズ 2 : 更新の拒否フェーズ拒否_update:ロックテーブル、書き込みビンログを拒否しますMHAの構成ファイルに「master_ip_online_change_script」パラメータが設定されている場合、通常は現在のマスターへの書き込みを無効にしますこの脚本はvipを使用しているときに最適な設定が必要です reconnect: 現在のマスターとの正常な接続を確保します lock_all_tables: READ LOCK でテーブルをフラッシュし、テーブルをロックします check_binlog_stop: マスターのステータスを再度表示し、書き込みbinlog がすでに停止しているかどうかを判断します read_slave_status: get_alive_slaves: check_slave_status: 「SHOW SLAVE STATUS」を使用してスレーブの次のような情報を取得します: Slave_IO_State、Master_Host、 Master_Port、Master_User、 Slave_IO_Running、Slave_SQL_Running、 Master_Log_File、Read_Master_Log_Pos、 Relay_Master_Log_File、Last_Errno、 Last _Error、Exec_Master_Log_Pos、 Relay_Log_File、Relay_Log_Pos、 Seconds_Behind_Master 、Retrieved_Gtid_Set、 Executed_Gtid_Set、Auto_Position Replicate_Do_DB、Replicate_Ignore_DB、Replicate_Do_Table、 Replicate_Ignore_Table、Replicate_Wild_Do_Table、 Replicate_Wild_Ignore_Table switch_master: switch_master_ external: master_pos_wait:调用select master_pos_wait関数数,等待機主从同步完了 get_new_master_binlog_position:执行'マスターステータスを表示'新しいマスターへの書き込みアクセスを許可します: 调用master_ip_online_change_script --command=start ...,vip指向新しいマスター disable_read_only: 新マスター上での実行:SET GLOBAL read_only=0 switch_slaves: switch_slaves_internal: change_master_and_start_slave change_master : start_slave:unlock_tables:元のマスター上でロック解除テーブルを実行 フェーズ 5: 新しいマスターのクリーンアップ フェーズ replace_slave_on_new_master release_failover_advisory_lock http://www.bkjia.com/PHPjc/1119676.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/1119676.html技術記事 MHA 障害切り替えとオンライン切り替えのコード解析前段階で、私は次の MHA 障害切り替えとオンライン切り替えのコード フローを整理し、同意した後、ここに送信します。