skip to main |
skip to sidebar
小沢幹事長不起訴に関する気になる2つの書き込み。(2NNより)
これはヤミ献金、賄賂事件だと勘違いしていたが、石川議員が逮捕された理由は実は収支報告書の虚偽記載違反だった。
収支報告書は一年に一回、ちょうど今頃提出されるもので、お金の出し入れはすべて記入しなければならない。
事件の概要はこうだ。
小沢さんの秘書たちは、銀行から借りて土地を買ったが、お金が下りるまで小沢さんに立て替えてもらった。
そして、すぐに返したのだが、そのことを収支報告書には記載しなかった。
1年の入金と出金だけ見れば結果的に同じことなので、小沢さんから一時的に借りたことを省略した。
なぜなら、小沢さんが大金を持っているのはイメージ悪いので隠したかったから。
これは嘘をついたことになり、虚偽記載違反となる。そういう罪で逮捕されて明日起訴される。
小沢さんが起訴されないのは、秘書に嘘をつくよう指示をしたり、関与した証拠が見つからなかったから。
今日のニュースはとても意外だった。
ゼネコンの捜索や2回の事情聴取を見て、検察は絶対何か証拠を掴んでると思っていた。
ヤミ献金の動かぬ証拠、起訴できる十分な証拠をもってるからこそ、捜索やら聴取やらをやったんだろうと。でもそうじゃなかった。
そもそも、その頃は野党だったので収賄罪にならないそうだ。え=っ!
検察の捜査の目的は、政治規制法違反容疑、つまり、「お金を一時的に借したことを記載しないよう指示した」証拠をつかむこと。
それが、そんなに重要なことかよ。
総務省 政治資金監査に関するQ&A(その4) 資料3
http://www.soumu.go.jp/main_content/000037209.pdf
収支報告書の記載方法に関すること
Q 政治団体の事務職員が立替払いで物品を購入し、その後、政治団体から物品購入相当分の精算を受けた場合は、支出の年月日及び支出を受けた者はどのように記載することになるのか。
A 政治団体の事務職員が立替払いで特定の物品を購入し、その後、政治団体から物品購入相当分の精算を受けた場合は、この精算は、政治団体内部の事務処理として、政治団体の事務職員に渡したものであると考えられます。
したがって、支出を受けた者は、事務職員ではなく、物品を購入した相手方が記載され、また支出の年月日は、物品購入時点が記載されることになります。
総務省自身が立替え処理を認めてるのに、検察はどうやって石川を【虚偽記載】で立件するの???w
たぶん、都合のいいように事実を曲げて書いたという悪意があったから。また、それを自供したことが大きなポイントかな。
法というのは、形式的なことより、事実などから読み取れる意図、特に悪意があったかどうかが重く見られるらしい。
中島御大から返事があった。
本当は、ホメオトシスのスレッドで、竹嵜さんをネタに、北城さんとの昔の顛末を書いてやろうと思っていたのです。
竹嵜さんの勤務時間に対する当時の鷹揚さ(?)が北城会長の眼に触れて、アドミ専門のスタッフを付けられそうになった話です。中島には管理能力が全く無い、というご判断をなされたらしい。
勿論それで研究所長を首になったわけではありませんが。。。
Scale OutアンチテーゼとeCloud構想:中島の考え
(; ̄ー ̄川
どうも、すみません。
(そんなことが起きていたなんて全く知らず)、当時のIBMは本当に懐が深かったなあ、なんて勝手に思っていた。単に、中島さんに甘えていただけだったとは。とにかく、当時のIBMは、めっちゃ遊び働きやすかったことだけは事実であった。
さて当時、中島さんは毎月の全体MTGで、いつも感動的なプレゼンをしてくださっていた。技術に裏付けられた論理、情熱、パワーにいつも圧倒されたが、一方で、机上の空論を嫌い、技術論だけでなく、ビジネスの重要性も説かれていた。技術要件と現実のあまりのギャップに戦意を無くしてしまうことも多かったが、脱力感を感じつつ毎回感激していたことも事実であった。特にすばらしかったのはIT動向で、5年~10年後のIT世界を、まるでタイムマシンで見てきたかのように具体的に話をされた。未来を妄想するのはとても楽しい。でも自分たちがIBMのイノベーションに一役買っていると思うともっと楽しかった。やりがいも感じていたし、本当にすばらしい会社だと思った。
でも、中島所長が本社の方に移動されてがっくりきたというか、モチベーションが無くなった。私にとって中島さんは5年~10年後の世界を教えてもらえる神のような、あるいは、北極星のような存在だったので、移動されてしまったことで方向性を見失ってしまい途方にくれた。まるで、たこの糸が切れたようにヒュルヒュルとなってしまった。
それでも、箱崎の方に移動させてもらい、2,3年は田原さんや米持さん達と好き勝手に過ごせたので楽しかった。その後、部署が解散、また幕張に戻されて、くだらない業務報告レポートばかり求められたのでやめることにした。仕事は無いのだが、自分がいかに有益な仕事をしたかを、毎週、妄想をかきたてて書かなければならない。私は、一日中、PCの前に座って誰と話すわけでもなく、ガマガエルのようにう~んと唸っていただけなので何も思いつかない。出てくるのはガマの汗だけ。不思議だったのは私と同じように全然仕事をしている雰囲気じゃなかった方達も毎週立派なレポートを書いていたこと。これはある意味すごい才能だと思った。私は罪悪感に苛まれて、こういった類のことがどうしてもできない。まあ不器用な人間である。今思えば、IBM社員で私ほど上司にレポートしなかった人間はいないんじゃなかろうか。(ところで、中島さんが上司にレポートしませんといった話は面白かった。レベルが全然違うけど、なんだ私と同じじゃん、と思った)
中島所長が本社の方に移動されてモチベーションが下がったことも、私がIBMを離れた理由の一つだが、(念のためいっておくけど首になったんじゃないよ)インターネットの普及で情報元に困らなくなったことも大きかった。
もうIBMから学ぶことはなくなったと思っていたので、いつやめてもいいと思っていた。それまで、SIプロセスも2,3回やって設計開発やプロジェクトリーダも経験した。また、自分一人でセリングをやって、割と大きな案件を成約させたりもした。しかし、IBMの情報元からは離れたくなかった。
当時までイノベーションリーダは間違いなくIBMだったと思う。ITの動向を知るにしても、お客様対応するにしても、社内の情報を見なければ解決しなかった。なので、IBMの情報にアクセスできるという優位な立場は、離れられない大きな理由の一つであった。
しかし、だんだんとインターネットに依存してくるようになり、あるとき、ふとIBM社内の情報は必要ないということに気づいてしまった。それから独立しようかなと考えるようになった。
久しぶりに、中島さんの話を聞いて感じたのは「戦意喪失感」。ああ、昔感じたこの感じ。まるで映画のエンディングを先に聞いてしまったかのような脱力感。やっぱり、あのサイトは見ないほうがよかった。昔はあまり思わなかったけど実は中島さんはネタばれすることで人の楽しみを奪う悪い人なのかもしれない。
それは絶対正しいのだけど、中島さんは、これまでも正しいことをおっしゃってこられたけれども、何か受け入れられないモヤモヤがある。でも反論の余地はないから、歴史が証明するのを待つしかない。(反論を思いついたらまた書きます)
一発逆転ホームラン願望に満ちた中途半端な自由人の私は、悲しいかな、丸山先生に感化されて夢遊病になってさ迷うか、中島さんに感化されて戦意喪失してしまうかのどちらかしかない。
まあ、いずれにしても楽しいことに変わりないのだが。(なんだ楽しいのかよ!?)
Scale Outがクラウドの本質ではない!?
ちょっと古いが、2008年10月に、クラウドの本質と動向という記事のなかで、1.スケールすること、2.安く利用できることがクラウドの本質であると書いた。大量のコモディティサーバを用意して分散KVSを配置することでスケーラビリティとアベイラビリティを確保することが基本で、プライベートクラウドは、この考えを企業内に応用したものである。
これに対するアンチテーゼとして最近よく耳にすることは、サーバ単体の能力は十分に大きく、その能力を超えて処理しなければならないような大規模なケースはあまりないのではないかということ。真偽はわからないが、ムーアの法則が十分に成り立っており、CPU処理能力向上は将来においても続く見通しであることも背景にある。
約5,000万PV/月くらいのサイトまでなら、アプリケーションサーバ1台で捌ける(ウェブアプリケーションサーバを複数台構成とか2010年代には流行らない)
一般に、クラウドといえばCAP定理などに象徴される、超大規模な分散ストレージについての話になりがちだが、そんな最先端の基礎理論が必要になるのはトップ1%のなかの1%ぐらいのサービスで、世の中のほぼすべてのサービス開発者にとって、むしろクラウドの恩恵というのは以上のように一見地味な進化の中にこそあるのである
スケールアウトからスケールアップへの回帰
また、クラウド・プラットフォームの不特定大量のプロセッサー資源をエラスティック(柔軟)にプロビジョニング(配置)して効率よく資源活用することが最大の効果であり、全体の最適化によりコスト削減を実現する仕組みの方が重要との意見もある。
scalabilityやスループットの高さよりも、すべてのアプリをpartition-tolerantに書くよう強制して巨大インフラに細粒度で集約し、桁違いの全体最適を実現できることが重要と思う。でないと大規模サービス以外はあまり必要ない>NoSQLとかKVS(App EngineやNoSQLはスケーラブルだからエラいのではない)
プライベートクラウドでも、リアルタイムに、必要なITリソースを調達できるメリットが強調されている。
海外で、ある金融機関に監査が入り、顧客の口座データや資金の動きをバッチ処理し、異常がないかを調べることになったという。期限は3日後。数十台のサーバが必要だが、今からIT部門にリソースを要求しても、とても間に合いそうにない。
そこで、この金融機関の担当部門はAmazon EC2を使ってバッチ処理を行った。それを知ったCIOは激怒した。重要な口座データをインターネット経由のパブリッククラウドで処理するなど、とんでもないと。ところが、担当部門の責任者は、「リソースをすぐ使えるよう準備していないIT部門の方が怠慢」と逆切れ。これを教訓に、この金融機関はプライベートクラウドを導入したそうである。メリットを共有する「業界クラウド」の可能性--IBMに聞くプライベートクラウドの価値
しかし、全体の最適化もそうだが、システムの規模が大きくなることで運用コストも増大する。特に、プライベートクラウドの経済性についての疑問は大きいようである。
プライベートクラウドは、正しい方向への第一歩のように感じるかもしれないが、しかし規模の経済としては、プライベートクラウドは本当のクラウドコンピューティングの効率性に遠く及ばない。何が違うか? 規模、共有されたリソースファブリック、高いリソースの利用率でこそよいサービスが低コストで提供できるのだ。
つまりHamilton氏はプライベートクラウドはパブリッククラウドと比べて効率性もサービスレベルも悪く、しかしコストは高い、といった点を突いているわけです。
プライベートクラウドに未来はないのか?
プライベートクラウドの価値
ところが、まったく逆の発想もある。
私たちのJEANSは、アプリケーションと基盤を疎結合化し、サーバー・クラウドなどの最新技術でアプライアンス・フレームワークを構築する企業システム革新への提案です。日本のお客様のIT変革を阻む大きな要因として、IT環境における強い安定志向と、それを達成するための案件個別のきめこまかな非機能要件(NFR)の作りこみが考えられると思います。この密結合に起因する変化対応能力の課題を解決できれば、グローバルな競争を凌駕する開発、保守、運用の革新を起こすことができると考えます。アプリケーションと基盤をNFRにフォーカスして疎結合化するために、新しくアプライアンス・フレームワークを設計し、いろいろとお客様実環境での実証性をスタディしたいと考えています。ミッションクリティカル環境にフォーカスし、仮想化技術やクラウド・コンピューティング技術を最大限活用してこの構想の実現をめざしています。”eCloud研究会” 参画について.JEANSの背景
Googleはあれだけの規模のデータセンターを少ないコストで運用できているのだがら、運用コストの削減はたぶん可能だと思う。そういった技術を企業システムに応用することのメリットは計り知れないだろう。
この提案で驚いたのは、開発コストにまで言及している点である。現在、IT投資の70%以上が運用系に費やされており、その原因が非機能要件(NFR)の作りこみの現状があるということ。この構想では、もう一度プラットフォーム側の可能性を見極め、そして、(HWではない)アプライアンス・フレームワークによる解決を試みる。つまり、NFR作りこみが必要ないぐらいの高度なプラットフォームを専用で用意(≒アプライアンス)することで、業務アプリは非常にシンプルにできる。そうなれば、3K,4Kといわれる酷いシステム開発の現状を打破できる。
CAP定理を超越した発想
CAP定理は、Consistency, Availability, Partitionsを同時に満たすことができないという有名な定理であるが、中島さんは、「Consistency, Availability, Partitionsは全て満足した上でスケールアウト環境での高性能を出さなければならない」といわれているように、CAP定理を根底から覆すような発想をしておられる。今に始まったことではないが、中島さんは、ある意味無茶苦茶な方である。
さて、スケールアウト構成での最も重要な課題はデータの信頼性、一貫性、即ちConsistencyです。プロセッサー・ベルの技術用語ではCoherenceです。クラウドレベルのレイヤーの議論になると、CAP定理とかBASEだとかの主張の下、ACIDが出来ないならアプリケーションで緩めてもいいじゃん、というようなWS-*(Web Service astar)前夜の議論が当たり前のようになっていますが、ハードウェア・レベルではそれは絶対許されません。そんな事が簡単に許されるならSUNが ROCKチップに失敗してギブアップする苦渋など無いわけです。CAP定理の逆、すなわち Consistency, Availability, Partitionsは全て満足した上でスケールアウト環境での高性能を出さなければならない。それがコンピュータ本来の、HWの基本です。SWとHWの話をゴチャゴチャに論じているように見えるかもしれませんが、ROCKが火を点けたTransactional Memoryの技術はその風景にあります。
さて、Hot Chips 21でクレームされているPOWER7のこの面での潜在能力、アプローチは中々凄いと思います。確かに Intel Nehalem-EXのQPIによる大幅な性能向上は驚愕です。しかしそれを超えて、POWER7で主張されているPOWER6に対する有効 Compute Throughput 5倍(1.6TB/s)のメッセージは大きい。これはフィールド・アップグレード等の面で、POWER7がPOWER6の足回りを基本的に受け継いだ以上物理的なチップI/Fの性能向上だけでは達成されないターゲットを、eDRAMのオンチップ搭載も含めた数々の技術革新によってクリアしようとしている点でIBMらしい味が感じられます。
ちなみに、クラウドでは、「ScalableでAvailableで、かつ、Eventually Consistentなシステムは可能である。」というように、Cの部分を緩くすることで、3つをほぼ同時に満たすことを目指している。この命題の実現こそが、現在のエンタープライズ向けのクラウド・システムが目標としているところなのである。
ところが、中島さんは、Eventually Consistentはナンセンスだとおっしゃっている。Googleを否定するわけではないが、ill-structuredだと。利用者側の対応に任せられてしまうことのデメリットの方が大きいと感じられているようだ。これはもっともなご意見である。
またレプリケーション型のデータ・モデルでデータ整合性を担保するためには、アプリケーション層で 3-Phase Commit 相応の最終的なコミット・コントロールが必須だ、というところでしょうか。プラットフォーム側の厳密さに期待できないという点でill-structured なわけですね。利用者側の対応に任せられてしまうということです。逆にこの ill-structured さがグーグルのスケールを可能にしているわけですから、”角を矯めて牛を殺す”ことがないようにもしなければならない。
これを”出来ない論議”で終わらせないためにプライベート・クラウドの主張があるわけですが、このアプローチに対しても出来ない論が強くあります。現行のきめ細かにカストマイズされた多様な NFR (Non-Functional Requirement) 構築に対応出来ないというのも大きなクレームです。
しかし私は疑問を抱かざるを得ない。
複雑さを考える---Complexity Quanta and Platform Definition
Summary of Jim Waldo‘sKeynote at the 10th Jini Community Meetingでいわんとしていることは、「それぞれの段階を通り抜ける際、我々は、何かを失う」ということ。
何も失わずにすべてを手に入れることなんて可能なのだろうか。これはとても難しい命題のように思える。
昨日、"eCloud"というリスティング広告に引っかかって、中島御大のサイトを発見した私であるが、とりあえず見なかったことにしようと思う。
(リタイヤされた元上司のサイトを半年もたってやっと見つけました。連絡ぐらいくれればいいのに。)
マルチ・スレッドへ:我々は、順序を失う(複数のことが同時に起こる)。これは、難しい。なぜなら、我々は、自然には、シーケンシャルに考えるから。
マルチ・プロセスへ:単一のコンテキスト(すなわち、我々が信頼しうる共有コンテキスト)を失う。グローバルな状態が、開発のあらゆるところで利用される。(すべてをスタティックに考えよ)
マルチ・プロセスからマルチ・マシンへ:我々は、状態を失う。「システム」のグローバルな状態というのは、虚構である。興味深い分散システムには、整合的な状態というものは存在しない。(Lamport:http://research. microsoft.com/users/lamport/pubs/pubs.html)分散OSのプロジェクトは、グローバルな状態を導入しようとしたが、大々的に失敗した。
信頼できないマルチ・マシンたちへ:誰を信ずることが出来るか分からない難しい状況の中で、我々は信頼を失う。
しかし、我々は何かを得てきた
Seq to MT: 並列処理
MT to MP: プロセスの分離(安全を与える)
MP to MM: 独立した失敗(何かまずいことが起きても、システムの部分は生きのこる)
MM to MMU: スケール(webスケール、インターネットスケール). 誰か他の人のリソースを利用せよ(あるいは、他の誰かが、我々のリソースを利用することを認めよ)
Google Docsのオンライン・ファイルストレージ機能
先日、Google Docsにオンライン・ファイルストレージ機能を追加するという発表があった。画像・動画、ZIPファイルなどあらゆる種類のファイルをGoogle Docsで保管でき、アップロードしたファイルは検索機能や共有フォルダ機能の対象にもなる。アップロードできるファイルのサイズは1つにつきMAX250MB※までだが、全体の容量の制限はなく、1GBまでは無料である。それ以上は追加で購入できる。ストレージの値段は、現時点で20GBが5ドル/年だが、Google Apps Premier Editionユーザーに対しては、1GB=3.50ドル/年で今後数ヶ月以内に提供する計画とのこと。
(※ MAX1Gに変更された。2010/1/28)
Documents List API: Upload any file and more (1/12/2010)
ついにGDrive実現、「Google Docs」に オンラインストレージ機能
全文検索の話
Documents List APIの一番大きな目玉はなんといっても全文検索APIである。Protocol Guide (v3.0)で「Performing a full text query」が New になっていないところをみると、もともとあった機能のようだが、今回から容量制限がなくなり、XMLやテキストファイルを登録できるようになったことで、やっと実用的になったのではないか。(サンプルプログラムによる検証を参照)
本題に入る前に、これまでのGAEにおける全文検索の実装方法についてまとめてみる。
1) DatastoreのPropertyIndexを利用する方法。これは、完全一致か前方一致しかできず、長さもStringの500バイトまでが上限。(Text型だと1MBまで格納できるがIndexを張れない)。使用するStrageの容量は格納するデータサイズの1倍以下。
2) N-gram検索。これには2つの意味がある。(①と②のb.は区別する)
① 転置インデックスのキーの切り出しを、辞書や構文解析に基づくのではなく、単に一定の文字数で切り出した語を入れる方法
a.ユニグラム = unigram (1文字単位)
b.バイグラム = bigram (2文字単位)
c.トリグラム = trigram (3文字単位)
② 分かち書きで切り出す方法
a.形態素解析(いわゆる転置Indexの実装)
b.N-gram(GoogleやYahooなどが採用している直前の(N-1)個の単語を見て、次の単語を予測するモデル(参考)
SuffixArrayは①のユニグラムと同等のものとなる。漏れはないが、データ量は膨大になる。nが単語のサイズとして、n+(n-1)+・・・+1 = (n+1)*n/2。また、nの最大は500バイトまで。
②の形態素解析でよく使われるロジックは、KAKASIや、TinySegmenterなどがある。ちなみに、TinySegmenter Java版の実装はココにある。
GAEにおいて現実的な実装と思われるものは、①のSuffixArrayと、②のTinySegmenterだろう。①はデータ量が膨大になることと、最大サイズが500バイトまでなので、長い文章には向かない。②は長い文章でも大丈夫だが、分かち書きの精度に問題があって、使い物になるかどうかはよくわからない。
Google Documents List Data APIの精度は、検証結果からみて②のb.ではないかと思う。とてもよい品質なので、これで十分だと思われるが、漏れが完全になくなるわけではないので、完全性が必要な項目にはSuffixArrayを使うとよいと思う。
注意点としては、Google Apps Premier Editionユーザーでないと、Documents List APIを使えないこと。ストレージの値段がGAEよりも2倍ほど高くなり、現在はまだストレージを追加購入できない。
サンプルプログラムによる検証
- Google Docs Serviceの生成と認証
DocsService service = new DocsService(appName);
service.setUserCredentials(user, pass);
- Google Docsの全文検索
URL feedUri = new URL("https://docs.google.com/feeds/default/private/full/");
DocumentQuery query = new DocumentQuery(feedUri);
query.setFullTextQuery(word);
DocumentListFeed feed = service.getFeed(query, DocumentListFeed.class);
- ポイント
- テキスト形式(text/plain)が対象
- Google Documents List Data APIを使用してアップロードしたmimeType="text/plain"のXMLファイルは検索対象となった。
- Google DocsのページからアップロードしたXMLファイルは検索対象とならなかった。
- Google DocsのページからアップロードしたTXTファイルは検索対象となった。
- Google DocsのページからアップロードしたExcelファイルは検索対象とならなかった。
- インデックス生成
- 検索ワード
- 「半茹で冷凍又は・・・」という文字列について
- 「半茹で」はヒットした。○
- 「半茹」はヒットしなかった。×
- 「冷凍」はヒットした。○
- 「冷凍又」はヒットしなかった。×
- 「冷凍又は」はヒットした。○
- 「東京都調布市深大寺東町1-XX-X」という住所文字列について
- 「調布市」はヒットした。○
- 「深大寺」はヒットした。○
- 「深大寺東」はヒットしなかった。×
- 「東町」はヒットした。○
- 「東町1」はヒットした。○
XMLファイルをGoogle Docsにアップロードする。
- Google Docs Serviceの生成と認証
DocsService service = new DocsService(appName);
service.setUserCredentials(user, pass);
DocumentListEntry uploadedEntry = uploadFile(service, fileName, title);
- Google Docsへアップロード
public DocumentListEntry uploadFile(DocsService service, String filepath, String title)
throws IOException, ServiceException {
File file = new File(filepath);
//String mimeType = DocumentListEntry.MediaType.fromFileName(file.getName()).getMimeType();
String mimeType = "text/plain";
DocumentListEntry newDocument = new DocumentListEntry();
newDocument.setFile(file, mimeType);
newDocument.setTitle(new PlainTextConstruct(title));
return service.insert(new URL("https://docs.google.com/feeds/default/private/full/"), newDocument);
}
- Googleのサンプルにあった
String mimeType = DocumentListEntry.MediaType.fromFileName(file.getName()).getMimeType();
を実行すると
java.lang.IllegalArgumentException: No enum const class com.google.gdata.data.docs.DocumentListEntry$MediaType.XML
とエラーが発生する。
- mimeTypeを"text/xml"に固定で設定すると
com.google.gdata.util.InvalidEntryException: Content-Type text/xml is not a valid media type.
アップロード時に上記エラーとなる。
"application/xml"でも同じくエラー。
- "text/plain"で正常にアップロードできた。
その他
- EUC形式のXMLファイルをアップロードしたが、その後ブラウザからダウンロードするとUTF-8形式に変換されていた。
またXMLの括弧"<"">"が、"<<"">>"に変換されていた。
- アップロードのURLにパラメータ"?convert=false"を付けると変換なしにアップロードされる。
ただし、全文検索対象とならない。
- 登録はconvert=trueで行い、取得についてXMLの括弧"<<"">>"を"<"">"に変換するのが妥当か?
成長戦略がほしい
現政権は成長戦略を描けていない。社民連出身の菅さんを筆頭に、労組などを出身母体としている政治家が多いので、どうしても「人に優しく、産業に優しくない」発想になりがちである。人に優しい政策は結構であるが、日本の産業がとても弱っており、財源を含め合理的な策が見い出せないのが問題だと思う。
人に優しい政策には大きなコストが伴う。それは、例えば、CO2削減は企業が、介護は国民が負担することになる。(介護ビジネスというのは局所的には成り立つが社会全体からみるとコストとなる。私は、麻生さんの失言「老人は働け」の方が、より生産的だと思っている)
しかし、既に大企業に頼る時代は終わっており、国の税収も少なくなってきている。無駄をなくすとはいっているものの、こういった現状をふまえると、おのずと「人に優しい」政策には限界が見えてくる。
日本の大企業は昔ほど元気ではなく、例えば、Panasocic(3.81兆円)とソニー(3.08兆円)を足してもサムスン電子(8.26兆円)より小さい。
時価総額上位ランキング(日本)
時価総額上位ランキング(世界)
足りないのは成長戦略である。基本はやはり産業の活性化。金融マネーゲームもよくないが、産業を否定するのもよくない。生産的な発想で、価値のあるものを効率よく生み出す努力をすることが重要だと思う。そういう意味では、ITは一つの柱になってしかるべきと思う。
現政権には具体的な政策を提示して欲しいものである。
政治家の権力は限定的だった
がらっと変わって、権力の話。
こないだ問題になった天皇の政治利用の件もそうだったが、民主党政権になっていろいろオープンに報道されるにつれ、政治家が及ぶ権力はかなり限定的だったんだなということがわかってきた。例えば、小沢さんの「検察の権力と闘う」といった発言はその象徴である。
しかし、そもそも検察の権力はどこに属しているのだろうという素朴な疑問が沸いてくる。国家権力を立法権・行政権・司法権の三権に分立しているのは、「国家の権力を性質に応じて分け、それぞれを別個の機関に分散させ、各機関に他の機関の越権を抑える権限を与え、相互に監視しあうことにより抑制均衡を図るためである。(Wikipediaより)
今は民主党が立法と行政の権力を握っているのは皆承知していることだ。実質的には、鳩山さんや小沢さんといった方が最高権力者だと思うが、その彼らたちが闘う国家権力とは一体何者なんだろうか?
小沢氏に「戦って」と首相、資質に疑問符
特捜部を含む検察庁は、行政機構上、法務省の一機関に位置付けられている。その法務省の長である法相は検察当局への指揮権を持つ。実際の指揮権発動には慎重な配慮が必要だろうが、その法相に指示できるのは唯一首相だけだ。
鳩山さんの言動から推測すると、ご自身の指示ではないようである。ということは、検察は一行政機関ではあるが、自分たちで勝手に判断して動いているということだろうか。それとも、他にいる影の権力者が指示しているのだろうか。もしそうだとすると、責任は誰が取るのだろうか。形式的には行政のトップである鳩山さんの責任になるのだろうが、実際に権力を行使する者の責任はどうなるのだろうか。
また、土地購入の際には、小沢さんは個人の積み立て金といっているが、検察は企業献金が使われた疑いがあるといっている。これが石川議員逮捕の理由とされているが、こういった情報は新聞やニュースから流れてくるだけで、検察からの説明はいっさいない。少なくとも、小沢さんの主張と検察の見解の違いがあるのだから、検察は根拠についての説明責任があるように思う。
検察の顔が見えないまま捜査が行われていることに、ちょっと気持ちの悪さを感じてしまう。
また、以下のように、権力闘争と指摘している記事もあり、検察といえども、どういう意図があって動いているのか、国民がしっかり監視していく必要がありそうである。
逮捕前日「理不尽な世界つらい」 石川議員、佐藤優氏に
佐藤氏は外務省在職当時、鈴木宗男衆院議員の側近とされ、鈴木議員に対する一連の捜査の過程で、背任などの罪で起訴され、有罪が確定した。その時の捜査を「国策捜査」と批判した佐藤氏だが、「今回は国策捜査ではなく、民主党と官僚組織の権力闘争だ」と指摘した。
<関連> 鈴木宗男氏「検察正義は間違い」 批判に沸く民主党大会
検察以外にも、政治家が及ばない権力があるように思う。独断と偏見で思いつくまま列挙するとこんな感じになる。
予算・・財務省
外交(軍事)・・米国
天皇・・宮内庁
情報管理・・マスコミ
また、昨日も書いたが、日本には世間様という絶対神がある。世間様がいいといえば良く、悪いといえば悪い。本当の意味で民主主義でないかもしれないけれど、世間様には誰も逆らえない。
戦前、暴走した陸軍は政府の統制下になかったといわれている。検察は軍ではないが、マスコミも同調していた構図は当時と瓜二つだ。
政治家よりも、検察とマスコミの方が世間様の判断を操作できる立場にあるというのは、結構怖い状態なのかもしれない。権力のシビリアンコントロールは絶対に必要であると思う。
GMAIL不正侵入問題で攻撃元となったサーバは中国政府関係者のものと同一だったというニュースが流れた。もしこれが本当なら国際社会から中国政府が釈明を求められる可能性があるとのこと。中国政府からの検閲を嫌って中国事業からの撤退も検討しているGoogleの動向にも影響を与えそうだ。
中国に関しては、これまで経済と政治は別物と見ていたのであるが、今回の一件で、両者は密接に関係していることを十分に認識させられることになった。しかし、1IT企業の対応が国際政治にまで影響を及ぼしたことには驚きである。
10年前に上海に行ったときには、活気あふれる街の雰囲気とはうらはらに、政治的なリスクを感じ得なかったので、いつかはこういう事件が起こるのではないかとは思っていた
ただ、言論の自由が保障されないお国の事情があるのもわからないでもない。13億人、55の民族からなる国家体制を維持するには、全体主義でやっていくしかない。急激な民主化はソ連崩壊のときと同じように、地域紛争を勃発させる危険もある。言論の自由、民主化を進めた結果、多くの人血が流れるという事態は避けなければならず、当然、これはその国の政府が責任をもってやっていくことでもある。言論の自由は国の政治体制に影響を与えかねないのだ。
今回の事件を受けて、岡田外務大臣が、「規制の裁量権はそれぞれの国にある」としながらも、「自由で民主主義の国に生きる我々として、言論の自由は可能な限り保障されるべきだ」と暗に中国を批判した。大臣のように正論を一方的に主張することは簡単だが、それがもたらす結果と責任をふまえ、現実論にもう少し踏み込んでもらいたい気もする。
中国の全体主義を理解するには、中華思想を理解するのが早道だと思う。中国人が語る中華思想がとても生々しくてわかりやすかった。
価値観という意味では、日本は欧米型の「個人主義」があり、それから、無意識のうちに世間体や恥の文化に支配されている。無宗教であるが世間様という絶対神には逆らえない。
でも日本は個人の尊重があるからこそ公害などを乗り越えられたと思うし、世間体や恥があるからこそモラルを高く維持して犯罪発生を防いでいるとも思う。住みやすい環境で安全に暮らしていけるのは、こういった日本独自の文化があるおかげだと思っている。
上海の大気汚染や、揚子江の水質汚染はとても酷いものだ。今より高収入になったとしても、そこに住もうとは思わない。
困ったことに、揚子江から流れる栄養塩のせいでエチゼンクラゲの大発生などが東シナ海で起きている。大気汚染が九州の方に流れたために、光化学スモッグ注意報が佐賀県のど田舎で起きている。こういった環境汚染は日本も無関係ではない。
中国の石炭の火力発電所建設などでは日本企業も支援していたらしいが、高度な脱硫技術をもっているにもかかわらず、現地の法律の基準が甘いとの理由で、わざわざ脱硫装置を外して導入したという話も聞いた。当事者にとってみたら、コストを安く導入できるので、ありがたい話なのかもしれないが、結局は自分たちがそのつけを払うことになると思う。
たぶん、このあたりのモラルも高くしていかないと、国際社会では説得力がない。これから日本は環境立国でやっていこうと思うならなおさらである。
一企業であってもGoogleのように強い姿勢で望むべきである。日本の環境基準を押し付けるぐらいの迫力で、政治的な摩擦を恐れず、どんどんやってほしいものだ。
福岡の事務所の近くで撮った室見川の写真

今年の動向、ネットのビジネスモデル
今年は、新しい技術や大きな目玉トピックはないものの、クラウドを使ったサービスが多数登場して、標準的になると予想する。XMLやWebサービスのときも最初そうだったが、ある程度認知されると、それが標準的になり、単に使っただけでは注目を集めることはなくなる。ただ、うまく活用できたところは大きな競争力を得てきたのも事実だ。GoogleやAmazonは、早い段階からWebサービスに関してとても熱心に実装してきたが、それが現在の競争力になっているようにも思える。クラウドも同様に、今後うまく活用していけるところが競争力になっていくと思われる。
さて、今年もあいかわらず景気はよくはならないと思うが、クラウドはだいぶ認知され一般的にも広く使われるようになってきている。弊社へのGAEに関する案件相談も着実に増えてきている。これまでは、知り合いのツテで請負の仕事をまわしてもらうようなことが多かったが、最近ではホームページを見て直接相談に来られるお客様が出てきた。インターネットから直接相談を受け、提案していた案件が成約できる見通しとなったことは非常に大きい。インターネットだけでビジネスをやりたいとずっと思ってきたので、本当にそれが実現できることがわかって嬉しいかぎりである。このモデルのいい点は、ブローカーのような、人を餌に暴利を貪る悪い連中を排除できるということ、また、大企業に依存してきた下請け体質から脱却できるので不景気でも強い会社になれること。それから、自分の強みや、やりたいと思っている分野(ドメイン)に集中できるという利点の3点である。これまでの下請け業務は、ある意味人材派遣的な要素が大きく、時間をお金に変えることはできても、プロダクトやノウハウが残ることはあまりなかった。GAEなどのクラウド技術に特化することで、やればやるほどプロダクトは進化してノウハウも蓄積する。本当に運用してはじめてわかる問題もあるので、リアルの案件の実績が得られることは本当に大きいと思う。
抱負
去年は種まきの年で今年は収穫の年。
今年の前半は何とか案件をリリースさせて、事例という形でお披露目できるようにしたいと思う。今年は泥臭く稼ぎ、消耗しきった体力を養う年にしたい。(もし一緒に開発したいという方がいたら連絡ください。弊社がブローカーとなってお仕事を依頼いたします。www)
それから、今年の後半は、現在開発中のECもリリースできるようにしたい。理想としているインターネットの小売ビジネスへの第一歩として、それが本当に実現可能なビジネスモデルなのかを検証していきたい。
技術的な点では、スケーラビリティの追求をテーマに以下をやっていきたい
1)GAE PDFサービスの大規模対応
大量のPDFを動的に生成するために、これまでにもReflex iTextを使って試行錯誤しながら実験してきたが、GAEを使うケースではまだ満足いく結果が得られていない。実案件ではAmazon EC2か独自サーバになってしまうのが現状である。今年も引き続き研究していき、何とか実用化させたい。GAEにこだわっている理由は「安い」からで、GAEでもちゃんとスケールすることが確認できたら実案件でも採用していきたい。
2)GAE 全文検索
実用的な全文検索サービスを作りたい。SuffixArray方式、分かち書き+転置Indexの2つの方式を採用し、用途に応じて使い分けていきたい。
3)クライアントを含めた実装パターンの確立
HTML5のWebStorageと大福帳 非同期モデルを推し進めたデザインで、これを実用レベルにすることを目標にしたい。リッチクライアントのようなWebアプリでありながら、いかにスケーラブルにしていくかが重要。これをやるには、ステートレスなバージョン管理がポイントだと思っている。プロジェクトでも積極的に採用していきたいと思う。
4)Privateクラウドソリューション
Privateクラウド、つまり、スケーラブルなシステムを分散KVSで実現させるシステムの需要は伸びてくると思われる。Reflex BDB単体では不十分で、Voldemortなどのミドルウェアを活用することで、具体的に提案できるレベルまで作っていきたい。
今年もよろしくお願いします。
ajn3のあおうささんのところで議論になったトランザクションのIsolation LevelがSERIALIZABLEであるという件。実はこれまでREAD COMMITEDじゃないかと思われていたふしがあった。ちょっとそれについて触れてみたい。
そのように思い込まされた元凶がMaxさんの、 App Engine におけるトランザクション分離という記事。ここに、ははっきりと「Google App Engine データストアのトランザクション分離レベルは、Read Committed とほぼ同等です」とある。
でもこれは、とりあえず、getTallPeople()がQueryだということで納得することにしよう。そもそもQueryはトランザクションに参加できないのでトランザクションの分離レベルの話をするには片手落ちである。Maxさんの記事は、分離レベルの話をしたいんじゃなくて、Datastore書き込みには2つのマイルストーンがあって、updatePerson()で実際にEntityやIndexを更新するタイミングによって見え方が異なるよという話がメインのような気がする。
一方のajn3は、Low Level APIのGET/PUTの話。あるトランザクションのPUTがコミットされるタイミングと、同時に他のトランザクションでGETされるときのタイミングの話だった。GETとPUTのタイミングを考えると、SERIALIZABLE相当と考えるのが正しい。
ちなみに、READ COMMITEDとSERIALIZABLEについては、以下の記事がわかりやすい。
トランザクションの隔離レベル
READ COMMITTEDに設定されている場合,トランザクションの実行中でも他のトランザクションによる更新処理や削除処理が行われれば,それらの処理が完了した時点から更新されたデータが参照されるようになる。一方,SERIALIZABLEに設定されている場合,トランザクションの実行中は他のトランザクションによるデータの更新処理や削除処理に関係なく,トランザクションが開始した時点のデータが参照される。つまり,SERIALIZABLEでは,他のトランザクションから完全に隔離された状態になる。
クラウドは本当に安いのか!?
Azureの登場もあって下図のようなクラウド比較情報が充実してきた。
Windows Azureの料金はGAEやEC2より安いのか

