月曜日, 6月 18, 2012

分散KVSにおけるスケーラビリティと一貫性の両立について このエントリーを含むはてなブックマーク

先日、容易なスケールアウト拡張とトランザクションの正確性を担保する分散KVS基盤、ReflexWorksを発表した。(http://reflexworks.jp/)
エンタープライズシステムの多くは強い一貫性が要求されるため、これまではRDBMSを使うことが多かった。しかし、簡単にシステム増強できないことから、増え続けるデータに柔軟に対応できないという欠点があった。
分散KVSは、単純なキーとバリューのデータからなるデータストアを複数のマシンに分散配置したものである。これをデータストアにすることで、システム稼働後であってもサーバー資源を動的に追加できるなど、柔軟なスケーラビリティを実現できる。

ReflexWorksは分散KVSにBerkeley DB Java Editionを採用、システムをスケーラブルにしつつ、同時にトランザクションの正確性を担保しており、大規模なトランザクション処理が求められる企業システムの構築を容易にする。

ReflexWorksはスケーラブルな企業システムを構築するための実用最小限の製品(MVPMinimum Viable Product)である。

スケーラビリティと一貫性の両立について

CAP定理を勉強している方々は、スケールしながらトランザクション処理の正確性を担保するといった、ReflexWorksの特長に違和感を感じられるかもしれない

クラウドの多くは「ScalableAvailableで、かつ、Eventually Consistentなシステムは可能である。」というように、Consistencyの部分を緩くすることで実現しようとしてきたが、3つを同時に満たすなんてことは不可能というのがCAP定理の原理の原則のはずである。

ReflexWorksでは、容易なスケールアウト拡張とトランザクション処理の両立は実現しているが実はAvailabilityを若干緩めている。実際にノード障害があってフェイルオーバするまでの間は多少の停止時間があり、また、マスター更新の際は各ノードの同期を取るために運用を停止したうえで実行しなければならないなどの制約がある。

つまらん お前の話はつまらん



まあ、少し待ちなさい。
実際の運用で大事なのは、MTTRMean Time to Repair)つまりどれだけ早く復旧できるかである。
ReflexWorksは、特定のノードが故障するとシステム全体がダウンするような単一障害点はなく、サービスの継続利用が可能な仕組みになっている。また、障害により担当ノードにアクセスできなくなった場合でも自動的に他のノードに引き継がれるため障害の影響は部分的であり、再ログインは必要になるものの)ユーザ単位にリストアするため数分程度で復旧できる。実際の復旧時間で比較すればRDBのフェイルオーバよりも短いかもしれない。

Cloud = Scalability + Consistency!?

ミッションクリティカルな企業システムでは、非常に高い可用性が要求されるのは当然なのだが、何よりも重要なのはデータの一貫性であって、AvailabilityをとるためにEventually Consistentなシステムにするというのは本末転倒である。かねてより、Eventually Consistentはナンセンスだと主張される方もいらっしゃったが(スケールアウトアンチテーゼ)、実際に一貫性を緩くするのはビジネス的に受け入れられないケースは多い。

ビジネスだけではない。以下の事例を見れば、コンシューマ向けWebサービスにおいても、一貫性は大きな課題であることが伺える。

twitterがHBASEを選択した理由の一つがシンプルな一貫性モデルであったこと。
Facebookが新サービスの基盤にしたのは、MySQLでもCassandraでもなく、HBaseだった


Instagramがスケールさせてきた際に一貫性問題が発生していたこと。
「バックエンドの経験はなかった」Instagram創業者は、どうやってシステムをスケールさせてきたか
クラウド = 「Scalability + Availability」といわれた時代もあったが、今後の主流は「Scalability + Consistency」、つまり、スケールさせつつ、どうやって一貫性を保証するかが重要になっていると思う。

スケーラビリティの実現手段

ReflexWorksが実現しようとしていることとは、容易なスケールアウト拡張と一貫性の両立である。では、可用性を緩めさえすればこの2つは両立できるのだろうか。

実はそんなに甘くない。

サギー

まあ、少し待ちなさい。
実際のオンラインシステムでスケールが必要になるケースというのは、多くの場合はユーザ数増加などによる負荷増大が原因である。それであればユーザID単位のシャーディング(分散配置)で解決できる。1ユーザあたりのデータ量の大きさが問題になる場合は利用期間や容量制限などで解決すればよい。

このシャーディングの考え方は特別に新しい技術ではないがとても実用的である。
Salesforceのマルチテナントアーキテクチャーにおける組織IDであったり、先ほどのInstagramのスケール化でもシャーディングで解決しているそうである。


ReflexWorksにおいてもユーザID単位でのシャーディングを基本としており、ConsistentHashアルゴリズムにより担当ノードを決定する。一度担当ノードが決まれば基本的にそこだけアクセスすればよく、ユーザ数が増えて処理能力が足りなくなったら単純にノード追加すればよい。


ただし、他ノードのデータを参照したい場合はリモート呼び出しで対応する必要があり、この場合はACIDは保証されない。「容易なスケールアウト拡張と一貫性の両立」といっておきながら分散トランザクション処理ができないなんてイミフwww、と思われるかもしれないが、複数ノードに跨がった更新処理はパフォーマンスのことを考えたらやるべきではないし、これを許してしまうと密結合の世界に誘導してしまうことになりかねない。

とにかく、疎結合であることは重要。密結合になってしまうと絶対にスケールしない。

分散トランザクションがなくても、実際にはユーザのグルーピング機能などを使って同一ノードに配置するなどの代替案で対応できると思われるので、本当に分散トランザクション処理が必要なのか設計の段階でよく検討すべきところではある。

その他、ReflexWorksでは、サーバはデータを返すだけでクライアントでページを動的に生成したり、帳票印刷といったような重い処理をクライアントで実行したりと、サーバの負荷軽減のための工夫が随所でなされている。単なるシャーディングだけではなく、疎結合を基本に全体的にサーバ負荷軽減がなされるようなアーキテクチャーになっている。




0 件のコメント:

 
© 2006-2015 Virtual Technology
当サイトではGoogle Analyticsを使ってウェブサイトのトラフィック情報を収集しています。詳しくは、プライバシーポリシーを参照してください。