ORCAのアーキテクチャ(二重化)

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での二重化は、

  • データベースのレベルで
  • 自動のフェイルオーバなしで
  • 自前のコードで

実現することとなった。具体的には、データベース層のリクエストを複数のサーバにリダイレクトする機構を自前で設け、複数のデータベースに同じ更新を行うことによって実現されている。よく「○○を使えば云々」という人がいるし、勝手にそれを使うのは構わないし、うまくやればその方が信頼性が確保しすくなると思うのだが、本体の機能としてそれに頼るわけには行かなかったのだ。