(昨日、AWSの値下げがあった)
クラウドのコストを考える際に重要だと思うポイントは、CPUコストとストレージコストの2つを分けて考えるということ。CPUコストは、できれば、ココで示したような、TPC-Cを元にしたPrice/Performanceといった値で比較するとよいと思うのだが、Publicクラウドについては各社とても安いので、単純にCPU利用料で比較してもいいのかもしれない。ただ、Amazon EC2のc1.xlargeといったハイエンドサーバを長時間使うと割高になるので、必要なときに必要なだけ利用するといったように、短時間に効率よく利用する工夫は必要になると思う。
問題はストレージコストの方だ。ココで指摘されているように、ストレージは決して安くはない。月額 $0.15/G でほぼ各社で足並みを揃えているが、8TB利用すると年間$14700/年かかることになる。1年間利用すると、これはカスタムサーバ1台買える計算になってしまう。
安いストレージサービスとの連携
実は、ものすごく安いストレージサービスがある。それは、GMAIL/Picasaで、なんと年額4096ドルで16TB利用できる。GAEやEC2のStorageにはトランザクションを格納し、GMAIL/Picasaには画像やファイルといったコンテンツを格納することで、全体的なコストを大きく下げることができる。
ということで、これを何とか活用できないか、ちょっと考えてみた。
GMAIL
Gmailにアクセスする方法は限られている。https://mail.google.com/mail/feed/atom/で一覧は取れるものの、そこからさらに本文や添付ファイルを取得することはできない。もちろん、ブラウザでGmail画面を開いて、中の添付ファイルを右クリックすればURLを取得することはできるが、これを自動的に取得できるようなAPIは公開されていない。これはGoogleのセキュリティポリシーなのだろう。世の中にはGmailをStorage代わりに使うGPhoto Spaceや、Gmail Driveといったものがあるが、おそらく不正なアクセスを行っているものであり、切断されて使えなくなってしまうリスクがあるので要注意である。オープンソースのJavaのAPI、g4jといったものもあるが、現在は接続できないし、開発もストップしているようだ。これらは個人で使用するのは結構かもしれないが、決してお客様に提案してはいけないものである。
ただ、Google Apps Premium Editionにおいて、データを格納するGData API、GMAIL Migration APIは正式に公開されているもので、このAPIを使用することで、GAEからでも様々なファイルをGmailに格納することができる。実際に検証してみたところ、本文および添付ファイルを格納することができた。Gmailをデータ格納用に使用しても違法ではない。このAPIを利用することで、DatastoreからExportしたデータのバックアップなどに使えるかもしれない。
Picasa
Picasaについては、Picasa Web Albums Data APIを使ってファイルの登録および取得が可能である。価格はGmaiと同じで非常に安い。
画像はURLを非公開(検索非対象)にできるが、知られてしまうとアクセス制限はできないので、基本的に公開されるものと考えるべきである。
1024文字の説明を画像に付けることができ、全文検索もできるので、ECの商品検索などに応用できそうである。
・1つの画像は最大20MB
・ 画像に説明を1つ追加可能(最大1024文字)。APIを使って追加可能。
・ コメント(最大512文字)を複数追加可能だがAPIからはできない。
・ JPEG、GIF、PNGなど様々なフォーマットに対応とあるが、実際にはjpegに変換されて格納される
Google Docs
Goole Docsには、PDFなどのドキュメントを保存できるが、全体の件数に制限がある。
Google ドキュメントの概要: サイズの制限
次のとおりです。
文書: 各文書は最大 500 KB まで、埋め込み画像は最大 2 MB まで可能です。
スプレッドシート: それぞれ最大 256 列、最大 200,000 セル、最大 100 シートとなっており、いずれか 1 つでも達すると制限が適用されます。行数には制限がありません。
プレゼンテーション: 作成できるファイルの最大サイズは、.ppt、.pps 形式の場合は 10 MB もしくは 200 スライド、ウェブからアップロードする場合は 2 MB、メールで送信する場合 500 KB です。
PDF: アップロードできる PDF の最大サイズは、パソコンからの場合は 10 MB、ウェブからの場合は 2 MB で、ドキュメント リストへは 100 個まで保存できます。
上記はどれも一長一短ある。
大容量コンテンツを格納できる格安ストレージサービスが欲しいところである。
ajn3の反響を読んで感じたこと
疎結合・非同期アプリケーションを快適に動作させるためのフレームワークはこれまでにない新しいものになるだろう。以下のつぶやきを読んであらためてそう思った。
クラウド・アプリケーションは、仕事を並列動作できる小さな単位に分割するのが基本という感を改めて #ajn3 で受けた。処理が完結しない場合は待つのではなくて、continuationを残してイベント駆動で待つ。reactiveという側面で捉えても面白い。
・・asami224
パラダイムも変わったのだから常識も変わる。ただ気をつけなければならないのは、これまでのデザインパターンも重要だけど、アンチパターンだからという理由で否定されてきたもののなかに、むしろ正解があるかもしれないということ。非正規化だってRDBからみたらアンチパターンなわけだから。いろいろ試行錯誤しながら最適解を見出すことが大事な気がする。その気持ちをわかっていただけて嬉しい。
昨日の #ajn3 で得た教訓。「なんでも試すことが重要」やってみることでわかることがある、覚えることができる。改めて心に響いた。早速会社で使おう。・・mochawan
#ajn3 の議論を見ているとKVSの同時性制御や隔離レベルに対する混乱とアプリケーション設計でのベストプラクティスの探求の様子が分かります。masayh
人生は見たり、聞いたり、試したりの三つの知恵でまとまってるが、世の中の技術者たちは見たり聞いたりばかりで一番重要な「試したり」をほとんどしてない。ありふれたことだが、失敗と成功は裏腹になっている。みんな失敗を厭うもんだから成功のチャンスも少ない。(本田宗一郎)・・404 ないわー (・∀・)キムティ♪ Not Foundの日記
とっても残念なこと
クラウドは破壊的イノベーションとはよくいったもので、これまで地球を中心に太陽がまわっていたのが逆になったぐらいの大きなインパクトをもつ革命である。私自身、クラウドがのもつイノベーションに驚き、可能性を探求しているところであるが、まだまだ認識が甘い気もしている。
その影響は、フレームワーク、言語やOSといったものにとどまらず、CPUまでにも及ぶ。(参照:シングルチップ・クラウドコンピュータ)これは、「ムーアの法則」限界説を覆す、まさにIT世界を変えるものでもある。

