読者です 読者をやめる 読者になる 読者になる

MySQLをmaster:slave=1:1構成にして参照をslaveに向けるのがなぜ良くないか

MySQLレプリケーションが簡単に構成できるのですが、時折 master 1台 に対して slave 1台、更新処理は master に、参照は slave に、という構成を目にします。
個人的にはこの構成はお勧めでないと思っているので、その理由を考察してみます。

1. 可用性が落ちる
当然ですが、master, slave のどちらが落ちても影響を受けるために可用性が低下します。

2. 全体の性能がほとんど上がらない
master 1台ですべてのクエリを処理する場合と比べて、可用性が落ちる引き換えとして見合った性能向上が得られるか、というと以下のような理由で、あまり性能が向上しないことが多いのではないでしょうか。

  • 更新性能は master, slave ともに同様の処理が必要なので変わらない
    • slave では binlog の書き込みがないとか、安全性を落とした設定ができるので実際には多少差が出ますが、システム全体としては遅いほうの性能が限界になります
  • 参照性能はクエリを均等に振り分けできれば 2倍になるが……
    • レプリケーション遅延を考慮すると、一連の処理時に master, slave 両方を均等に参照するのは避けたい (とある行が消えたり現れたりされたくない)
    • となると実際には、更新を含む一連の処理はすべて master、参照のみの処理は slave、という振り分けかたになる
    • 一般的な Web Application で、更新 1 に対して参照 9 が発生する場合、処理量の不均衡が発生する
            +--------+
            |        |
            |        |
            |        |
            |        |
            | read(9)|
            |        |
            |        |
+--------+  |        |
| read(1)|  |        |
+--------+  +--------+
|write(1)|  |write(1)|
+--------+  +--------+
  master       slave

この状態だと slave の性能が先に限界に達するわけですが、その時点で全体の処理能力は write 1、read 1 + 9 = 10 です。
1台でも読み込みは 9 処理できるのですから、読み込み性能は 9 → 10 でほとんど変わらないことになります。

3. 障害発生時の運用
再起動程度で回復しない障害が発生した場合、ダウンタイムを短くするためには以下のような運用を行うことになります。

  • master 停止 → slave を master に昇格
  • slave 停止 → すべての参照を master に向ける

つまり、そもそも1台で処理できる性能を確保しておかないと、master, slave どちらに障害が発生しても継続運用することができません。

……なら最初から master 1台で処理したほうがいいよね。

ということで、2台でレプリケーション構成を取る場合、参照を slave に振り分けず、アクティブ-スタンバイ構成にしておくほうがよいでしょう。
そうしておけば、

  • slave 障害時 → 使用していないのでサービス停止しない
  • master 障害時 → slave を master に昇格させるのみで復旧可能

となりますから、全体の可用性は落とさず、障害発生時のバックアップ体制も整えることができます。

参考: 私家版省サーバ運用2011またはWebシステムのコンポーネントの配置について

続きのエントリ MySQLで参照の負荷分散を行うslaveは3台から構成するのがよいのでは - 酒日記 はてな支店