ORCAの要件には、「二重化」というのがある。つまり、一種のフォルトトレラント化するということだ。
バックアップをどうするか
これは、元々「バックアップをどうするか」という話があった。ORCAの基本設計では、最初に想定システム構成を決め、その中で安定して運用することを提供することを考えていた。ただしその「想定システム構成」は十分安く構築することが出来なければならない。
「バックアップ」となると、RAIDではダメだ。なぜなら、RAIDでは復旧させるためには、ハードウェアに手を入れなければならない。software RAIDでも少なくともディスクの交換、hardware RAIDだとコントラーラの交換… だから、RAIDはバックアップとは言えない。何にせよ、バックアップと言うからには、
- バックアップは稼働しているハードウェアから切り離せること
- 復旧する自体に手間がかからないこと
- ダウンタイムが極小化させること
という条件がつく。
その当時、マトモなバックアップの手段は、
テープ
であった。書き込み可能なDVDはまだ一般的ではなかったし、信頼性にも不安があったので、この時点では想定していない。ところが、テープは、
高い上に遅い
のだ。下手すればもう1台サーバを用意してもお釣りが来る… さらにローテーションをうまくやらないと、使えないバックアップを作ってしまうし、テープの経年劣化は環境によってはかなり激しい。ということで、その時にひらめいたのは、
サーバを二重化する
ことであった。一見オーバースペックに見える方法であるが、
- パソコンなんて安いもの
- 故障したら壊れた方だけセンドバック修理
- ダウンタイムは短い
という可能性があった。何よりも「壊れたらセンドバック」という修理方法が使えるということは、僻地離島といったサービスにとって厳しい環境であっても、安心して使えるということで意義は大きい。しかも、安いパソコンを使えばコストダウンも出来る。
データベース二重化の実現方法
問題はこれをどうやって実現するかであった。
当時、データベース(PostgreSQL)を二重化するためのソフトウェアは、これと言って決定版がなかった。どれもが
帯に短し
で、「襷に長し」なものはなかった(「襷に長し」なら切って使えばいい)。つまり、「とりあえず実装しました。いろいろ機能不足がありますが、その辺はうまくなだめて下さい」という状態で、どれを選んで良いか判断に苦しむものだった。今となれば「あれも、これも」の状態なのだが、「当時」はどれが使いものになって行くかすらわからなかった。
この時、選択を誤ると「開発元が開発を放棄したら、自分たちでずっと面倒を見る」ことを考えないといけない。それはそれで良いことなのだが、我々がやりたいことは、
使いやすいプラットフォームでアプリケーションを作る
ことであって、「これから発展するであろう他人様の開発したOSSにコミットする」ことではない(繰り返すが、このプロジェクトはOSSの実験プロジェクトではなく実用品を作るプロジェクトだ)。だから、「有りものでやれるのならそれを使うが、有りものの前途がわからなかったら手を出さない」という判断になる。ここで他人の開発したものを使わないという判断をすれば、
- 開発元の方針や進捗にプロジェクトが左右されない
- 自分たちに必要な機能だけを実装すればいい
- 自分たちの方針でプロジェクトが動かせる
となる可能性がある。
自分たちでやるメリット > 他人が作ったものを選択するメリット
であるなら、自分たちで作った方が安くて速い。特に「帯に短いものが多数」みたいな状況だと、どれを選ぶかというのは大変難しい決断を要求される。
他方、データベースエンジンについては、PostgreSQLを使うことにそれ程強いこだわりのようなものはなかった。MySQLが使いものになればそれを使えれば良いし、Oracleを使いたい人がいたらそれでもいいだろう。MONTSUQIのデータベースアクセスのアーキテクチャは、自前のO/Rラッパのようなものがあって、アプリケーションはその上での操作しかしないから、データベースエンジンでアプリケーションは左右されない。そのメリットを生かすためには、「PostgreSQLに特化した二重化ツール」は使わない方が安全だ。PostgreSQLはいいものだとは思うが、縛られたくはない。
処理レベルでの二重化
二重化には他の方法もある。複数のサーバに独立したデータベースとアプリケーションを用意しておき、処理要求は両方のサーバに分枝して行うということだ。これだと、
ダウンタイムの極小化
が実現出来る。サーバ自体がコケても、フェイルオーバしてやることにより、事実上のダウンタイムが0に出来る。つまり、完全なフォルトトレラントが実現出来る。せっかくサーバを二重化するんだから、この方法を取れば「コケてもそのまま業務が続けられます」と言うことが出来て、なかなか格好もいい。ダウンした後の対処も、「ダウンしたサーバを取り外すだけ」で済むので、運用にも都合がいい。
こういった良いことづくめの方法ではあるのだが、ORCAという環境で使うということを考えると、思わぬところに落とし穴がある。
- フェイルオーバしてしまうと、故障に気がつかない
- 「サーバ2台」とは言うもののクライアント兼用だ
- 様々な理由でデータベースの内容はくい違うことになる
- ネットワークだけ泣き分れることはしばしば起きる
ということが起こりうる。特にマズいのは「故障に気がつかない」ということだ。もちろん故障が起きたら何らかのアラートを上げればいいわけだけど、このシステムは
システムオペレータ = エンドユーザ
なのだ。だから「動いているから気にしない」みたいな判断をされかねない(実際、サポート要求の内容を見るとその手のことをやる人は、私が想定した以上に多い)。だから、「壊れたらとりあえず止まってしまう」という乱暴な方法で「エラー通知」をしなきゃいけない。となると、せっかくのフォールトトレラントが意味を持たない。
そんなわけで、処理レベルの二重化は設計の中には入れていて、コードや動作もその影響を受けているのだが、実際には全てを実装するには至っていない。大病院やSaaSというような話が一般的になれば、完成させようと思うのだが、今のところはやっていない。
実際の二重化
そんなわけで、ORCAでの二重化は、
- データベースのレベルで
- 自動のフェイルオーバなしで
- 自前のコードで
実現することとなった。具体的には、データベース層のリクエストを複数のサーバにリダイレクトする機構を自前で設け、複数のデータベースに同じ更新を行うことによって実現されている。よく「○○を使えば云々」という人がいるし、勝手にそれを使うのは構わないし、うまくやればその方が信頼性が確保しすくなると思うのだが、本体の機能としてそれに頼るわけには行かなかったのだ。