クラウドイノベーションの話はここまで。
で、何が残念かというと、今日の日経新聞の1面の記事
自治体クラウド、IT大手一斉参入、運用費3~4割減
自治体クラウドに関しては、ITproの記事が詳しいが、よく読むとクラウドでも何でもないことがよくわかる。いつものようにバズワードを利用した手口で、大手ITベンダーに発注させるネタに使われているだけ。内部統制JSOXの次はクラウドというわけだ。
この大きなイノベーションが起きているときに、こんなことでいいのかよ。クラウド化を真剣にやれば、少なくともコスト1/4以下にできるはずで、Publicクラウドであれば2桁減が常識だ。3割~4割カットなんて鉛筆なめてやっているだけだろう?お手盛りミエミエなんですよ。
我々から見たら自治体クラウドは霞ヶ関と大手ITベンダーによる「雲の上」の茶番劇にすぎない。ビジネスも技術的にも全く関係ない世界。
いっそのこと予算なんて付かなきゃいいのにとさえ思う。そうすりゃ本当に困って我々のところに相談しにくることだろうに。
クラウド研究会も手弁当、ajnも手弁当。ああ、国に期待できることは何もない。こんなんでいいのかね?国はもっと真剣にクラウドに取り組むべきだよね。
1個人でさえ、「高速道路をつくりたいんだ」といってるんだよ。いやあ、泣かせるねえ。ホトトギス。
この遠慮のない濃さが #ajn3 クオリティ。良くも悪くも。俺は #appengine に関する高速道路をつくりたいんだ。そのための努力は惜しまない・・higayasuo
皆さん、お疲れ様でした~。あっという間に23時半になっていた。いやあ、楽しかったですね。以下に資料を置いておきます。
「ぶいてく流 スケーラブルアプリの作り方」
ご意見、感想をお待ちしております。
<驚いたこと3つ>
・ tx処理でも必ずしもルートエンティティが存在する必要はない。つまり、タイムスタンプはエンティティ単位ではなくキーの単位で管理されている
・ 負荷をかけてあっためることでTaskQueueはスケールしそう
・ runqueryをasyncに実行できること
<まとめ>
・ ハッシュタグの検索結果一覧をまとめてみた
・ appengine java night #3に行ってきた。 #appengine #ajn3
(雨の日サービスに早速登録しますた)
・ #appengine java night #3( #ajn3 )に参加した
・ 最近読んだ論文
・ 恵比寿で働く社長のアメブロ
・ スティルハウスの書庫
しかし、皆まとめがうまいですね。
<追記補足>
・ PUTの速度は1行のときは100ms~150ms(GETの5~6倍)ぐらいです。資料はEntityGroupによる2行更新の速度です。
・ 受注Kindを分けるのは意味がないかもしれないと自分でもいったのですが、それはスケーラビリティに意味がないということではなく、非常に多くの受注が同時に集中することは現実的にあまり考えられないという意味です。私のモデルでは挿入時にカウンタを作成するので、1Kindに集中するとリトライ回数が増えますが、複数Kindに分けることでカウンタ作成を分散できるのでリトライ回数を減らすことができます。(ShadingCounterと同じ理屈)でも普通はKind1つでOKな気がします。
・ 商品画像などの扱いをどうするかという質問が懇談会のときにありました。私のおすすめはPicasaです。.jpgみたいなキーで関連づけることで、GAEと別々に管理することができます。また、大量の画像を登録する際にGAEを介さなくてもよいという利点もあります。そして、何より安いこと。8TB格納したとすると、Datastoreだと$14400/年ですが、Picasa(GMAIL)だと$2048/年で済みます。PicasaにはGDataAPIで操作できます。
トランザクションは意識しないのが一番
歴史は繰り返すんだろうか。トランザクションに関しては、こんな感じで話がループしている気がしている。
1) トランザクション宣言を明示的にコードに記述(ホスト、ODBC/JDBC)
2) 生産性が低くなり新しいフレームワークが出現(EJB、Seasar2)
3) 新しいイノベーション誕生(cloud)、トランザクションを明示的に宣言、以下繰り返し
トランザクションについては、2年前にも一度述べたことがある。実装が難しく不具合になりやすいので、生産性、品質を上げるには、開発者にトランザクションを意識させないことが一番である、といった感じのことを書いたつもりであった。
【EC開発体験記-トランザクション処理-】古くて新しい永遠のテーマ
GAEにおいても方法論は異なるとは思うが、開発者にトランザクション処理を意識させたくないという私のスタンスは今でも変わっていない。GAEにもそのうち新しいフレームワークが現れて生産性が高くなっていくかもしれない。
でもエンジニアの性というか、トランザクションを議論するのは、いつの時代でも好まれるようである。何百時間とかけて、そのくせ不完全だったりする(私も例外ではない)。
モデリングの話もそうだったが、エンジニアは基本的に穀潰しである。
とはいえ、過去の考え方をあらためて学ぶことは、それはそれで有益に思えることもある。 ということで、一応、復習することにする。
トランザクションコンテキストは野球のボール
EJBが登場したとき、メソッドの呼び出しだけで、何でトランザクション処理が可能になるのかわからなかった。実はコンテナがメソッドを管理していて、呼び出し時にトランザクションコンテキストの受け渡しを行うことで実現していたのだが、これを理解できたときはとても感動したものだった。(しかし、重いEJBはパフォーマンスが悪かったので普及せず、Seasar2がそれを改善した。AOPによりトランザクションを実現しているのを知ったときは一本取られたと思った。)
で、その具体的な仕組みを説明する。
トランザクションコンテキストは何かというと、マジックで番号が記入された野球のボールのようなものと考えればよい。担当者に仕事を依頼する際に、受付番号を書いたボールも一緒に渡すことにして、もし担当者が処理に失敗した場合は、ボールに×を書いて返すようにする。担当者は別の担当者に再委託もできるが、その際にも必ずボールも渡すこととする。最後に依頼者にボールが戻ってきたときに、×が付いているかをチェックして、処理の成功失敗を判断する。成功であればその受付番号の処理を最終的にコミットとする。失敗であれば何もしないでボールを捨てる。受付番号が記入されているので同時並行処理が可能なのである。
受注と在庫引当を分散トランザクション実行
以下は、分散トランザクション実行のアイデアである。(このBlogでは、受注とか在庫とかのEC単語が唐突に出てくる。)上記のトランザクションコンテキストを受け渡す方法を元に考えたものだ。図には書いていないが、TaskQueueによる在庫引当では冪等性(べきとうせい)も考慮する。
受注受付のタイミングと在庫更新のタイミングは異なるが、2重引当などの致命的な問題は起こらないはずである。ただ、実際より在庫が少ないとみなされる瞬間がある。
ブラウザーでステータスを確認するか、ステータス更新時にメールするなど、基本的にはステータス参照で対応するところが非同期の特徴である。
なお、口座送金処理といったものへの応用は、もしかしたら可能かもしれないが、参照のタイミングが一致しないので、この方法ではたぶん無理だと思う。
世界的な不況が続く中、競争力のある強い体質の企業になるためには、大幅なコスト削減が必要である。とりわけ、ITシステムへのコスト削減圧力は大きく、これに対応するためには、アーキテクチャー見直しや内製化などを含め、抜本的な改善していかなければならない。
Privateクラウドは、ITシステムのコスト削減の一手段として考えることができ、こういった課題に対応できる可能性をもつと考えられる。
今回は、Privateクラウドをテーマに思うところを述べてみたい。
Privateクラウドはクラウドではない?
11/22の日経新聞にクラウドの特集があった。
そこには、クラウドの定義ははっきりしないが、「ネットの向こう側にあるソフトなどのIT資産を使う」という概念が基本となると書いてあった。また、誤解に関して以下のような感じで書かれてあった。
クラウドがブームになり、最近は関連する一部技術を入れ込んだだけのサービスにもその名が付く。「企業内クラウド(プライベートクラウド)」。「仮想化」という技術を企業内のIT資産に適用したもので、効率的な社内システムを構築できるが、「ネットの向こう側」を利用するクラウドの本質からは外れている。こうした拡大解釈が広がれば、利用者の誤解を招きかねない。利用する側も注意が必要だ。
まあ、クラウドは一般的には「ネットの向こう側」と解釈されるのだろう。
でも私は、クラウドの本質と動向にも書いたとおり、あくまで「抽象的に定義されたデータベースサービスへのアクセス手段」と考えていて、また、べらぼうに安いこと、およびリニアにスケールすること、の2つのポイントも重要だと考えている。なので、企業内にあっても外部にあっても、上記が満たせるのであれば別にクラウドと呼んでもいいと思っている。別に「ネットの向こう側」になきゃいけないわけではない。具体的には、今後はDHT(Distributed Hash Table)技術を使った分散KVS(Key Value Storage)などを応用したものが企業内クラウドの代表的なものになっていくんじゃないかと考えている。
一方で、「ネットの向こう側」にありながら、全然安くないクラウドもたくさんある。GAEやAmazonEC2などは、CPU時間あたり$0.10、Storageは$0.15 (GB/Month)でほぼ足並みをそろえているのに対し、日本の某通信会社のPublicクラウドは十数万円と2桁の差がある。利用する側が注意しなければならないのは実はこっちの方である。
企業内クラウドもコストとスケーラビリティは重要
分散KVSといったクラウド技術を企業内システムに応用することで得られるメリットは、コスト削減とスケーラビリティ向上の2つである。
まず、トランザクション増加に対応するためには、ノードの追加だけでリニアにスケールするような仕組みが重要である。それから、基幹システムであるからにはAvailabilityも重要となる。一部が故障しても自動的に切り離されて問題なく動作しつづけるような高可用性システムをいかに構築できるかが鍵となる。
コスト削減効果として期待できるところは、コモディティサーバとオープンソースの活用によるインフラコストの削減である。実際に、ノードはIAアーキテクチャでLinuxベースのコモディティサーバを使えばいいし、ソフトウェアに関しては、実際に動的なノードの追加削除を可能とするDynamoクローンのオープンソースもある。このように、クラウドの仕組みを、今ではコモディティサーバとオープンソースで実現できる。
2点目は、内製化により「脱ベンダー依存」ができるという点。つまり、コモディティサーバとクラウド技術を活用したオープンなアーキテクチャーを構築することで、ITベンダーの固有のアーキテクチャーに依存しないシステムを構築することが可能になるということ。これまでベンダーによる見積もり(お手盛り)をせいぜい値引きするぐらいしかできないのが現状であった。
オープン技術の組み合わせでエンタープライズシステムを構築できれば「脱ベンダー依存」が進み、ベンダー独自の技術に依存してきた弱みから脱却できるようになる。
ITベンダーによるボトムアップ提案から利用者自身によるトップダウン調達。コモディティサーバなどの部品調達レベルの取引になっていくことで、エンタープライズシステムの価格破壊は必至となる。
価格シミュレーション
実際にどれくらい安くできるのかを調べるため、具体的にTPC-Cベンチマークを元に価格比を計算してみた。
1) Scale-up型の最高モデルであるIBM p-595とコモディティサーバHP ML350とを比較すると、単純CPU能力換算でCostは1/4となる。
2) HA構成(マシンは2台)とクラウド構成(マシンは3台)で比較するとCostは1/3となる。(クラウド構成でマシン3台を根拠とする理由は、Quorumプロトコルで推奨されるのがN:R:W=3:2:2であること。実際のDynamoの冗長ノード数が3台であることなど)
もちろん、場所代や電気代など、計算に含まれない要素はある。極めて一面的な見方しかしていないが、PrivateクラウドのHWコストメリットは、ざっくり、1/3~1/4となる。
面白いのは、IBMの機種どおしで比較してもコストメリットは見出せないということ。おそらく、全プラットフォームでPrice/Performanceが2.5前後になるような戦略的な値を設定しているのだろう。

