BT

Your opinion matters! あなたのご意見でInfoQが変わる!

スケーラビリティに関するベストプラクティス:eBayからの教訓

| 作者 Randy Shoup フォローする 5 人のフォロワー , 翻訳者 編集部 フォローする 0 人のフォロワー 投稿日 2008年8月21日. 推定読書時間: 16 分 |

A note to our readers: As per your request we have developed a set of features that allow you to reduce the noise, while not losing sight of anything that is important. Get email and web notifications by choosing the topics you are interested in.

eBayが日々挑んでいる主要なアーキテクチャの勢力は、スケーラビリティです。これはアーキテクチャや設計に関するあらゆる意思決定を特徴づけたり、駆り立てたりします。世界中には何億人ものユーザーが存在し、1日当たりのページ閲覧は20億を超える中、当社システム内には何ペタバイトにも及ぶデータが保存されていることを考慮すれば、スケーラビリティはもはや選択肢にとどまらず、まさに必要不可欠なものと言えます。

スケーラブルなアーキテクチャにおいて、リソースの使用は、ユーザートラフィックやデータ容量などで測定される負荷とともに直線的に増加します。パフォーマンスが単体の作業に付随するリソース使用に関するものである一方、スケーラビリティは作業の単位(量、サイズ)の増加につれてリソースの使用がどのように変化するかに関するものです。別の言い方をすると、スケーラビリティは価格対パフォーマンス曲線という形をとり、その曲線のある一点での値とは対照的です。

スケーラビリティには、トランザクション、運用、および開発に関する取り組みなど、多くの局面があります。この記事では、eBayが長い時間をかけて学んだ、Webベースシステムのトランザクション関連のスループットをスケーリングするための主なベストプラクティスをいくつか紹介します。これらのベストプラクティスの大半は読者にとっておなじみのものだと思われますが、初めて聞くものもあるかもしれません。すべては、eBayのサイトを開発、運用する人々の経験を集結して得たものです。

ベストプラクティス#1:機能別の区分

SOA、機能分割、または単に優れたエンジニアリングなど、いろいろ呼び方はありますが、関連する機能群はグループにまとめ、関連しない機能群は別々にするという方法があります。さらに、関連しない機能の分割が可能であればあるほど、それらの機能を個別にスケーリングするためのフレキシビリティが得られます。

これはコードレベルでは常に行われていることです。JARファイル、パッケージ、バンドルなどはすべて、ある機能セットを別の機能セットから分離し、抽象化するために使用するメカニズムです。

eBayではアプリケーション層にて異なる機能を別々のアプリケーションプールにセグメント化します。販売機能、入札機能、検索機能などは、それぞれ別個のアプリケーションサーバーセットによって提供されます。eBayでは全体で約16,000台のアプリケーションサーバーを220個の異なるプールに編成しています。これによって、機能の需要やリソース消費に応じて、各プールを個別にスケーリングすることができます。また、リソース依存の切り離しや合理化が可能になり、たとえば、販売プールは比較的小さなバックエンドリソースの一部とだけ通信すればよくなるのです。

データベース層でもほぼ同様のアプローチに従っています。eBayにはモノリシックデータベースはひとつもありません。その代わり、ユーザーデータ用のデータベースホストセット、アイテムデータ用セット、購入データ用セットなど、計1000個の論理データベースが400個の物理ホストに存在します。繰り返しますが、このアプローチによって、データタイプごとに個別にデータベースインフラがスケーリングできるのです。

ベストプラクティス#2:水平分割

機能の区分化によって光明が見えてきたわけですが、完全にスケーラブルなアーキテクチャにとってそれだけでは十分ではありません。ある機能は他の機能から分離されるかもしれませんが、1つの機能エリアの需要は時間とともに肥大し、どのような単独システムよりも大きくなってしまいます。私たちが好んで自身に言い聞かせていることですが、「分割できないなら、スケーリングもできない」のです。特定の機能エリア内では、価格対パフォーマンスのバランスがうまく保たれるよう、作業負荷を処理しやすい単位に分割できる必要があります。これこそ、水平分割の役割です。

アプリケーション層においてeBayの対話は意図的にステートレスですが、水平分割の実行はささいなことです。標準的なロードバランサを用いて受信トラフィックをルーティングします。すべてのアプリケーションサーバーは等しく構築され、どれもトランザクション状態を保持しないため、どのサーバーでも目的を果たします。より多くの処理能力が必要な場合は、アプリケーションサーバーを増やせばいいのです。

