mysqlマスタースレーブでマスターを決定する方法


17

MySQLマスタースレーブレプリケーションを設定し、スレーブをマスターに昇格させるフェールオーバー状況を処理する方法を見つけようとしています(マスターがダウンした場合)。

アプリケーションサーバーはすべての書き込みを現在のマスターに転送する必要がありますが、2つのdbサーバーは物理的に異なる場所にある完全に異なるサブネット上にあるため、マスターとスレーブの間でサーバーレベルのHA(ハートビート、キープアライブ)を使用できません。

これは、アプリケーションレベルで処理する必要があるものだと思います。2つのサーバーにクエリを実行し、どちらがマスターかを尋ねてから、そのサーバーに対するすべてのクエリを実行できます。

現在のサーバーがマスター/スレーブレプリカのマスターであるかどうかを確認するクエリがMySQLにありますか?


使用しているMySQLのバージョン???
-RolandoMySQLDBA

これはmysqlの出力であるServer version: 5.5.23 MySQL Community Server (GPL)
イーサン・アジョン

回答:


13

@RolandoMySQLDBAはこの質問に正確に答えました...しかし、彼はまた、彼の解決策は「迅速かつ汚い」ことを指摘しました。

そして、それは非常に真実の声明です。:)

ここで私に関係するのは、その答えではなく、元の質問が間違った仮定をしているように見えることです。

2つのサーバーにクエリを実行し、どちらがマスターかを尋ねてから、そのサーバーに対するすべてのクエリを実行できます。

問題は、MySQLレプリケーションでは、マスターがマスターであることを真に認識しないことです。

「マスターへの昇格」の概念は、MySQL非同期レプリケーションの概念ではありません。MySQLサーバーをマスターロールに「昇格」することは、MySQLサーバーの「内部」で発生するものとは対照的に、MySQLサーバーの「外部」で発生するものです。

技術的に言えば、バイナリロギングが有効になっているすべてのMySQLサーバーは、スレーブがない場合でもマスターであるため、「マスターへの昇格」はいかなる種類のサーバープロビジョニングによっても行われません。 SHOW MASTER STATUSスレーブの有無にかかわらず、まったく同じように機能し、まったく同じ結果を返します。2つのスレーブを持つマスターは、1つのスレーブまたは0のスレーブを持つマスターとほぼ同じです。同様に、スレーブがすべてオフラインであるマスターは、マスターと同じです。スレーブがオンラインに戻ると、中断したところから複製を開始するからです。

ある意味では、どちらかのサーバーの唯一の「認識」は、それがマスターであるかどうかではなく、スレーブであるかどうかです。

それが、ローランドのソリューションが求めているものです:「あなたは奴隷ですか?」答えが「いいえ」の場合、仮定はこれがマスターでなければならないということですSTOP SLAVE;。しかし、停止したスレーブはまだスレーブであるため、「スレーブではない」(いつでも)は「マスターであること」に相当しません。

推定されるマスターで同様のテストを実行できます。

SELECT COUNT(1) FROM information_schema.processlist
 WHERE user = 'the_username_used_by_the_slave';

または

SELECT COUNT(1) FROM information_schema.processlist
 WHERE command = 'binlog dump';

値がゼロの場合、スレーブのIOスレッドは接続されていません。このテストには同様の欠陥があります。スレーブが管理上切断された場合、隔離された場合、または失敗した場合、スレーブは接続されません。したがって、これでも実際には何も解決されません。

さらに悪いことに(これらのシナリオのいずれかについて)、information_schema.processlist "table"は、選択されるたびにマテリアライズされる仮想テーブルであり、これには時間とコストがかかります。各スレッドのアクティビティはピアインする必要があるため、サーバーが忙しいほどコストがかかります。

より軽量なソリューションは次のとおりです。

SELECT @@global.read_only;

