この程、InfoQ.comはこのサイトを始めてから使用していたバックエンドのデータベースを刷新した。しかし、すべて計画通りに事が運んだわけではなかった。ほとんどの移行作業は滞りなく進んだが、いくつかの予期していなかった問題(現在は解決済み)に直面した。この記事では、私たちがどんな計画をして、何が成功し何がうまくいかなかったのか、そして直面した問題をどのように検知し解消したのかを詳しく論じたい。
計画
今回の更新作業は複雑な案件であり、2、3ヶ月を必要とした。既存のデータベースサーバは、最初に導入した2006年からハードを変えていなかったので、ほとんど最大限に利用している状況だった。そしてこの結果、性能上の問題が顕在化し始めていた。特に定期的に実行されるレポート出力処理が走っているときは性能劣化が顕著だった。加えて、単一のマスタMySQLデータベースからマスタ/スレーブ構成のMySQLデータベースへ移行する良い機会でもだった。この構成にしておけば、ホットフェイルオーバが可能になり、マスタデータベースではなくスレーブに対してレポート処理やバックアップを行うことができる。InfoQ.comのユーザはこのような処理の性能上の悪影響を受けずにすむようになる。
私たちは下記のような複数の段階を踏む計画を立案した。
- 準備: ISP (Contegix社)と開発チーム、オペレーションチームとの電話会議や作業計画の作成、必要なすべての構成ファイルの事前準備、ISP側への計画の周知徹底。
- サービス定期時間/データ転送: MySQLの計画停止の実施(すべてのトランザクションが完了していることを保障するためにウェブサーバの停止し、DBを読み取り専用に変更、トランザクションログを検証しMySQLを停止)、データ転送速度を最大化するためデータセンターの古いデータベースサーバと新しいサーバを物理的に接続し、旧サーバから新サーバへデータをコピーし、コピーしたデータを検証。そして、InfoQ.comを(旧サーバを利用してでも)再開できるようにしておくため、サービスに関するすべての情報をバックアップ。
- InnoDBテーブルの変換: 新データベースサーバ上にMySQLを構築しmysqldumpを使ってテーブルをエクスポート。そしてMySQLを停止して既存のデータをすべて削除。その後、file-per-tableモードへ変換するためにエクスポートしたデータをインポート(インポート処理ではすべてのステップを検証する)。
- ファーストスレーブの準備: 新データベースサーバを旧データベースサーバへ向け、マスタ/スレーブレプリケーションが正常に行われることを確認する。そしてレポート処理を新しいスレーブサーバで実施するようにする。
- セカンドスレーブの準備: 2台目の新データベースサーバを1台目の新データベースサーバへ向け、マスタ/スレーブレプリケーションが正常に行われることを確認する。結果的には
master <-- slave 1 <-- slave 2
という構成になる。こうしておくことで、スレーブ1からスレーブ2への同期の高速化が実現できる。これは(最大限に利用されていて負荷も高い)マスタと同期するmaster <-- slave 1, slave 2
という構成よりも圧倒的に早い。 - 新しいマスタとの入れ替え: 既存の古いマスタから新しいマスタ(ファーストスレーブ)への切替作業を実施する。古いマスタは新しいスレーブにする。同時にウェブサーバを新しいマスタデータベースへ向ける。
また、新しい2つのスレーブサーバにMySQL 5.1を導入したことで、更新作業に伴うサービス停止時間が少なく抑えられることがわかった。私たちの調査によると、MySQL 5.1のスレーブはMySQL 5.0のマスタと正常に同期ができる。したがってスレーブにMySQL 5.1を導入する作業から始めることで、ファーストスレーブを新しいマスタに置き換える作業とMySQL 5.1へのアップグレードをあわせて行うことができる。
他のとりうる選択肢(サービスの停止を回避できる)としてはマスタを停止してファイルのコピーを実施するのではなく、mysqldumpを使ってマスタサーバからデータを取り出しスレーブに転送する方法があった。しかし、対象が最大限に利用されているサーバなのでこの方法は選択肢から除外した。というのは、バックアップ処理を実施すればマスタデータベースに対して過大な負荷がかかり、その結果、応答の遅延が発生して最終的にはサービスが停止している状況と同じになってしまう可能性があるからだ。
計画の実行
最初に直面した課題は計画を実施の適切な時間を見つけることだった。開発チームはルーマニア、ISPはミズーリ、オペレーションチームはバンクーバーとオレゴンに分散している。結局、InfoQ.comへのアクセスが少ない時間帯をサービス停止時間にできること、オペレーションチームが夜間に作業を開始できることと開発チームが朝に作業を開始できること(ルーマニアとバンクーバーには10時間の時差がある)を考慮して、太平洋標準時刻の金曜深夜帯(ヨーロッパでは土曜日の朝)を実施時間とした。実施時間を決定したことで計画の第一段階が完了した。
第二段階はサービスの停止だ。計画したときには、2台のサーバをギガビットイーサネットで接続して作業を行うため、2時間程度の停止時間で大丈夫だろうと見積もっていた。しかし、実際作業をおこなうとネットワーク上の問題が見つかったため最終的には5時間以上もかかった。この点で私たちは重要な教訓を得た。すなわち、ひとつのデータセンター内の作業だからネットワーク上の問題が起きないと思っていたら大間違いだ。
第三段階から第六段階は滞りなく進み、とくに問題には直面しなかった。2月26日に新しいマスタデータベースへの切り替えを行い、その後基本的な動作確認をおこなっても問題は見られなかった。うれしい事にサイトの挙動は以前と比べて段違いに早くなった。私たちは今回の作業全体にとても満足していた。
しかし、これでこの記事が終わってしまったらちょっとつまらないでしょう。 :)
コメントシステムの問題
移行実行の数日後、コメントシステムにいくつかの問題があることに私たちは初めて気付いた。具体的には、新しいコメントが投稿されてもその後数分経つと消えてしまうという現象で、ユーザの印象では削除されたように見えるそうだ。結局、この問題の原因は驚くべきものだった。データベースサーバのマスタ/スレーブレプリケーションを有効にしたため、現在使っているバージョンのJiveがコメントを消失していたのだ。解決策としてトランザクションの分離レベルをREAD_UNCOMMITTEDからREPEATABLE_READへ変更した(READ_UNCOMMITTEDではレプリケーション環境でエラーを発生させてしまうからだ)。こうすれば、もう一度コメントを作成できる。
しかし、これですべての問題が解決したわけではなかった。初期のテストでは問題なくコメントが追加できていたものの、2、3日経つと一貫性についてとても奇妙な問題が発生していることがわかった。具体的に言うと、データベースの移行以後に付け加えられたコメントが、サイト上の全く関係のない既存のコメント欄に加えられているようだった。もう少し深く調べてみるとJiveが何のエラーもログを出力せずにスレッドを追跡するためのユニークなIDを初期化していることがわかった。その結果、IDのカウンターが16,000から0へ初期化されてしまった後、既存のスレッド(古いものではあるが)を上書きしてしまったり、壊してしまったりする可能性が発生していた。結局、原因は私たちが、MySQLの行ベースレプリケーションを選択したことにあった。この原因に気付いた私たちは、原因を解決して不正に割り当てられてしまったコメントの削除を実行した。
私たちが学んだこと
今回の更新作業で私たちは次のことを学んだ。
- 詳細な計画が大事: 不慮の出来事(失敗やエラーに直面した場合の対応策も含む)について計画し、あらかじめ推測しておくことで、実際の作業は滞りなく進み、更新作業中に不測の事態が発生しても慌てずに計画通りに対処できる。
- 計画は時間がたてば変わる:"どんな戦術も眼前の敵には無力だ。"という古い格言がある。 -- 計画を通して考えを練ることは重要だが、思いがけない問題に対しても準備しておく必要がある。すべてのことを計画することは不可能だ。
- 機械的なデバッグ作業は時間の節約になる: 可能性を排除するのが早ければ早いほど、ある問題の原因を見つけるのが早くなる。エラーに直面したらすぐにgoogleで検索してどんな答えが返ってくるか調べること。こうすることで不明瞭でよくわからない問題を解決する時間が大幅に節約できる。
- 活発にフィードバックを求める: ある問題に直面したら誰かメールをくれたり直接助言をくれたりするのを待っていてはならない。私たちが問題に気付いたのはTwitterをよく見ていたからだ。もし誰かがメールで問題を指摘してくれるのを待っていたら問題の解決にはもっと多くの時間がかかっただろう。Twitter検索やGoogleアラートは友達だ。うまく使おう。
また、私たちはいつでもフィードバックを受け付けている。チャンネルは下記のどれでもいい(複数でも!)。
- Twitter: via @InfoQ
- メール: via feedback@infoq.com
- Googleグループ: via InfoQグループ
- LinkedIn: via InfoQグループ
- 記事へのコメント