データは本質的にステートフルであるため、より困難な課題はデータベース層において発生します。当社はここでデータを主要なアクセスパスに沿って水平に分割(「シャード」構築)します。たとえば、ユーザーデータは現在20台のホストに分かれており、各ホストはユーザーの1/20を含みます。ユーザー数が増えたり、各ユーザー用の保存データが増えたりすると、ホストを追加し、ユーザーをさらに再分割します。上述のように、アイテム、購入、アカウントなどに対して同じアプローチをとります。異なる使用ケースは、異なるデータ区分化スキームを使用します。つまり、キーという単純なモジュールに基づくもの(例:1で終わるアイテムIDはあるホストに、2で終わるものは次にホストに分類する)、ID範囲に基づくもの(例:0~1M、1~2Mなど)、参照テーブルに基づくもの、またこれらの戦略の組み合わせに基づくものなど、さまざまです。しかし、区分化スキームの詳細を問わず、一般観念として、データの区分化および再区分化をサポートするインフラは、サポートしないインフラよりもはるかにスケーラブルとなります。

ベストプラクティス#3:分散トランザクションの回避

この時点で、読者の皆さんはデータ区分化のプラクティスがどのように機能的および水平的にトランザクション関連の保証と合致するのか疑問に思っていることでしょう。結局、関心のあるほぼすべての操作は、2種類以上のエンティティを更新し、ここですぐに頭に浮かぶのはユーザーとアイテムでしょう。月並みな答えは、よく知られ、理解されているものですが、2層コミットを使用してあらゆるリソースにわたってすべてが更新されるか、まったく何も更新されないかを保証することによって、さまざまなリソースを網羅する分散トランザクションを作成することです。しかし残念ながら、この悲観的な手法にはかなりのコストがかかってしまいます。スケーリング、パフォーマンス、および待ち時間は、調整コストによってマイナスの影響を受け、依存するリソースや参加クライアントの数を増やすにつれて幾何学的に悪化します。同様に、可用性もすべての依存リソースが利用可能である必要があるという要件によって制限されます。実用的な答えは、関連しないシステムにわたるトランザクションの保証を緩和することです。

つまり、すべてを手にすることはできないということです。特に、複数のシステムまたは区分にまたがる即座の一貫性を保障することは、通常、必要ではないし、また不可能です。Inktomi の創立者Eric Brewer氏が約10年前に主張したCAP定理によると、一貫性(C:consistency)、可用性(A:availability)、および区分耐性(P:partition-tolerance)という非常に望ましい3つの特性のうち、同時に選べるのは2つです。高トラフィックのWebサイトでは、スケーリングに欠かせない区分耐性を選択する必要があります。24時間運営のWebサイトでは、通常、可用性を選択します。したがって、一貫性は道を譲らなくてはなりません。

eBayでは、クライアント側のトランザクションや分散トランザクションはどのような種類でもまったく許容しておらず、2層コミットは存在しません。ある明確な状況下では、単独データベース上の複数のステートメントを単独のトランザクション操作に統合することはあります。しかし、大半において、個別のステートメントは、自動的にコミットされます。このように正統的なACID特性を意図的に緩和するとすべての場所での即座の一貫性は保障されませんが、現実的には、大部分のシステムはほとんどの時間にわたって利用可能です。もちろん、eBayではデータベース操作の慎重な順序づけ、非同期の回復イベント、調整および決済バッチなど、さまざまな技術を用いてシステムが最終的に一貫性を保てるよう努力しています。当社は、特定の使用ケースの一貫性需要に応じて、方法を選択しています。

ここでアーキテクトやシステム設計者に主に伝えたいことは、一貫性が、融通の利かないオール・オア・ナッシングの定理としてとらえるべきではないということです。現実世界の大部分の使用ケースでは、即座の一貫性をまったく必要としません。可用性がオール・オア・ナッシングでないのと同様です。当社は、ジョブに関して適切なレベルの一貫性の保障を特定の運用の要件に合わせて調整するのと同様に、定期的に一貫性をコストなどの他の影響力とトレードオフしています。

ベストプラクティス#4:非同期的な機能分離

スケーリングに対する次の主要な要素は、非同期性の積極的な使用です。コンポーネントAがコンポーネントBを同期的に呼び出す場合、AとBは密接に結合され、その結合システムは1つのスケーラビリティ特性を持ちます。つまり、Aをスケーリングするには、Bもスケーリングしなくてはならないというものです。同様に、可用性に対する影響も問題です。ロジック初級編を振り返ってみると、AがBを含意するなら、Bの否定はAの否定を含意します。言い換えると、Bがダウンすると、Aもダウンするのです。これと反対に、AとBがキュー、マルチキャストメッセージング、バッチプロセスなどの手段を通じて非同期的に結合している場合、一方は他方と個別にスケーリング可能です。さらに、AとBは独立した可用性の特性を持つことになり、Bがダウンしていたり困難な状態にとどまっていたりしてもAは動作を続行することができます。