スレーブではread_onlySUPER特権のないユーザーが意図せずに書き込むことができないように、グローバル変数を設定する必要があります(また、アプリケーションが持つべきではありませんSUPER)。スレーブをマスターの役割に手動で「昇格」する場合SET GLOBAL read_only = OFF、書き込みを有効にします。(これがどのように設定されていても、レプリケーションは常にスレーブに書き込むことができます)。

しかし、これはまだ重要な点を見落としていると思います。

アプリケーションがマスター/スレーブのセットアップでこの決定をヒューリスティックに行うべきではなく、接続ごとではないことを提案します。 アプリケーションはハード構成オプションを使用するか、アプリケーションが気付かないままにして、データベース接続の宛先を別の方法で処理する必要があります。

または、少なくとも、マスターに障害が発生するまでアプリケーションを切り替えないでください。その後、アプリケーションが再び切り替えられることはありません。

私がそう言う理由は次のとおりです。「決定」が行われた場合-誰でも何でも-別のサーバーをマスターにすると、オンラインに戻った後でも、アプリケーションは何らかの理由で元のマスターに戻ることができません、介入なし。

バグを見つけて、ソフトウェアによるクラッシュが発生したとしましょう。mysqld_safe忠実に再起動しmysqld、InnoDBクラッシュリカバリは問題なく実行されます。しかし、それには数分かかります。

その間、マスターがダウンしているため、アプリケーションはスレーブに切り替わりました。トランザクションが作成され、注文が行われ、資金が転送され、コメントが投稿され、ブログが編集されました。

これで、元のマスターがオンラインに戻ります。

アプリケーションが元のマスターに戻った場合、絶対に怪我をしていることになります。これは、アプリケーションが平均でスレーブのデータを変更したため、矛盾が発生してレプリケーションが停止する可能性があるためです。時間。一貫性のないデータを持つ2つのデータベースサーバーがあり、手動で調整する必要があります。ドルやポイント、クレジットが関係している場合、残高が一致していません。

したがって、ユーザーの介入なしにアプリケーションが元のマスターに戻ることを許可されないことが重要です。

待って、私が説明したように、このシナリオで問題を見つけましたか? マスターは失敗しましたが、スレーブはマスターではなくスレーブであるとみなされるため、アプリケーションはスレーブを使用しません... information_schema.processlistマスターサーバーの電源が切れても、スレーブに対するクエリはゼロ以外を返します。

そのため、アプリケーションが何かを発見してもあまり意味がありませんSTOP SLAVE。そのテストを有効にするには手動で行う必要があるからです。

おそらく、アプリケーションを切り替えられるようにする場合のより良いアプローチは、循環レプリケーションを使用してサーバーを構成することです。

循環レプリケーションには固有の問題がありますが、アプリケーションが常に一度に1つのサーバーにしか書き込むことがない限り、これらの問題のほとんどは問題になりません。言い換えると、両方のマシンはレプリケーションの意味で常に同時にマスターとスレーブの両方ですが、アプリケーションは何らかのメカニズムを介して、一度に1台のマシンのみを「マスター」としてポイントし、書き込む必要があります。 。

MySQLサーバーに分離されているため、HAツールをMySQLサーバーにデプロイすることはできませんが、アプリケーションサーバーで実行されているHAProxyを使用して実装できます。アプリケーションはlocalhostの「MySQL」に接続します。これはMySQLではありませんが、実際にはHAProxy ...であり、TCP接続を適切なMySQLマシンに転送します。

HAProxyは、MySQLサーバーへの接続をテストし、接続を受け入れ認証を許可しているMySQLマシンにのみトラフィックを提供できます。

アプリケーションサーバーで実行されているHAProxyの組み合わせ(リソースに対する要求は、アプリケーションサーバーが行う他のすべてに比べて実質的ではありません。ソケットを結び付けてペイロードを無視するだけです)...およびMySQL循環レプリケーション質問から知られていることに基づいて、おそらくこの場合に私が取るであろうアプローチでしょう。