もう一つ、特筆したいのがHWに及ぼす影響についてである。
クラウドは、Scale-up型のハイエンドサーバから、Scale-out型のIntel Xeonベースのコモディティサーバへの変化をもたらし、さらには、FAWNといったようなローエンドプロセッサとフラッシュメモリのクラスタへの変化を促すだろうと考えられている。そして最後には、シングルチップ・クラウドコンピュータへの進化に行きつく。クラウドのイノベーションは、複数のCPUが疎結合で連携するような処理を、1チップのなかで実現することを可能にする。

クラウド化による新たな課題
安価なハードウェアの導入とオープンソースの利用を中心とした、エンタープライズ・システムのコモディティ化は、コスト面やスケーラビリティにおけるメリットが大きい一方で、以下の新たな問題を生むこともわかっている。
1)リスクを利用者自身が負うことになる
2)システムが複雑になる分、運用管理が大変になる
脱ベンダー依存を成し遂げたら、すべての責任は利用者自らが負うことになる。これまで、システムの調子が悪かったら何でもかんでもベンダーの責任にできたところが、そうはいかなくなり、自分自身で大きな不安と苦しみを抱え込むことになる。
また、これまでの2~3台であったシステムが100台近くに増えると、運用の仕組みが大きく変わってくる。例えば、バックアップを取る際には、全ノードを一旦Read Only状態にしたうえで実行しなければならない。また、ソフトウェアの配布などを100台一斉に実行するような仕組みも必要になってくるだろう。このあたりは実際に運用してみると、もっと大きな課題が出てくると思われるが、いずれにしても運用をいかに効率よくやっていくかが重要なポイントであることは間違いない。(Googleはこの点がすばらしいと思う)
マイクロソフトとAzure戦略
日経新聞のいうところのクラウドの本質は「ネットの向こう側」を利用することであった。前述したように、私から言わせれば、PrivateとPublicの違いはコストだけなのだが、コストメリットだけ考えると、Publicクラウドの利用は大変魅力的であり、エンタープライズにおいて活用できれば非常に大きな競争力となるのは間違いない。とにかく、Publicクラウドはべらぼうに安い。
AmazonやGoogleには、それぞれがEC、検索エンジンといった本業をもっていて、システムの余剰なリソースを貸し出せるという利点がある。もちろん、スケールメリットがあり、電力効率などを含めたデータセンターの効率的な運用数値PUEがずば抜けてよいことも知られている。
当分の間は2強の時代が続くと思われるが、猛烈に追随しているマイクロソフトのAzureも気になるところである。繰り返しになるが、ポイントはコストとスケーラビリティの2つ。安さという点で2強を追随できるのか、あるいは、スケーラビリティの点で優れた技術を提供できるのか。
本来、Windowsはコンシューマから発展したOSで、基幹システムでの利用が進んでいるとはいえ、ミッションクリティカルで大規模なシステムはあまり得意ではなかった。前述したような、IBM p-595サーバとは、比較すらできなかったのであるが、Azureでもってスケーラブルシステムが構築できるようになれば話は別である。セキュリティ、コストといった課題はあるものの、エンタープライズに踏み込める可能性がさらに大きくなったといえる。
<追記>
日経BPの中田さんによるAzure IT PACの写真
<関連>
Chrome OS戦略とIT世界の対立軸
Request was aborted after waiting too long が出る理由
前記事の実行結果を見てもらえばわかるとおり、"Request was aborted after waiting too long・・"というエラーのせいで、処理が中断されてリトライが頻発しているものが多くある。これがTaskQueueのスケーラビリティを阻害しているのは間違いない。これは、queryの実行時間が10秒を超えると出るようである。(PDF生成処理Taskでは10秒を超えるものがあるのでtaskの経過時間というよりqueryの実行時間によるのだと思う。たぶん)
別にquotaを上回るような処理を流したつもりはないのになぜ出るのか。
この現象については、ココでも質問されているが、Googleからの返事はまだない。
total queue execution rateの定義
Taskの実行時間が10秒を超えるとキャンセルされる、とはどこにも書いていないので、エラーメッセージにあるとおり、何かしらquotaを上回る処理があって、それが原因で待ちが発生して、これ以上待つのは無理だからキャンセルされた、というふうに理解していた。quotaといっても、ココにあるように、いろいろあるが、私は、total queue execution rateが一番あやしいと思っている。
MLでJamesさんが自己レスしているが、total queue execution rate が 20 task invocations per second というのは、dequeueするtaskの数ではなく、処理可能なquery数ということらしい。つまり、taskqueueを使って処理できるのは最大20qps/sということ。これなら(納得はできないが)理解はできる。
この件に関して、ありがたいことに、ひがさんからコメントいただいた。このあたりの話は、GAE Nightでいろいろ聞くことにしよう。
あのwarningは、リクエスト処理中に後続のリクエストが来てqueueにつまれ10秒以内に処理されなかったときに発生します。
つまり、AppEgnineは30秒ルール以外にも、負荷が集中するときには、10秒以内に処理しないければいけないという10秒ルールも存在するのです。
10秒ルールを守ったとしても完璧にスケールするかはまた別の話ですが、今のAppEngineの能力を最も引き出せるということはいえると思います。
エラーが発生する原因
「Request was aborted after waiting too long 」が出る原因を考えてみた。
仮定1)同じインスタンス(同じVM上アプリ)に複数のリクエストが入ろうとして待たされている。
仮定2)spin up(アプリケーションの起動)までに時間がかかるのが原因。例えば、cold start時には、まっさらなVMにクラスをロードする時間などが余分にかかる。それが加算される。
これを突き止めるために、以下の実験をやってみた。
実験1) 同じvmであればEnQueueしなおしてすぐに終了させるようにするとどうなるか
実験2) 新規のvmhashの場合、一回目はすぐに終了させるとどうなるか