この原理は、インフラの上り・下りに適用可能で、また適用すべきものです。理解しやすいプログラミングレベルを保ちつつ個別のコンポーネント内で非同期性を実現するには、SEDA(Staged Event-Driven Architecture:イベント駆動型アーキテクチャ)のような手法が使用できます。コンポーネント間でも原理は同じで、できるだけ同期結合を回避します。しばしば、2つのコンポーネントの間には、イベントにおいて互いに直接行うビジネス通信は存在しません。どのようなレベルでも、処理をステージやフェーズに切り離すこと、またそれらを非同期的に結合することが、スケーリングには不可欠です。

ベストプラクティス#5:非同期フローへの処理の移行

非同期的な切り離しの次は、できるだけ非同期側に処理を移行する番です。リクエストへの高速な応答が不可欠なシステムでは、これはリクエスト側が経験する待ち時間を大幅に低減することができます。Webサイトや取引システムでは、データや実行待ち時間(すべての処理どれだけ早く終了するか)と、ユーザーの待ち時間(ユーザーがどれだけ早くレスポンスを得られるか)をトレードオフする価値があります。アクティビティの追跡、課金、決済、報告などが、バックグランドに属する明確な処理の例です。しかし、しばしば、主要な使用ケースの処理における重要なステップは、非同期的に実行するために自身で分かれます。待てるものは、待つべきなのです。

同様に重要なことでありながらしばしば正当に評価されていない事実として、非同期性がインフラコストを大幅に削減できるというものがあります。同期的な動作では、ピーク時の負荷を対象にインフラをスケーリングすることが強要され、この場合、まさにその時間での最悪な日の最悪な時間を取り扱う必要があります。一方、コストのかかる処理を非同期フローに移行すると、インフラをピーク時ではなく平均的な負荷を対象にスケーリングできるようになります。すべてのリクエストを即座に処理する必要がなくなり、キューは時間とともに処理を分配し、したがって、ピークを抑制します。システム上の負荷が鋭角状であったり、変動したりすればするほど、この利点は大きくなります。

ベストプラクティス#6:あらゆるレベルでの仮想化

仮想化と抽象化はどこにでもあり、あらゆる問題への解決法は別のレベルの間接的行動であるという昔のコンピュータ科学の格言に従っています。オベレーティングシステムはハードウェアを抽象化したものです。多くの現代語における仮想マシンとはオペレーティングシステムを抽象化したものです。オブジェクトリレーショナルマッピング層はデータベースを抽象化したものです。ロードバランサと仮想IPはネットワークエンドポイントを抽象化したものです。eBayはインフラを機能やデータごとに区分化してスケーリングするため、これらの区分の追加レベルの仮想化が非常に重要です。

たとえば、eBayではデータベースを仮想化します。アプリケーションはデータベースの論理的表現と対話し、続いてコンフィギュレーションを通して特定の物理マシンとインスタンスにマッピングされます。同様に、アプリケーションは、特定のレコード(たとえば、ユーザーXYZのレコード)を特定の区分に割り当てる分割ルーティングロジックから抽象化されます。これらの抽象化はともに、当社が作成したO/R層で実装されます。これによって、運用チームは、物理ホスト間でそれらを分割したり、連結したり移動したりと、アプリケーションコードには一切触れず、論理ホストのバランスを再度整えることができます。

eBayはサーチエンジンも同様に仮想化しています。検索結果を抽出するため、アグリゲータコンポーネントは、複数の区分にわたってクエリを並列処理し、クライアント側では、高度に区分化されたサーチグリッドが1つの論理インデックスに見えます。

ここでの目的として、プログラマにとっての便利さだけではなく、運用上のフレキシビリティも挙げられます。ハードウェアやソフトウェアシステムは故障すると、リクエストのルーティングが再度必要です。コンポーネント、マシン、および区分が追加、移動、削除されたとして、仮想化を賢く使用すると、高ラベルのインフラは幸運にもこれらの変更には気づかず、したがって、ユーザー側でも自由に作成が可能になります。仮想化はスケーリングを管理しやすくするため、インフラのスケーリングを可能にします。

ベストプラクティス#7:適切なキャッシング

スケーリングに関する最後の要素は、キャッシングの賢明な利用です。ここで推奨する具体例は使用ケースに強く依存する傾向があるため、あまり普遍的ではありません。1日の終わりにおける効率的なキャッシュシステムのゴールは、保存制約、可用性の要件、および鮮度劣化への耐性の中、キャッシュのヒット率を最大にすることです。このバランスをとるのは非常に難しいものであることが分かります。経験上、いったんバランスをとっても時間とともに変わる可能性も高いのです。

