2009年3月27日

データベース

Yahoo!オークションでのMySQL 冗長化技術

  • このエントリーをはてなブックマークに追加

こんにちはオークション事業部プラットホーム技術のチャックです。

オークションでは一部サービスに RDBMS の MySQL を使ってサービスをご提供させていただいております。
オークションでは多くのお客様よりアクセスを頂いておりますので、大量の更新、参照の処理速度に優れた
MySQL を選択し、お客様にストレスなくサービスをご利用いただけるよう
日々業務に取り組まさせていただいております。
しかし、精密機器には故障がつきもので、サービス運用の観点からは

「機器が故障するのはしかたない、しかしそれをいかに早く復旧させるか」

といったことを念頭に入れております。
実際には、障害が起こってから復旧させるのではなく、障害が発生した場合に
代替サーバーが処理やデータを引き継げるように failover を意識して前もって
システム設計をすることになります。

MySQL の failover というと DRBD + Heartbeat による HA構成をよく見受けますが、
今回はオークションの少し変わった? failover の仕組みを紹介したいと思います。

更新サーバーと参照サーバーの分離

オークションでは MySQL を使ったサービスの多くは webアプリケーション と MySQL とで
それぞれ別サーバーに機能分けしています。さらに MySQL サーバーでは多くのアクセスを
滞りなくさばけるように更新のみを行うサーバー(master)と 参照のみを受け付けるサーバー(slave)
とで機能分けしています。

dual master

オークションの一部のサービスでは master , slave のセットを2つ用意し、上流の master 同士で
双方向レプリケーションによる dual master を構成しているものがあります。

上流の master では自身に更新される binlog と レプリケーションにより更新される
binlog の両方を吐き出すように設定しているため、4台のサーバーは非同期ではありますが
常に同じデータを持つことになります。

ソフトウエアロードバランサ

webアプリケーションからのmysqlへの更新、参照のアクセスはYahoo!独自のソフトウエアロードバランサを
経由して行います。このソフトウエアロードバランサが failover の肝となります。
このソフトウエアロードバランサは、仮想のDNSを設定し、gethostbyname (3)を置き換えることで
負荷分散を実現します。そして仮想のDNSに登録されたサーバーの特定ポートへ、
ヘルスチェックを常に行い、障害が検知されたサーバーへはアクセスしないよう制御します。

master には primary (master01), secondary (master02)を設け、通常時は更新は master01 のみ ,
参照は slave01,slave02 をラウンドロビンでアクセスするよう設定しています。

そして master01 に障害が発生すれば自動的に master02 へ
ソフトウエアロードバランサにより failover されます。
slave 側に障害があった場合も同様です。

ヘルスチェック

ここでソフトウエアロードバランサのヘルスチェックについて少し補足を。
ソフトウエアロードバランサはサーバーの特定ポートへヘルスチェックを行い障害を検知するわけですが、
MySQL の ポートはデフォルトで 3306 です。しかし、このポートを直接ヘルスチェックのポートに
使用することは避けました。

以下の理由からです。

   ・サーバーメンテナンス等で意図的に MySQL サーバーをサービスアウトさせたい時に mysqld を落とす、
    もしくはソフトウエアロードバランサの設定を変更しなければならなくなる。
   ・サーバー復旧時に MySQL を立ち上げてしまうと web サーバーからアクセスされてしまう恐れがある。

このことから、ヘルスチェックは別ポートにしています。
この別ポートでは以下の機能を持ったデーモンを動かしています。

   ・通常時は常に指定のポート で LISTEN している。
   ・MySQL の生死チェック、障害を検知すればポートを閉じる。
   ・特定ファイルの存在チェック、存在しなければポートを閉じる。

このデーモンにより、ソフトウエアロードバランサに MySQL の生死だけではなく、
特定ファイルがない場合にはアクセスをしないという機能を間接的に持たせています。
サーバーメンテナンス等で意図的にサービスアウトしたい場合にはこのファイルをなくしておけば
MySQL は立ち上がっていてもwebアプリケーションからはアクセスされる心配がないということです。

Nagios

話を戻しましょう。以上のように failover を実現しているわけですが、
この構成では master01 が障害にあった場合、更新アクセスを master02 へ切り替えるだけでは
十分ではありません。参照についても slave01 へアクセスしてはまずいのです。
なぜなら master01 に直結している slave01 はレプリケーションによる更新が
途絶えてしまっているからです。このまま参照が slave01 ,slave02 にアクセスし続けていると
slave01 , slave02 でデータの差異が出てくるわけですからwebアプリケーションから見れば
更新したのに更新が反映されてない! ということになってしまいます。

この問題を解決するために私達は最も簡単な方法をとりました。
サーバー監視に利用している Nagios のイベントハンドラです。

オークションのサーバーの監視にはYahoo!が独自にカスタマイズした Nagios を使用しています。
サーバーの MySQL の監視も Nagios で行っていますのでこれを利用することにして、
この MySQL の監視のイベントハンドラに以下の機能を付け加えることにしました

   ・masterサーバーに障害があった場合には、それに直結する slave のヘルスチェック用ポートを閉じる。

これにより、webアプリケーションからの slave01 へのアクセスを止めるようにしています。

このシステムを構築した後、あらためて見てみると少し複雑だなぁなんて思ったりしましたが (汗

ともあれ、オークションではこのように 「dual master + ソフトウエアロードバランサ + Nagios」
で failover を実現しているサービスもありますよという紹介でした。
障害時でもお客様にサービスを提供しつづけるため、日々より良いシステム構成を求め、
より障害に強いサービスを提供していきます。

今後とも Yahoo!オークションをよろしくお願いいたします。

Yahoo! JAPANでは情報技術を駆使して人々や社会の課題を一緒に解決していける方を募集しています。詳しくは採用情報をご覧ください。

  • このエントリーをはてなブックマークに追加