l'essentiel est invisible pour les yeux

Monday, March 06, 2006

[Vol.3] RailsとMySQLによる大規模サイト構築実験 

MySQL + Railsで大規模サイト構築実験もいよいよ大詰めです。

前回までは、
DB : Active-Active
LB : Active-Passive

構成を想定して構築してきました。

また、レプリケーションの遅れによる更新の衝突を避けるための解をいくつか紹介しました。

だがActive-Active構成にするコストが大きい!!
「そもそもActive-Active構成で組む必要があるのかどうか?」といった疑問が沸いてきました。

調査を進めたところ、DBのActive-Active構成にするコストに対して、メリットが少ないことが判明。

[Active-Active構成を組むメリット]
瞬間的なコネクション増への対応が可能。
コネクションの負荷分散のみ可能。(I/Oの負荷分散はできない)

[Active-Active構成を組むデメリット]
更新系クエリの負荷分散は不可。
レプリケーション遅延による更新の衝突の問題。
厳密な同期を要するアプリでは、どちらのDBにもレコードを問い合わせる必要がある。
レプリケーション遅延の度合いを監視する必要がある。

以上を考慮した結果、
DBもActive-Passive構成で組むという結論に至ることになりました。

[MySQLをActive-Standby構成で組む]
MySQLをActive-Passive構成で組むために、ldirectordを少しハック的に使います。

2台の実MasterサーバとVIPを
real server1: 192.168.10.219
real server2: 192.168.10.230
VIP : 192.168.10.226

と定義する。

ldirectord.cfの設定で、通常なら
virtual=192.168.10.226:mysql
real=192.168.10.219:mysql gate 10
real=192.168.10.230:mysql gate 10
fallback=127.0.0.1:mysql gate

とするところを

virtual=192.168.10.226:mysql
real=192.168.10.219:mysql gate 10
fallback=192.168.10.230:mysql gate 10

とする。

このマジックは、fallbackサーバにスタンバイサーバを指定することによりActive-Passive構成を実現します。

※fallbackサーバは、全ての実サーバに接続できないときに接続するサーバです。通常はローカルホストを指定します。


これでActiveのMySQLが落ちた場合にスタンバイ側にコネクションが確立されるようになり、高可用性を実現できました。

WARNING!!!!
一つ注意するポイントがあります。この問題でまる2日ハマりました。
LBを配置しているホストにDBもWEBも配置している場合、WEBからDBへのリクエストはLBを経由して、DBにフォワードされます。この構成では、ダイレクトルーティング使用時、リクエストのフォワーディングに失敗します。

上の状況、つまりロードバランサー(Linux directord)がゲートウェイになりうる時は、パケットの送信元がVIPになるが、LB自体のインタフェースにもVIPが設定されているため偽装さ れたパケットとみなさ、ldirectordによって廃棄されるという罠があります。

詳しくは、
http://ultramonkey.jp/papers/lvs_tutorial/html/

-- 引用 --
しかし、場合によっては(Linux Directorが、本当に実サーバのネットワークのゲートウェイである場合など)、実サーバからの返信パケットをLinux Director経由でルーティングすることが望ましいこともあります。このようなパケットの送信元アドレスはVIPになります。ただし、このVIPは Linux Directorのインターフェイスに属しているので、Linux Directorはパケットが偽造されていると見なしてこれを破棄してしまいます。

この問題を解決する方法はいくつかあります。最もよいのは、Julian Anastasov提供のカーネル・パッチを適用することです。このパッチは、インターフェイスごとにパケット破棄の動作を無効にすることができる procエントリを追加します。このパッチはhttp://www.ssi.bg/~ja/#lvsgwから入手できます。



[更新系の負荷分散]
更新系の負荷分散は、Vol1でも書いたとおり、クラスタ自体のパーティションにより実現します。クラスタのパーティションには二つあります。

・役割に基づくパーティション
・データに基づくパーティション

現在のバージョンのActive Record Clusterでは、役割に基づくパーティションのみサポートしています。


これでMySQL+オープンソースプロダクトを用いたMySQLクラスタの実現に成功しました。
Active-Recordと組み合わせれば、大規模サイトの構築も簡単にできてしまいます。
レプリケーション遅延による自動増分キーの衝突も発生しません。

・・・すばらしい(笑