最近、スケーラブルなシステムとNoSQLの決定に関する議論が頻繁に行われ始めました。 AmazonのCTOによって書かれたこの記事は、私の意見では、スケーラブルなシステムを構築する際に生じる問題、ツールボックスを選択する際に考慮すべきこと、cassandraの作成者がcassandraでAPを提供し、HBaseでCPを提供する際に考慮すべきことを示す最高の入門書の1つですなどなど。
はじめに
Amazonクラウドコンピューティングは、インフラストラクチャサービスに基づいています。 Amazon S3、SimpleDB、EC2など。 スケーラブルなコンピューティングプラットフォームとアプリケーションを構築できます。 これらのサービスの要件は非常に厳しいです。 優れたセキュリティ、スケーラビリティ、可用性、パフォーマンス、およびリソースの効率的な使用を提供する必要があります。 そして、これらすべてを世界中の何百万人もの顧客に提供しています。
内部的には、これらのサービスは世界規模で動作する巨大な分散システムです。 数兆および数兆のリクエストを処理する場合、通常非常に低い確率で発生するイベントが発生することが保証されているため、これにより追加の困難が生じます。 また、システムを設計および開発する際には、これを考慮する必要があります。 世界中で、あらゆる場所でレプリケーションを使用して、必要なパフォーマンスと高可用性を提供しています。 複製によって目標に近づくことができますが、それでも目標を透過的に達成することはできません。 レプリケーションを使用するサービスのユーザーが遭遇する微妙な違いがいくつかあります。
これらの微妙な違いの1つは、システムによって提供されるデータの一貫性のタイプです。 特に、多くの一般的な分散システムは、データ複製のコンテキストで結果整合性モデルを使用します。 Amazonで大規模なスケーラブルなシステムを開発するとき、大規模なスケーラブルなシステムでのデータ複製に関連する一連のルールと抽象化を使用しました。 高可用性とデータの一貫性の間の妥協点を見つけることに焦点を合わせました。 この記事では、世界規模で機能する信頼性の高い分散システムを構築するためのアプローチを形作った情報の一部を調べます。
歴史的視点
理想的な世界では、一貫性のモデルは1つしかありません。データの更新を実行すると、すべてのオブザーバーが更新を確認できます。 これを達成することに関する最初の問題は、70年代後半のDBMSで発生しました。 このテーマに関する最良の研究は、Bruce Lindsayの分散データベースに関する注意事項です。 彼は、データベース複製の基本原則の概要を説明し、一貫性の達成に関連するいくつかの手法について説明します。 これらの手法の多くは、配布の透明性を実現しようとしています。そのため、ユーザーの観点からは、多くの接続されたシステムではなく、単一のシステムのように見えます。 当時の多くのシステムは、システム全体の障害が透明性の侵害よりも優れているというアプローチに従っていました。
90年代半ば、インターネット上のシステムの成長に伴い、このプラクティスは改訂されました。 この時点で、人々はアクセシビリティが最も重要な財産であると信じるようになり始めましたが、妥協として何を犠牲にするかを決めることができませんでした。 バークレーのエリック・ブリューワー教授は、当時Inktomi
(成功した検索エンジンをリリースした会社で、後にYahooに吸収されました-約Per。)でしたが、2000 PODC会議のレポートですべての妥協をまとめました。 彼は、分散データを持つシステムの3つのプロパティの一貫性、ノードの1つに障害が発生したときのシステム可用性(システム可用性)、およびネットワークセグメント間の接続損失に対する耐性(パーティショントレランス)であると述べるCAP定理を提示しました
(以下、ネットワークのセグメンテーションとは、各システムが別々に動作する場合、分散システムの各コンポーネント間の通信が失われることを意味しますが、互いに「見えない」-約レーン) -一度に2つしか達成できません。 より正式な確認は、2002年のセスギルバートとナンシーリンチの記事に掲載されています。
ネットワークセグメント間の通信の損失に対する耐性を提供しないシステムは、データの一貫性と可用性を実現できます。これは、多くの場合、トランザクションプロトコルを使用して実現されます。 この場合、特定の状況はシステム障害として扱われます。 たとえば、クライアントがノードの一部を表示しない場合。 大規模でスケーラブルなシステムでは、データの一貫性と可用性を同時に達成できないため、セグメンテーションが頻繁に存在することに注意してください。 これは、2つの選択肢があることを意味します。一貫性を弱めることにより、ネットワークセグメンテーションの条件で高可用性を備えたシステムを作成できるようにするか、特定の状況でシステムを使用できなくなる一貫性に焦点を当てます。
どちらのオプションも、システム機能にクライアント側の開発者の注意が必要です。 システムが整合性に焦点を合わせている場合、開発者は、たとえば記録にシステムが利用できない可能性があることに留意し、データを失わないようにこの状況を処理する必要があります。 システムがアクセシビリティに重点を置いている場合、常に記録を提供できますが、場合によってはデータの読み取りは最近の記録の結果を反映しません。 開発者は、クライアントが本当に最新の変更を本当に必要とするかどうかを決定する必要があります。 多くの場合、わずかに古いデータでも問題ありません。
基本的に、ACIDに準拠するトランザクションシステムの一貫性は、わずかに異なる種類の一貫性です。 ACIDでは、一貫性とは、トランザクションの完了時にデータベースが一貫した状態にあることの保証を指します。 たとえば、アカウント間で送金する場合、アカウントの金額は変更しないでください。 ACID準拠のシステムでは、通常、トランザクションとデータベースツールを使用してデータの整合性を確保することにより、この種の一貫性が確保されます。
一貫性-クライアントとサーバー
一貫性には2つの観点があります。 開発者/クライアントの観点からの1つ:データの更新をどのように見るか。 2番目はサーバー側からのものです。システム内の更新はどのように行われ、更新に関してシステムが何を保証できますか。
顧客の一貫性
顧客の観点から、次のコンポーネントがあります。
ストレージシステム 。 現時点では、ブラックボックスと見なしています。 ただし、安定性とアクセシビリティを確保するために構築されたものは、非常にスケーラブルで分散されていることを考慮しています。
プロセスA ストレージシステムへの書き込みおよびストレージシステムからの読み取りを行うプロセス。
プロセスBおよびC。 プロセスAから独立した2つのプロセス。ストレージシステムへの書き込みと読み取りも行います。 それらがプロセスであるか、1つのプロセスのスレッドであるかは関係ありません。 唯一重要なことは、それらが独立しており、情報を交換するために相互作用する必要があるということです。
クライアント(クライアント側)の一貫性は、オブザーバー(この場合、プロセスA、B、C)がストレージシステム内の指定されたオブジェクトの変更をいつどのように見るかを決定します。 さまざまな種類の一貫性を示す次の例では、プロセスAがデータの更新を実行しました。
強い一貫性 。 更新が完了すると、その後のデータへのアクセス(プロセスA、B、またはCによる)は更新された値を返します。
弱い一貫性 。 システムは、後続のデータアクセスが更新された値を返すことを保証しません。 更新された値が返される前に、いくつかの条件が満たされる必要があります。 更新から、各オブザーバーが更新された値を常に見ることが保証される瞬間までの期間は、
不整合ウィンドウと呼ばれ
ます 。
最終的な一貫性 。 一貫性が弱い特殊なケース。 システムは、新しいデータの更新がない場合、最終的にすべてのクエリが最後に更新された値を返すことを保証します。 障害がない場合、最大の不一致ウィンドウサイズは、通信の遅延、システムの負荷、複製スキームに応じたレプリカの数などの要因に基づいて決定できます。 「長期的な一貫性」を実装する最も一般的なシステムはDNSです。 更新されたレコードは、構成パラメーターとキャッシュ間隔の設定に従って配布されます。 最終的に、すべてのお客様に更新が表示されます。
最終的な整合性には、考慮すべき重要な多くのバリエーションがあります。
因果関係の一貫性 。 プロセスAがプロセスBにデータを更新したことを通知した場合、このデータに対するプロセスBの後続の呼び出しは更新された値を返し、レコードは以前の値を置き換えることが保証されます。 プロセスAに因果関係のないプロセスCへのアクセスは、結果整合性の通常の規則に従います。
一貫性モデル「Read-your-writesの一貫性」 。 これは、データを更新した後、プロセスAがアクセス時に常に更新された値を受け取り、古い値を参照しないという重要なモデルです。 これは、因果一貫性の特殊なケースです。
セッションの一貫性 。 プロセスがセッションのコンテキストでリポジトリにアクセスする場合、これは以前のモデルの実用的なバージョンです。 セッションが存在している限り、システムは読み取り/書き込みの一貫性を保証します。 何らかの障害が原因でセッションが終了した場合は、新しいセッションを作成する必要があります。これにより、他のセッションと重複しないことが保証されます。
単調な読み取り一貫性モデル 。 プロセスが特定の値を検出した場合、その後このデータにアクセスすると、古い値が取得されることはありません。
単調な書き込み一貫性モデル 。 このバージョンでは、システムは1つのプロセスの記録の順序を保証します。 このレベルの一貫性を提供しないシステムは使用が困難です。
これらのバリエーションのいくつかは組み合わせることができます。 たとえば、単調な読み取りとセッションの一貫性を組み合わせることができます。 実用的な観点から、単調な読み取りと読み取り/書き込みは、「長期的に一貫性」を実装するシステムで最も望ましいですが、必ずしも必要ではありません。 この組み合わせにより、アプリケーションの開発が容易になりますが、ストレージは一貫性を弱め、高可用性を実現できます。
「結果整合性」は、極端な分散システムのある種の難解な詩ではありません。 バックアップサーバーへの複製による信頼性(プライマリバックアップの信頼性)を提供する多くの最新のリレーショナルDBMSは、同期と非同期の2つのモードでレプリケーションメカニズムを実装しています。 同期モードでは、レプリカの更新はトランザクションの一部です。 非同期モードでは、更新はバックアップとして配信されますが、多くの場合ログが配信されます。 後者の場合、ログが配信される前にプライマリサーバーで障害が発生すると、プライマリサーバーではなくバックアップサーバーからの読み取りによって古いデータが返されます。 また、読み取りのスケーラビリティを向上させるために、リレーショナルDBMSは、バックアップサーバーからの読み取り機能を提供し始めました。これは、「長期間の一貫性」を保証する典型的なケースであり、不整合ウィンドウのサイズはログの送信頻度に依存します。
サーバー側の一貫性
サーバー側では、この方法またはその方法が開発者に与えるものを理解するために、システムで更新がどのように配布されるかをより深く理解する必要があります。 最初にいくつかの定義に同意しましょう:
N =データのコピー(複製)を保存するノードの数。
W =更新が完了したと見なされる前に更新の受信を確認する必要があるレプリカ
の数。
R =データの読み取り要求を処理するときに接続されるレプリカの数。
W + R> Nの場合、記録に参加し、読み取りに参加するレプリカのセットは常に交差し、強い一貫性を保証できます。 リレーショナルDBMSのバックアップサーバーへの同期レプリケーションのメカニズムは、N = 2、W = 2、およびR = 1です。 どのレプリカから読み込むかは関係ありません。実際のデータは常に読み込まれます。 非同期複製を使用し、バックアップサーバーからの読み取りを有効にすると、N = 2、W = 1、およびR = 1になります。 この場合、R + W = Nであり、データの一貫性は保証できません。
このような構成の問題は、障害のためにWノードに書き込めない場合、書き込み操作がエラーを返し、システムにアクセスできないことに注意することです。 たとえば、N = 3、W = 3、2つの使用可能なノードがある場合、システムは書き込みエラーを生成する必要があります。
高いパフォーマンスと可用性を提供する分散リポジトリでは、レプリカの数は通常2つ以上です。 フォールトトレランスのみに焦点を当てたシステムでは、N = 3(W = 2およびR = 2)を使用することがよくあります。 非常に高い読み取り負荷を処理する必要のあるシステムは、多くの場合、フォールトトレランスを提供するために必要以上のレプリカを使用します。 Nの値は、R = 1の場合、数十または数百のノードになることがあるため、1つのノードへのクエリは結果を返します。 システムは、更新のためにデータの一貫性セットW = Nに焦点を合わせました。これにより、記録が成功する可能性が低くなります。 フォールトトレランスを必要とするが強力な一貫性を必要としないシステムの構成では、W = 1を使用して最小更新期間を取得し、レイジー(遅延、流行)技術を使用して残りのレプリカを更新します。
N、W、およびRの構成方法は、さまざまな負荷のユースケースとパフォーマンス要件によって異なります。 R = 1、N = Wの場合、読み取り速度を最適化し、W = 1、R = Nの場合、非常に高速な書き込みのためにシステムを最適化します。 もちろん、後者の場合、障害が発生した場合のシステムの存続は保証されません。W<(N + 1)/ 2の場合、複数のノードがさまざまな書き込み操作中に交差しない場合、レコードが競合する可能性があります。
W + R <= Nの場合、弱い/最終的な一貫性が発生します。 つまり 書き込みおよび読み取り中にノードのセットが交差しない可能性があります。 これが意図的なステップであり、フォールトトレランスの要件ではない場合、Rを1以外に設定することはほとんど意味がありません。 弱い整合性は、主に2つのケースで発生します。1つ目は、前述のように読み取りスケーラビリティを提供するための多数のノードへのレプリケーションであり、2つ目はより複雑なデータアクセスです。 単純なキー値システムでは、バージョンを比較して、最後に書き込まれた値を判断するのはかなり簡単です。 しかし、オブジェクトのセットを返すシステムでは、どのセットが最後に関連すると見なされるかを判断するのはより困難です。 W <Nであるほとんどのシステムには、バックグラウンドで必要なノード(セットWに含まれない)のデータを更新するメカニズムが含まれています。 すべてのノードを更新する前の期間は不整合のウィンドウであり、これについては前に説明しました。 W + R <= Nの場合、システムはまだ更新を受信していないノードからデータを読み取ることができます。
読み取り/書き込み、セッション、単調一貫性モデルを実装する機能は、一般に、分散システム全体で作業を提供する特定のサーバーにクライアントをバインドすることに依存します。 クライアントが毎回同じサーバーにアクセスする場合、読み書きの読み取りと単調な読み取りの実装は非常に簡単です。 同時に、負荷分散とフォールトトレランスを実装するのは多少困難ですが、これは簡単なソリューションです。 スティッキーなセッションを使用すると、これが明示的になり、クライアントが推論できる露出レベルが提供されます
(翻訳オプションは大歓迎です) 。
場合によっては、クライアントが読み取り/書き込みと単調な読み取りを実装します。 レコードにバージョンを追加すると、クライアントは最後に検出されたバージョンよりも小さいバージョンの値を破棄します。
セグメント化は、システムの一部のノードが他のノードに接続できないが、両方のノードセットにクライアントがアクセスできる場合に発生します。 従来のクォーラムメカニズムを使用すると、Wノードを持つセグメントは引き続き機能し、更新を受信できますが、別のセグメントにはアクセスできなくなります。 読書にも同様の考慮事項が適用されます。 読み取りおよび書き込み中のノードのセットは定義により交差するため、より小さなノードのセットはアクセスできなくなります。 セグメンテーションはまれにしか発生しませんが、データセンターとデータセンター内の両方で発生する可能性があります。
一部のアプリケーションでは、一部のノードが使用できないことは受け入れられないため、任意のセグメントと対話するクライアントが正常に動作できることが重要です。 この場合、両方のセグメントがデータを格納するための新しいノードのセットを定義し、セグメント間の通信が復元されるとマージ操作が実行されます。
アマゾンのダイナモ
Amazonのダイナモは、アプリケーションのアーキテクチャに従って上記のすべてのパラメーターを構成できるシステムです。 これは、多くのeコマースプラットフォームサービスおよびAmazon Webサービスで使用されるキーバリューストレージシステムです。 Dynamo開発の目標の1つは、複数のデータセンターに分散していることが多いDynamoストレージシステムのインスタンスを使用するサービス所有者が、一貫性、安定性、可用性、システムパフォーマンスの妥協点を決定できるようにすることです。
上記の要約
高度にスケーラブルで信頼性の高い分散システムでのデータの不整合は、次の2つの理由で許容されるはずです。 すべてのノードが機能している場合でも、システムの一部にアクセスできないことを宣言する必要がある場合、セグメンテーション処理。
矛盾が許容されるかどうかは、クライアントアプリケーションによって異なります。 いずれにせよ、開発者は、ストレージシステムによってどのような整合性が提供されるかを忘れてはならず、アプリケーションを開発する際にこれを考慮する必要があります。 セッション整合性や均一な読み取りなど、結果整合性モデルには、開発者の作業を楽にする多数の実用的な改善点があります。 多くの場合、アプリケーションは問題なく結果整合性を使用できます。 特定の広範なケースは、ユーザーの観点から一貫性の概念を持っているWebサイトです。 この場合、不整合ウィンドウは、ユーザーが次のページに進むための予想時間よりも短くする必要があります。 これにより、次の読み取り要求までシステムで更新を配布できます。
この記事の目的は、グローバルスケールで動作する必要があるシステムの複雑さを認識し、必要なパフォーマンス、可用性、復元力をアプリケーションに提供できるように慎重に調整する必要があることです。 分散システムの設計者が作業しなければならないことの1つは、システムの顧客が高度にスケーラブルなシステムを開発する現実を体験できる不整合ウィンドウのサイズです。
翻訳を改善するためのコメントと提案を歓迎します。