同じVMであるかどうかは、こちらの記事にあるとおり、Runtime.getRuntime().hashCode()を比較することで判別するようにした。(memcacheを使ってhashcodeを管理する)
そしたら、hashcodeが重なってた(下図)ので、こちらの記事のように、ServletContext+UUIDで判別するようにした。

実験結果
前記事の全文検索アプリを使って実験した結果、以下のようになった。
- 1タスク500件、一度に4タスク登録。(合計20タスク)
- 全データ検索まで : 1分41秒
- 1タスクの処理時間 : 5~7秒
- ただし、初期起動の場合は8~9秒
- RuntimeのhashCodeが同じでも、違うuuidが最初に起動する場合、8~9秒かかる。
- "Request was aborted ..."が1回出現。
- 起動チェックをRuntimeのhashCodeでなく、uuidで行う。
- uuidごとだと仮定1(複数のTASKが同じVM(マシン)で実行される)は起こらないので、実験1は行わない。実験2のみ行う。
- 以上の条件で、1タスク500件、一度に4タスク登録。(合計20タスク)
- 全データ検索まで : 1分4秒
- 1タスクの処理時間 : 6~7秒
- 起動インスタンス : 4個
- "Request was aborted ..."のWarningログは1回も出力されていない。
- 1タスク500件、一度に8タスク登録。(合計20タスク)
- 全データ検索まで : 1分6秒
- 1タスクの処理時間 : 6~7秒
- 起動インスタンス : 4個
- "Request was aborted ..."のWarningログは1回も出力されていない。
- 1タスク500件、一度に16タスク登録。(合計20タスク)
- 全データ検索まで : 1分34秒
- 1タスクの処理時間 : 6~7秒
- 起動インスタンス : 5個
- "Request was aborted ..."のWarningログは1回も出力されていない。
- 1タスク1000件、一度に4タスク登録。(合計10タスク)
- 最初にリクエストして約5分経過しても、1個のタスクも終了しない。
- 新しいインスタンス起動 : 22回
- 実験2)新しいインスタンスの場合QueueにTaskを登録し直してすぐに終了する、という処理は正常にできている。
- "Request was aborted ..." : 18回
- なぜかQueueのTaskが4個から9個に増えた。(プログラムバグ?)
- TaskQueueの設定を変えてテスト。rate=10, bucket size=10に設定。
- 4タスク : 1分4秒
- 8タスク : 58秒
- 16タスク : 1分12秒
- 16タスクの場合のみ"Request was aborted ..."のWarningログが数件出力されている。
- TaskQueueの設定を変えてテスト。rate=10, bucket size=20に設定。
- 4タスク : 1分5秒
- 8タスク : 1分
- 16タスク : 1分22秒
- 8,16タスクの場合"Request was aborted ..."のWarningログが数件出力されている。
- 1タスクあたりの処理件数を変えてテスト。(TaskQueueの設定 : rate=10, bucket size=10、一度に4タスク登録)
- 700件(合計15タスク) : 2分54秒
- 1タスクの処理時間 : 8秒~10秒弱(10秒は超えていない)
- "Request was aborted ..." : 4回
- 600件(合計17タスク) : 1分57秒
- 1タスクの処理時間 : 7秒~8秒
- "Request was aborted ..." : 2回
- 400件(合計25タスク) : 57秒
- 1タスクの処理時間 : 4秒~6秒
- "Request was aborted ..." : なし
- 300件(合計34タスク) : 1分2秒
- 1タスクの処理時間 : 4秒~5秒
- "Request was aborted ..." : なし
- 200件(合計50タスク) : 1分16秒
- 1タスクの処理時間 : 2秒~3秒
- "Request was aborted ..." : なし
- まとめ
- uuidごと(ServletContextごと)にcold startされている。
- Taskの処理時間が10秒を過ぎると"Request was aborted ..."とWarningログが出力され、リトライされているようだ。
- 仮定2)cold startの場合はQueueに再度処理を登録し直して自分は終了する、という方法は、しない場合と比べて速くなった。
- cold startの場合は処理時間が10秒を超えてリトライされていたためと推測される。
- インスタンスは4~5個立ち上がるが、同時に処理を行うのは最大4個。
- 1タスクあたりの処理時間が4秒~6秒以下の場合、Taskの同時処理数が4個で安定する。
10秒近くなるとTask同時処理数が減ってくるため、総処理時間が遅くなる。
- 1タスクあたりの処理時間を4秒~6秒とすると、総処理時間が最も速くなった。
エラーメッセージは出ないようになったが、相変わらずインスタンスの最大が4つというところが納得いかない。
TaskQueueを使ってPDFを生成する
先の記事で疎結合、バージョニング、非同期がスケーラブルにするための要素だと述べた。私たちが提供するReflex iTextサービスでは、PDF生成サービス(図中 pdfservice)やデータサービスなどは、独立したサービスとして立てられる。独立したサービスは(カッコつけていえば)サービスコンポーネントとして考えることができる。サービスコンポーネントは、ServiceとReferenceの2つの口をもち、いわゆる芋ずる式に(疎)結合できる。そして、TaskQueueを利用することで、それらを非同期かつ並列に実行することができる。これを、ぶいてく流サービスコンポーネントアーキテクチャーと呼んでいる。