キャッシングにおける最も明白な機会は、低速キャッシング、ほぼ読み取り専用のデータ、メタデータ、コンフィギュレーション、および静的データなどに付随します。eBayはこの種のデータを積極的にキャッシシングし、プル/プッシュ法を組み合わせて用いて、更新の中でも適度にシステムの同期を保ちます。同じデータに対するリクエストの繰り返しを減らすと、実質的な影響を与えることができます。より困難なのが、急激に変化する読み書きデータの扱いです。eBayでは大部分においてこれらの課題を意図的に回避しています。当社は従来から、リクエスト間の一時的なセッションデータをキャッシングしていません。同様に、アイテムやユーザーデータなど共有ビジネスオブジェクトもアプリケーション層においてキャッシュしていません。eBayでは明確に、このデータキャッシングの潜在的メリットを、可用性および正確さとトレードオフしています。書き添えておきますが、他のサイトは異なるアプローチをとっており、また別のトレードオフを行い、成功を収めています。

当然のことながら、良いことも過ぎれば禍となる可能性が高いのです。キャッシングにメモリを割り当てれば当てるほど、個別のリクエストに提供可能なサービスが少なくなります。しばしばメモリ制約のあるアプリケーション層では、これは非常に実質的なトレードオフです。しかし、さらに重要なことに、いったんキャッシュに頼って、主要システムのサイズ縮小という非常に抵抗しがたいステップをとってキャッシュのミスだけに対処するようになると、インフラは文字通りキャッシュなしでは生きていけなくなる場合があります。主要システムが負荷を直接に扱えなくなると、サイトの可用性はもはや100%キャッシュのアップタイムに依存するという、潜在的にかなり危険な状況となります。バランス再調整、移動、コールドスタートなどの日常業務のようなものにさえ問題が発生します。

適切に実装した優れたキャッシュシステムはスケーリング曲線の線形を下に曲げ、引き続いて起こるリクエストは比較的コストのかかる主要ストアよりもキャッシュから低コストでデータを引き出します。一方、キャッシュの誤った利用は、かなりのオーバーヘッドを増やし、可用性の課題をもたらします。キャッシングに対して効果のある機会をもたないシステムにはまだお目にかかったことはありません。重要なポイントは、自身の状況に適したキャッシング戦略を施すことです。

まとめ

スケーラビリティは時に「機能的ではない要件」と呼ばれることがありますが、これは機能性には関係しないことを言外に含み、また、あまり重要でないことを強く意味しています。しかし、これはまるで見当違いです。むしろ、私の意見では、スケーラビリティは機能性の必要条件であり、もしあるとすれば「優先度0」の要件です。

読者のみなさんがこれらのベストプラクティスの説明を読み、スケールに関係なく新しい方法で自身のシステムについて考えるのに役立てればと願います。

参考文献

  • eBay's Architectural Principles(PDF) (ビデオ)(英語)
  • Werner Vogels on scalability(リンク)
  • Dan Pritchett on You Scaled Your What?(PDF)
  • The Coming of the Shard(リンク)
  • Trading Consistency for Availability in Distributed Architectures(参考記事)
  • Eric Brewer on the CAP Theorem(リンク)
  • SEDA: An Architecture for Well-Conditioned, Scalable Internet Services(PDF)

著者について

Randy Shoup氏はeBayの有名なアーキテクトです。2004年以降、彼はeBayのサーチインフラストラクチャの主要アーキテクトを務めています。eBayに入る以前は、Tumbleweed Communicationsのチーフアーキテクトであり、またOracleやInformaticaではさまざまなソフトウェア開発およびアーキテクチャ業務を行ってきました。

同氏は、スケーラビリティやアーキテクチャパターンについて業界カンファレンスで定期的にプレゼンを行っています。

原文はこちらです:http://www.infoq.com/articles/scalability-principles
(このArticleは2008年5月27日に原文が掲載されました)

この記事に星をつける

おすすめ度
スタイル

こんにちは

コメントするには InfoQアカウントの登録 または が必要です。InfoQ に登録するとさまざまなことができます。

アカウント登録をしてInfoQをお楽しみください。

あなたの意見をお聞かせください。

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする
コミュニティコメント

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする

ディスカッション

InfoQにログインし新機能を利用する


パスワードを忘れた方はこちらへ

Follow

お気に入りのトピックや著者をフォローする

業界やサイト内で一番重要な見出しを閲覧する

Like

より多いシグナル、より少ないノイズ

お気に入りのトピックと著者を選択して自分のフィードを作る

Notifications

最新情報をすぐ手に入れるようにしよう

通知設定をして、お気に入りコンテンツを見逃さないようにしよう!

BT