または、厳密に手動で設定/etc/hostsする場合は、アプリケーションがMySQLに接続するために使用するホスト名を持つアプリサーバーのファイルのエントリなど、「ディスカバリ」よりもはるかに単純なものを使用します。 masterは、手動プロセスを意図しています。

または、Percona XtraDB Clusterを使用した、より複雑なもの。ただし、PXCに3つのノードがある場合、2つのサーバーは相互に認識できても1つのサーバーから分離されると(3つすべてがまだ実行されている場合)、2つのサーバーは引き続き正常に実行されるため、3番目のサーバーを追加する必要があります1台のサーバーは小さなボールに丸まって、それが奇妙なものであるに違いないと認識しているため、何もすることを拒否します。これは、ネットワークが分割される前にオンラインであったノードの大部分を構成しているのが2つであり、そうでないことを1つが認識するためです。PXCでは、アプリケーションがどのサーバーに接続するかは問題ではありません。

これはすべて、「アプリケーションがサーバーをポーリングしてどちらがマスターであるかを確認しない」と言うことだと言います。遅かれ早かれあなたに噛みつき、噛む日まであなたのパフォーマンスを食いつぶしてしまうからです。


まず第一に、よく書かれた応答に感謝します。あなたは良い解決策を提案したと思います。私は過去に循環レプリケーションを使用することを考えましたが、その信頼性に関して悪いことを読みました。ただし、auto_increment_increment、auto_increment_offsetなどを変更することにより、これらの問題の多くを防ぐことができます。アプリケーション層から離れたロジック。HAProxyの設定を検討します、ありがとう!
イーサンアヨン

1
喜んでお手伝いします。まだ投票していない場合は、投票してください。循環レプリケーションは、その仕組みを理解し、賢明な方法で使用している限り、マスター/スレーブと同じくらい信頼性があります(同じテクノロジーで、両方向に進むだけです)。サーバーが適切に同期されており、アプリケーションが一度に1つのサーバーにしか書き込みを行っていない限り、問題は一度もありません。auto_increment_*変数は、「念のために。」、まだこのシナリオで使用してもいいです また、忘れずにbinlog_format= rowまたはmixed- を使用してstatementください(循環を行っていない場合でも)。
マイケル-sqlbot

この詳細な説明は、システムをより堅牢にするために再設計するのに役立ったため、受け入れられた答えを純粋に変更しました。@RolandoMySQLDBAの答えは依然として正しいものであり、最初に説明した問題を解決します。ありがとう!
イーサンアヨン

10

マスター/スレーブのみを使用している場合は、ここに手っ取り早い方法があります。

SELECT COUNT(1) SlaveThreadCount
FROM information_schema.processlist
WHERE user='system user';

これは何を意味しますか?

  • SlaveThreadCount= 0の場合、マスターがいます
  • SlaveThreadCount> 0の場合、スレーブがあります

警告:これは実行しない限り機能しますSTOP SLAVE;

もう1つ試してみてください。スレーブでバイナリロギングを無効にして実行するSHOW MASTER STATUS;と、マスターは現在のバイナリログを提供します。スレーブは何も提供しません。


素晴らしい、これはまさに私が必要なものです。これは問題の面倒な解決策だと思いますか?私が想像できる唯一の問題は、両方のサーバーがマスターに昇格することですが、それは実際には決して起こりません。
イーサンアヨン

この回答が必要なものである場合は、回答のチェックマークをクリックして、回答を承認済みとしてマークしてください。
RolandoMySQLDBA

私はそれをさらに5分間受け入れられるとマークすることはできません:)
イーサンアヨン

問題ない。手伝ってくれて嬉しかった!!!
-RolandoMySQLDBA

0

mysqlプロンプトからこのステートメントを実行します
mysql> show slave status;

スレーブでは多くのパラメーターとその値/ステータスが表示され、マスターでは空のセットが表示されます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.