2004年4月に始めたKAI_REPORT、今月で20年経ったのであります。
DBエンジン開発ストーリー1、投稿日:2004年4月13日
こちらが最初のエントリーであります。
こうして月に一度とはいえ、ある程度の長さの文章を書く習慣を付けられたのも、このブログのおかげなのであります。
最近特に思うのは、twitter(ドメイン名)と言う短文でさえ、筋の通った文章をまともに書けない人々が増えたことであります。
おまけに、こうした人々は筋の通った短文を誤読して、筋の通らない文章を返しているのであります。
こんなことがなぜ起きるのか、想像に難くないのであります。
それはSNSでのチャットに慣れてしまって、仕事以外では長文を読み書きする機会が極端に少ないか、あるいは皆無だからなのであります。
更にスマホと言う小さな画面がそれに輪をかけるのであります。
スマホで長文を読もうとすると、前後関係を確認するには文章を何度も上下させる必要があるのであります。
KAIがこうした経験から学んだ教訓は、SNSで議論をするなってことであります。
またメールでも相手がスマホであるならば、これも議論してはいけないってことであります。
ではどうするかの結論は、簡単であります。
議論はメールを「パソコン」で交換することに限定するだけなのであります。これであればお互い交換したメールをパソコンの全画面で見ることができ、言った言わないの泥仕合を避けることができるのであります。
そして、アナログ人間社会でも、記録の残らない議論はするだけ、損するのであります。苦手な相手は逃げるが勝ちであります。関わらないのが一番であります。長く生きてきた人間の教訓であります。
いかがでありましょうか。
デジタル社会に生きる人間の知恵であります。 KAI
このブログを始めて、なんと19年が経ったのであります。
このところエントリーアップが月一のペースではありますが、KAIにとって唯一の自前の情報発信の場になっておるのであります。
SNSを含めてどうしても自前でない場は、管理者の制限を受けざるを得ず、なかなか思い通りの自由な発信ができないのであります。
こんな中にあって、20年近くの長きにわたって、ドメインを維持できたことは、関係者のみなさまのご協力の賜物と、感謝申し上げるのであります。
それでは、ブログスタートのエントリー、「DBエンジン開発ストーリー」をご覧ください。 KAI
テトリス的メール滝修行
このBlogでは、過去DBエンジン開発ストーリー5の中のbison君以外私たちのメンバーを話題にしてきませんでしたが、本日からメンバーに加わったkio君のお話を。
今朝から、彼がやるグループ参画手続きと並行して、まず準備しなければいけないのが、私たちが使用するメールシステムをkio君が利用できるようにすることです。先週ゴールデンウィーク谷間に担当者にお願いしていたにもかかわらず、準備できていませんでした。やっと午後になってメーラーが使えるようになって子一時間、彼が一言。
まるで「テトリス」をやってるみたいですよKAIさん!
そうです、メーラーのチェック時間を6分に設定しておくと、そのたびに受信メールが数件づつ、次から次へと上から下へ表示されていくさまを、kio君はテトリスと表現しました。まさに言いえて妙です。
3年間で40万件のメールが、筆者のクライアントにたまっています。月稼働日20日掛ける12ヶ月、240日掛ける3年間で720日、一日平均500件、1日500分とすれば1分1件の割合です。このほとんどが仕事のメールです。これが日増しに増えていくさまはテトリスの時間経過とともにスピードアップするようでコワイ(笑)。
私たちの仕事のやり方は、すべての問題を1件1件のメールに還元することで、メンバー全員で、ありとあらゆる問題を共有し問題解決して行く仕掛けになっています。メーリングリスト上ですべての問題が処理されている状態と言えます。ですから私たちは基本的にリアルなミーティングは、今年に入って一、二度くらいしか開催していません。それで済むと言うことです。
当然このシステムの中には、これを維持するためのノウハウが満載で、これを理解して使いこなせるようになるのに3ヶ月、「意味」までわかるようになるには更に半年、しばらく滝に打たれる修行が続きます。 KAI
前回のオンラインゲーム業界を支える技術−Googleの掌中に?の続きです。
早速ですが、オンラインゲーム用のサーバーの技術的要件を整理します。一般的なマルチプレイヤーの場合を想定していますが、以下のような機能が必要になるかと思われます。(以降の用語、概念はすべてKAI個人が定義して使用しているものです)
(1)個人認証
(2)サービスの選択
(3)サービスの実行
(4)サービス環境の保存
(5)チャット(メッセンジャー)
(6)課金
インターネットからの大量の同時アクセスを制御しながら、これらの機能を実現する技術が、オンラインゲームを支える技術の要の技術になります。特に、ゲームという性格上、レスポンスが悪ければ誰も使ってくれませんし、中途半端なものでは面白さも半減です。そのためには、いわゆる負荷分散と言われる技術が必須となりますが、これは後ほど具体的に説明します。
さて、レスポンスが問題となるのは主に上記の(3)の機能ですが、これを実現するための基本的な考え方を説明します。オンラインゲームの実行には主にゾーン管理とセッション管理の二つの管理が必要です。
ゾーンとはゲームの空間的な単位です。プレイヤーはゾーンの中で決められたルールでプレイします。ゾーンに参加するプレイヤーの人数によって、一人のシングルプレイヤーか、2名から数名までの対戦型か、多人数のマルチプレイヤーか分類されます。セッションとはゲームの時間的な単位です。セッションは、更にターンとリアルタイムという2種類の単位に分類されます。ターンは、プレイヤーとプレイヤーあるいはプレイヤーとシステムの間の往復の時間が単位になります。リアルタイムはプレイヤー同士が時間を共有してプレーする場合の時間の単位です。
ゾーン管理およびセッション管理にとって一番難しいのが、マルチプレイヤーでリアルタイムのゲームの管理であるというのは、容易に想像できるでしょう。そのため、一般的にはゾーンの参加人数をサーバーの能力に合わせた人数に制限し、かつ、セッションはリアルタイムに進行するけれどブラウザ上のリアルタイムは保証しないことで、レスポンスを維持しています。
次に、これらゾーン管理およびセッション管理の、具体的な実現方法を説明しますが、これは大半の部分がインターネットでのアクセスを高速化するための基本的な考え方と同じやり方になります。
一般的なWebサーバーにアクセスする場合、まず、ブラウザとサーバー入口との間の問題があります。サーバーの中に入ってからは、コネクションと言われる接続の問題、アプリケーションサーバーの問題、データベースサーバーの問題等々が存在します。
ブラウザとサーバー入り口の間の問題とはいわゆる通信速度です。ADSL環境と言えども、アクションゲームのように画像情報自体を通信でやり取りしていたら、全く使い物になりません。そこで大半のゲームはフラッシュプレイヤーのようなサーバーとは独立したアクションコントロール機能を持ったプラグインのソフトを利用することで、オンラインを感じさせないゲーム専用機並みのレスポンスを実現しています。
次のコネクション問題ですが、これはインターネット特有の問題です。インターネットと言う通信の仕掛けは、耐障害性の考え方から1回1回のアクセスをすべて独立した通信として扱われます。そのために、いわゆるコンテキストを維持するためのクッキーのような仕掛けを利用しますが、クッキーとはあくまでブラウザの仕掛けです。サーバー側としてはコネクション周りのハードウェアを利用して、ロードバランシング、バッファリング、使いまわしなどでスループットの向上を図ります。
次にアプリケーションサーバーの問題です。通常はゾーン単位にサーバーを割り振るような仕掛けになるのですが、別の理由からサーバー自体の台数がアプリオリ(あえて言えば営業予算的)に決まりますので、結果的に1台のサーバーにそのサーバーの能力に応じた数十から数百のゾーンが割り当てられることになります。結果的に1台のアプリケーションサーバーで、場合によって千単位のセッション管理が必要になります。これに当然、1台2、30万のサーバーではサービスが不可能で、数千万のサーバーが割り当てられます。
残りのデータベースサーバーの問題は、DBエンジン開発ストーリー6に書いたように、通常の仕掛けではサービスの限界があり、同時にサービスを実現するためには前述のような高価なサーバーが欠かせません。
これらを、SunやIBMが、グリッド技術などを駆使して取り込もうと言うのが、前回のエントリーに取り上げたオンラインゲーム市場を狙う大手IT企業の思惑の記事だったのです。 KAI
ASPサービスとDBエンジンの関係
この話の冒頭にも触れましたが、私たちはASPサービスをやっています。
ASPサービスとは、会員企業向けにインターネット経由で私たちが開発したアプリケーションを利用できるようにするサービスです。
具体的には、APサーバー上にユーザー毎の環境が準備され、これを、それぞれのユーザー毎の複数のクライアントがブラウザから入って利用することが出来るようになっています。共用サーバーを前提にしたコースの場合、1台のAPサーバーに平均40ユーザー(会員企業)、100クライアント(接続台数)が繋がっています。
もし、このアプリケーションのDBMSをOracleにしていたら、私たちは大変な額のライセンス料を支払う必要があり、当然月額利用料にも反映させざるを得ません。
これは大きなアドバンテージであるのですが、それだけではありません。
私たちのDBエンジンは非常にシンプルに出来ています。1台のサーバー上で、アプリケーションが何本同時に立ち上がっていても、DBエンジン自体の消費するメモリーは必要最小限のアプリケーション毎のバッファメモリーだけです。
ですから、あまり大きな声では言えませんが、APサーバーもDELLから通販で買った最低限のスペックのマシンでも十分なパフォーマンスが出ることになります。結果的にこのことも月額料金を低く押さえることが出来る大きな要因なのです。(1回目に梅田さんのBlogに触れたのもこのことです)
ウォーラブルコンピューティングの世界
私たちのプロジェクトは、2015年私たちの世界はどうなっているか、を考えることからスタートしました。ホームページの中のkaiレポートで書いた
「西暦2015年のオフィス、家庭、お店を想像してみて下さい。そこら中の壁がモニター化しているのが見えませんか?(これを私はウォーラブル(wall+able)コンピューティングと呼んでいます)
そうです、2015年には壁一面がモニターになっていて、私たちは、このパーソナル化したモニターを通して、コミュニケーション、エンターテイメント、エデュケーション、メディカルチェック、ショッピングなどに、1日の起きている時間の半分以上を費やしているはずです。
このモニターの中の世界を、現実世界のリアルランドに対するもう一つの世界、アナザーランドと呼びます。」
この世界のインフラとなる製品を作りたいという、夢を実現させるプロジェクトです。
この世界では、コンテンツとソフトウェアが融合した様々なサービスが開発され、提供されています。ここに、私たちが開発したDBエンジンとアプリケーションがどう繋がっていくのか、未だ定かではありませんが、しかし、着実に一歩一歩近づきたいと思っています。 KAI
2002年−2004年
「500台のマシンの接続」を目指して
現在、DBエンジンの更なる改良に取り組んでいます。
その一つは「500台のマシンの接続」です。
4回目にも触れましたが、DBエンジンの性能の良し悪しはこの接続台数にあります。
コールセンターなどの環境で使用する場合、今まで想定する台数はせいぜい100台規模でした。ところがIPセントレックスの普及で500台規模のコールセンターも現実味を帯びてきています。
更にWebサーバー上で動作する場合は、同時に何万アクセスも考えられるため当然その負荷分散が行われるものの、更新系の場合は詰まるところ1台のDBサーバーにアクセスが集中します。
こういった使用方法に対応できるように、当面の接続台数の目標を500台と定め、技術開発を行っています。
この開発のポイントは、APサーバーとDBサーバー(キャッシュサーバー)との間の接続方法の一点にあると考えています。現状のTCP/IPによるLAN接続ではトランザクションの偏りを解消することができません。こういったことを解決するために、SANのようなクローズドシステムではなく、あくまで世の中で流通しているオープンな技術の上に構築していきたいと思っています。 KAI
2000年−2001年
DBエンジンの要の機能と言えば、それは排他制御と言われる、データベースへの同時アクセスの制御です。
何十台のクライアントマシンから同じテーブルに対して更新がかかると、他のマシンの要求を待たせた上で1台ずつ順に要求を処理していく必要があります。ここらへんをいい加減に作ると、ACCESSの初期のバージョンのように原因不明のデータベースの破損が発生します。
私たちのDBエンジンも、このデータベースの破損に見舞われました。
破損と言っても様々な現象があります。
初期の頃は、排他制御を行うための基本の機能であるロックが効かないために同じ出荷番号が採番されるという現象で、本来別々の伝票にならなければならないのに、一つの伝票になってしまうと言うものです。この欠陥は致命的です。こんなことが起きてしまえば、全く使い物にはなりません。
よくよく調べると、ロック機能がおかしいのではなく、コミット命令というWindowsAPIが機能していないことが判明しました。それが判ったのはいいのですが、替わりのAPIが見つかりません。試行錯誤の末、別のAPIで問題が起きなくなることが判りました。問題が起きてから解決するまでの1ヶ月間、ほとんど寝るまもなく調べ続けました。
そして、数十台規模の運用で、最後まで残った破損の現象がインデックスの破損です。
このストーリーの2回目にも出てくるインデックスが、突然おかしくなる現象です。どうおかしくなるかというと、2回目の話でIBと書いたインデックスブロックの一つの中身が、突然まるで関係のない別の内容に置き換わってしまうのです。
これには参りました。全く手がかりがつかめないまま1年以上が経過してしまいました。その間、大規模ユーザーの環境で2ヶ月に1回くらいの割合で発生します。
DBエンジンの完成
これも試行錯誤の末、手がかりを掴みました。2001年1月のことです。
3回目に書いたようにリエントラントな構造にするために、必要なメモリーはすべてdllの中で動的に確保し、それを、呼び出し側から渡されるポインタが指すエリアに格納していました。
この動的にメモリーを確保するAPIが、先のコミット同様機能していないのではという結論でした。リターンコードと呼ぶAPIからの戻り値はゼロ(正常終了)であるにもかかわらず、実際にはメモリーが確保できていなかったのです。何らかのタイミングで何兆回に一度の割合で発生する現象です。
IBを読み込むためのバッファと言われる領域も、当然動的に確保していました。その領域が、実は実際には確保されず、全く関係ない領域を使用していたために、せっかくバッファの内容を更新しても実際に書き込まれる内容が別の内容に置き換わってしまうと言う現象だったのです。
原因が判れば対策可能です。
メモリーの確保は、すべて動的に確保するのを止めて、呼び出し側に最初からマックスの静的メモリーを持たせることで、そのメモリーを使い廻す構造にコードを書き換えたのです。
すぐ対策版を組み込んで内部で入念なチェックの後、ユーザー環境に入れました。これから2ヶ月間、インデックス破損が発生しなければ対策できたことになります。
その期限であった5月31日までの間に、1件のインデックス破損も発生しませんでした。
bisonと私は、8年前とは違う、西麻布のとあるバーのカウンターで二人だけの祝杯を上げました。 KAI
1998年−1999年
1998年1月、約5年を掛けて開発したアプリケーションの製品版を出荷。DBエンジンも最新版を組み込んでいます。
製品版を出荷しても、新たな機能追加と不具合の対策は今まで以上です。この年から翌年にかけてが、アプリケーション、DBエンジンとも開発で一番苦しんだ時期です。
DBエンジンに限っても、ユーザーが増えるに従って様々な環境で使用されるようになり、想定外の現象が色々と発生し、一つ一つ原因を究明して対策していかなければなりませんでした。
私たちが開発した製品は、アプリケーションと言っても企業の基幹の業務に使用するもので、DBエンジンの不具合により業務が停止してしまえば、企業の業績そのものに致命的な影響を及ぼしてしまいます。担当する技術者たちにはこれが無言のプレッシャーとなって、体調を崩すものもいました。
しかし、逆にこのプレッシャーがあったからこそ、これだけの品質、信頼性を要求されるDBエンジンを完成させることができたのだと思います。
50台のロードテスト
それは1999年年明け早々でした。事務所の一室に、50台のマシンが並んでいます。そのマシンの前に座った50人のオペレータがセーノ、ドンで一斉に登録実行ボタンを押します。登録が終わるとその場で手を挙げます。最も早いマシンで2秒、遅いマシンで20秒台。
これは、その年の夏、本稼働を予定しているコールセンター向けのロードテストです。一つの登録の処理を50台が同時に行う確率はきわめて小さいですが、こういった場合でも十分なレスポンスが得られるか、本番前に試験しておく必要があります。
20秒台であればまずまず合格です。
こうしていよいよ、数十台同時運用の本番が始まりました。 KAI
ほんとにCNETのBlogは為になるBlogです。
渡辺聡さんが「全てはIPに乗って(2)」の中で
「うっすらと予見出来るマーケットの変化の中でキープレイヤーとして考えられるのは、物理的にではなく、電子的にネットワーク、コンテンツを管理出来るプレイヤーである。」
と書いていますが、全く同感です。
コンテンツをアプリケーションと渾然一体となったサービスとしていかに開発できるかがキーポイントだと私は常々考えています。この話もこのストーリーの最後に具体的に書ければと思います。(宿題が増えてきて大丈夫か?)
さて、開発ストーリーに戻ります。
1996年−1997年
いよいよ試作版を元に、VCに書き換えなければいけません。
1996年の4月頃外部の人間に依頼しましたが、結局できあがらず、元の担当者のK君が仕上げて10月頃完了しました。当初アプリケーションのリリース予定であった1996年12月にぎりぎり間に合わせたという状況です。
そのアプリケーション自体は、遅れて、翌年の4月にやっとベータ版をリリースしたのですが、これ以降、実際のユーザーの元でDBエンジンが試されることになります。
1997年9月、担当者がK君から現在の担当であるbisonに変わりました。
bisonが早速着手したのは、全てのコードの見直しです。DBエンジンはdllと呼ばれるリエントラント(dllを実際にチェックしたところ厳密な意味の再入可能にはなっていないようですが)な常駐プログラムとして動作しますが、これに対応できていなかったからです。
クライアント側で動作する場合、リエントラントでなくても当初は問題ないのですが、現在のアプリケーションサーバーのような使い方をすれば一発でアウトです。
そのためには、dll側には一切スタティックなメモリーを持たず、呼び出し側のポインタですべて管理できるようにしなければなりません。この作業自体はbisonががんばって3ヶ月くらいで完了しました。
この作業が6年後、大きなアドバンテージとして報われることになります。
1998年1月、いよいよ製品版の出荷の時です。 KAI
1994年−1995年
1994年10月、約1年掛けて試作版ができあがりました。
これはVBで書かれたもので、性能的に実用に耐えるものではありませんでしたが、それでも、DBエンジンが備えるべき機能とそのアルゴリズムを検証するには十分でした。
当時のOSは確かWindows3.1だったかと思いますが、この上で動くアプリケーションを開発するのに言語はVBを選択しました。開発予定の画面数が数百画面を想定しており(実際には1200画面以上になりました)工数削減を考えてのことです。(この選択で、あとからずいぶん泣かされることになりましたが)
このアプリケーションに組み込んで更に1年掛けてテストを繰り返しました。
1995年8月頃だったと思います。アプリケーションの開発も進み、いよいよ大量データによる本格的なテストを始めた矢先、とんでもないことが起きてしまいました。
同一キー値のサーチ問題
いわゆる同一キー値のサーチ問題と言われるもので、テスト中に突然アプリケーションがダンマリになってしまい、原因を調べるとDBエンジンがループしているように見えるのです。何分かすると回復するのですが、これでは使い物になりません。
私たちのDBエンジンは、木構造と言われるインデックスを採用しています。このインデックスは、インデックスブロック(IB)という単位で階層構造になっていて、IBにはキー値と下位のIB番号が昇順に格納されています。一番下位のIBに実際のデータのレコード番号を持つという構造です。IBの階層も、数千万レコードのデータベースでもせいぜい10階層もあれば管理できるシンプルな構造になっています。
通常のサーチの場合、目的とするキー値を指定することにより、IBを検索することで同じキー値を持つ目的のレコードを高速に見つけることができます。
ところが、1レコードの内容を更新する場合は、キー値だけでなくレコード番号も指定する必要があります。キー値だけでは同一キー値を持つレコードの特定が出来ないからです。そこで問題になるのが、このレコード番号が最下層のIBにしか格納されていないと言うことです。
試作版のこのロジックを調べると、同一キー値の場合、先頭のレコードから一つ一つレコード番号を最下層のIBまでたどって比較していました。もし値がセットされていない項目のインデックスの場合、何万レコードすべてがスペースという同一キーになっていますので、結果、全件検索と同じ動作になってしまいます。
さて、これをどう直せばいいのか。
すぐにバイナリーサーチというアルゴリズムを応用すればいいのは分かったのですが、階層構造の中の最下層の値のバイナリーサーチというのは初めてです。
10月の頭からアルゴリズムを考え始めて11月の終わりまでかかりました。
すぐにコード化してテストすると、ものの見事に、ループすることなく高速に動作するようになったのです。その後一箇所ロジックを修正しただけで、今も立派に働いてくれています。 KAI