例えば、請求書アプリでは、
http://invoice.latest.reflexcontainer.appspot.com/invoice?invoiceNo=DEMO1&xml
でGETすることで、データサービスからデータを取得することができる。(&jsonとすることでjsonも取得も可能)
そして、以下のようにデータとtemplateを同時に与えることでPDFを生成する。内部的には、pdfservice(service)に与えられたurlを元に参照(reference)を実行している。
http://pdf.latest.reflex-itext.appspot.com/pdfservicegae?template=http://invoice.latest.reflexcontainer.appspot.com/invoice.html&entity=http://invoice.latest.reflexcontainer.appspot.com/invoice?invoiceNo=DEMO1&xml
さらに、TaskQueueによって起動された複数のTaskからこのリクエストを実行すれば、大量のPDFを瞬時に生成することができる。これは以下のような仕組みになっている。

スケールしない現実
だが、ココや、ココに書いたとおり、実際にはスケールしない。
700ページを12リクエスト(合計8400ページ)処理させた場合について計測してみると、unit=70の場合(700/70*12=120タスク)で約15分かかってしまう。unit=70の場合で1タスクの処理時間が30秒未満なので、本当に並列処理されているとすれば、30秒で完了しなければならないはずである。ちなみに、unitの数と処理時間の関係は以下のとおりである。unit=50で最速であるが、それでも1分かかっている。
- 1 : 生成(全タスク完了まで)
- 2 : 取得(PDFマージ処理からクライアントで文書を開くまで)
- unit=70,total=700 (タスク件数 : 10件)
- 1分20秒,1分10秒
- 57秒。42秒
- unit=60,total=700 (タスク件数 : 12件)
- 1分20秒。
- 1分。
- unit=50,total=700 (タスク件数 : 14件)
- 1分2秒,1分15秒。
- 1分4秒,47秒。
- unit=40,total=700 (タスク件数 : 18件)
- 1分15秒。
- 54秒。
- unit=30,total=700 (タスク件数 : 24件)
- 1分20秒,1分35秒,1分14秒。
- 50秒,43秒。
- unit=10,total=700 (タスク件数 : 70件)
- 1分52秒,1分33秒。
- 52秒,50秒。
詳細分析
- どれも以下のWarningが多発
Request was aborted after waiting too long to attempt to service your request. Most likely, this indicates that you have reached your simultaneous active request limit. This is almost always due to excessively high latency in your app. Please see http://code.google.com/appengine/docs/quotas.html for more details.
TaskQueueのワーカー側から出力されている様子。
2個目の終了ログの前に上記ログが複数出力されているケースが多い。
処理の合間にもちらほら出力される。
Maximum RateとBucket Sizeを下げる(どちらも5に設定)と、abort発生頻度が下がる。
- 1はインスタンス2個、2,3はインスタンス3個
- 全ての処理が終了するのは、どれも15分程度で変わらない。
- あるインスタンスが最初に処理を行う場合、2回目以降と比較して処理時間が長い。
- 一度に4個程度並行処理を行っている。そのうち3個は同じJVMで、1個だけ別のJVMというパターンが多い。
- また、クライアントから連続してリクエストを投げた際(今回のテストでは4秒間隔)、エラーが時々発生する。1回目のリクエストは成功し、2回目のリクエストでエラーが発生することが多い。
ボトルネックがどこにあるかわからなかったため、下図のように、Memcacheにデータを格納することで、ネットワークI/Oをなくすケースについても計ってみた。

- TaskQueue処理データをMemcacheに登録するテスト
- 1Taskあたり700ページ作成すると、dispatcherでの処理で以下のエラーが発生してタイムアウトする。240~300ページあたりで、エラーになったり正常終了したりした。
- jp.reflexworks.pdfservice.PdfDispatcher doGet: com.google.apphosting.api.DeadlineExceededException: This request (789cb38865d5e3d2) started at 2009/10/27 06:10:31.448 UTC and was still executing at 2009/10/27 06:10:59.946 UTC.・・・
- 8400ページ出力処理(以下、1Taskあたり240ページ作成とする)
TaskQueueのMaximum Rate : 5.0/s、Bucket Size : 5.0に設定。
- unit=20,total=240を35回リクエスト(クライアントからのリクエスト間隔:4秒)
- タスク数は、12×35=420個。
- 1タスクにつき処理時間が6~11秒かかる。
- 実行結果
- dispatcherへの1回目のリクエストはエラーになった。2回目から正常終了。
- やはり"Request was aborted ..."のWarningが所々出力されている。(4回正常、1回Warningログというパターンが多い)
- dispatcherの応答時間が長い。
- Memcacheを使わない場合は2~7秒、今回は9~10秒。
- 1タスクあたりの処理時間は、Memcacheを使わない場合とあまり変わらない。
- 総処理時間は19分。(エラー分の2回を追加でリクエストした。)
- VM起動数は4個。
- リクエストを投げ終わる時間は10分。
この結果でわかることは、
1)リクエストを投げ終わる時間は10分だが、リクエストを投げてから、すぐにTaskが起動されるため、Task処理開始から終了までにかかる時間は19分である
2)1タスクの処理時間に変化がなかったことで、一括検索+Memcaheに格納のメリットは見い出せなかった
3)1回目のリクエストでエラーとなるケースが多い(この件については、次回の記事にて、詳細に分析した結果を報告する)
ちなみに、TaskQueueを使わないで、すべてdispacheで処理したケース(つまり、多重度1)では、
- 8400ページ出力処理、クライアントからのリクエスト間隔を0秒にしてテスト
- リクエストを投げ終わる時間は7分。
- dispatcherへのリクエストは、35回中2回エラー
- 総処理時間は19分。(エラー分の2回を追加でリクエストした。)
また、MemcacheのI/O回数を減らし、20件分をまとめてgetしたケースでは、
- Memcacheへのデータ登録単位を1件からunit(20)件にし、Task側ではMemcacheからgetする回数を1回にしてテスト
(Memcacheに、1個のキーに対しデータunit(20)件分のjson文字列を格納する。)
<続く>
<追記>
・ 軽いWorkerタスクを別途用意して連続して負荷をかけることでVMは16程度起動することがわかっている。今度はServletContext+UUIDで負荷分散状況を調べてみた
・ WdWeaverさんの実験 スケールアウトの真実
ぶいてく流スケーラブル設計3大要素
私たちがスケーラブルなアプリを作る際に重要だと考えている要素は、疎結合、バージョニング、非同期の3つである。
今回は、疎結合、特にバージョニングについて詳しく述べる。非同期(TaskQueue)は次回の予定。
疎結合
GAEといったスケーラブルなプラットフォームを利用することで、単純なWebアプリでもスケーラビリティを得られるわけだが、さらにそれをRESTfulなWebサービスにすることで、より柔軟なスケーラビリティを享受できる。マッシュアップアプリがいい例で、ワンソース・マルチビューを実現できる。それは、この記事や、実装例で示してきたとおりである。これらはReflexやReflexGaeフレームワークにより、EntityからJSONやXML等に変換することで実現している。
バージョニング
この記事の最後の一文は、なんのこっちゃ!?と思った方も多いと思う。
「ただし、これをやるには、レコードをRevision番号で管理するという前提で考える必要があり、更新において新しいRevision番号でレコードを追加する必要がある。」
要はバージョニングのことなのだが、その目的は、楽観的排他によるスケーラビリティの向上と、履歴管理によるトレーサビリティの向上の2つである。削除したデータも保存しておくことでUndo機能もつけることができる。
楽観的排他はロックを起こさないのでスケーラビリティ向上につながる。つまり、更新の際にRevison番号を比較することで不整合を起こしていないかチェックする仕組みで、それをアプリレベルで実装しようというものである。
HTML5のDataStorageのように、疎結合、非同期を前提とした「いまどき」のアプリでは、ブラウザで何かアクションを起こしても、すぐにはサーバに問い合わせにはいかない。そうなると不整合を起こす可能性も大きいわけだが、レコードがバージョニングされてさえいれば、整合性を解決することはそれほど難しくない。Revison番号が同じレコードは常に同じ内容であることが重要で、また、サーバのDatastoreやMemcache、あるいはクライアントのStorageなど、どこにあろうと同じものとして扱われることになる。もし同じRevisionで異なる情報があったとしたらDatastoreの内容を正とすることで整合性は保たれる。したがって、クライアントに存在する情報とサーバにある情報は時間差こそあるものの、全体的に見ると常に整合性が取れた状態とみなすことができる。(これが私が理解している、Eventually Consistencyの概念だ)
というわけなので、オフライン時はクライアントのStorageを読みこめばいいし、オンラインでもMemcacheにデータが残っていればそれを返せばいい。そのとき最新のRevisionがDatastoreにあったとしても、神経質にならずに、Memcacheのタイムアウトまでは古い情報であっても返しちゃえばいいのだ。もちろん、在庫引当や座席予約など、このやり方が通用しない要件はあるが、ほとんどは「遅延」を許容できるアプリと思うので、このように実装することでスケーラブルになることは間違いないと思われる。(そういえば、DatastoreのIndex作成も遅延が起きるような・・appengineはRead Committed相当だがcommit()には2つのマイルストーンがあることを忘れてはいけない)
関連として、レコードにシーケンス番号をつけることも挙げておく。これは、Pagingや件数管理のために使用する。シーケンス番号をつけることで、最新レコードを取得できるようになる。また、大量のレコードを分割してTaskQueueで並列処理させたい場合には、シーケンス番号で範囲指定を行える。
件数管理は、GAEは件数を数えるのが苦手で数十万件以上になるとタイムアウトを起こして検索できなくなるので、最新レコードで常に管理しておこうというアイデアである。
最新レコードのQueryは件数に影響されずにそこそこ高速に検索できる(約0.6s)ことを利用している。
削除済みデータなど、不必要に思える(むしろ消すべきと思える)ものを残して履歴管理する第一の理由は、データ量がパフォーマンスに影響しないということ。その点は特に強調したい。
以下に、バージョニングのロジックを示す。大福帳管理モデルというのは私が勝手につけた名前で、あまり人に吹聴するとイタイ目にあうかも。multidimensionalの方が近い意味だと思う。
大福帳管理モデル(別名:カーボンコピーモデル 英語名:multidimensional)
- 大福帳管理モデル(multidimensional,カーボンコピーモデル)(勝手に命名)
- 楽観的排他でスケーラビリティ向上
- 履歴管理によるトレーサビリティ向上、Undo機能
- 件数管理によるパフォーマンス向上
- すべてのレコードは、Key+Revison番号で管理される。
- Key(※)+Revisonが同じであれば、同じ内容のレコードであるとみなす。ただし、削除は例外扱い。(※このKeyはアプリのキーでありDatastoreのKeyではない。詳細は、ココのKeyに何を入れるべきかを参照のこと)
- 追加では、レコードが存在しなければ、Revisonを0にセットして追加する。レコードが存在していれば、エラーか強制登録を実行する。強制登録は、削 除フラグが立っていることを確認して、revisonを+1したうえで追加する。このとき削除フラグが立っていなければエラーとする。この処理は GET/PUTによるトランザクションで実行されなければならない。
- ただし、強制登録では一度削除されたものと同じKeyでの再登録をすることになるので、それを許すかどうかはアプリの要件による。(Forceオプションか何かで区別すべき)
- 更新では、現在のレコードがあることを確認して、更新レコードのRevisonと同じであるかチェックする。NGであれば楽観的排他エラーとする。OKで あればRevisonを+1して更新すると同時に現在のレコードには削除フラグを立てる。この処理はGET/PUTによるトランザクションで実行されなけ ればならない。また、現在のレコードに削除フラグが立っていてもエラーとする。(これで既に削除されているときの楽観的排他ができる)
- 検索ではRevison番号は更新されない
- 削除は論理削除であり実際には消さない。削除フラグに削除された日時を入れて更新することで削除されていることを示す。Revison番号は変わらない。
- 削除レコードを追加するという考え方ではなく、削除フラグに日時を入れることで対応する。その理由は、古いRevisonレコードに削除フラグが立たないと検索対象に含まれてしまって不都合だから。また、削除フラグのみの更新であれば、元の情報が消されることもない。
- 情報の鮮度(強弱)
- 同一KeyのレコードではRevisonの大きいものが最新となるが、同一Revisonで削除フラグが立っているものがある場合には、それが最新となる。
- Rev.3(削除なし)>Rev.2(削除あり)>Rev.2(削除なし)>Rev.1(削除ありなし)
大福帳管理モデル 更新のサンプルとパフォーマンス
以下にサンプルコードを示す。これはカウンタをもつEntityGroupを構成するタイプで、最新レコードに件数をもつタイプではない。
拙作のReflexGaeを利用している。
ReflexGaeの特長は、JDOのEntityをLow Level APIを使ってGET/PUTできるところ。なんのこっちゃ!?と思うかもしれないが、要はJDOがヘタレなのでLow Level APIでラッパーを作った。その際、EntityはJDOと完全に互換性をもたせるようにした。(JDOがダメダメと言い出したのはたぶん私が最初だと思うが、概念というか、Entityの構造まで否定したつもりはなく、実はこれはこれで気に入っていたりする)
ReflexGaeには、KeyUtils、EntityConverter、FieldMapperというものがあり、以下のようなことができる。
1.KeyUtilsを使って、EntityGroupを作成する
2.EntityConverter().convert(RECORD_KIND_CLASS, entity); で、EntityクラスからJDOクラスに変換する
3.fieldMapper.setValue(current, target); で、JDOの@Persistent項目で更新があるものだけをセットする
Entity変換ではReflectionを使っているが高速である。
速度比較
- 登録(登録 + カウンタ更新・・EntityGroup更新)
- JDO : 0.251s
- ReflexGAE : 0.163s
- 更新(1レコード登録 + 1レコード(旧Revision)・・同一Kind更新)
- JDO : 2.790s
- ReflexGAE : 0.250s
検索ではJDOは1万件以上でタイムアウトになるので単純に比較できないが、ReflexGaeは次の通り。
- keyによるget : 0.030s
- query : 0.622s (92300件対象にSort条件をつけて1件取得)
ちなみに、Memcacheへの登録参照はココによれば、0.015s程度とのこと。