分散データベースシステム101
または、分散データベース-FKが「ウェブスケール」とはどういう意味ですか?
分散データベースシステムは複雑な生物であり、さまざまなフレーバーがあります。大学でこれについてぼんやりと覚えていた研究の深さを掘り下げてみると、分散データベースシステムを構築するための重要な工学的問題のいくつかを説明しようと思います。
まず、いくつかの用語
ACID(Atomicity、Consistency、Isolation、Durability)プロパティ:これらは、望ましくない副作用を引き起こさずにトランザクションを確実に実装するために実施しなければならない重要な不変条件です。
アトミック性では、トランザクションが完了するか、完全にロールバックする必要があります。部分的に完了したトランザクションは決して表示されるべきではなく、システムはこれが起こらないように構築されなければなりません。
一貫性は、トランザクションがデータベーススキーマによって保証される不変条件(宣言的な参照整合性など)に決して違反しないことを要求します。たとえば、外部キーが存在する場合、存在しない親に敬意を表して子レコードを挿入することはできません。
分離では、トランザクションが互いに干渉しないようにする必要があります。トランザクションが並列または順次実行される場合、システムは同じ結果を保証する必要があります。実際には、ほとんどのRDBMS製品では、パフォーマンスと分離をトレードオフするモードが許可されています。
耐久性を確保するには、トランザクションがコミットされると、ハードウェアまたはソフトウェアの障害に対して堅牢な方法でトランザクションが永続ストレージに保持される必要があります。
これらの要件が分散システムに存在する技術的なハードルのいくつかを以下に説明します。
共有ディスクアーキテクチャ:クラスター内のすべての処理ノードがすべてのストレージにアクセスできるアーキテクチャ。これは、データアクセスの中心的なボトルネックになる可能性があります。共有ディスクシステムの例は、 Oracle RACまたは Exadataです。
シェアードナッシングアーキテクチャ:クラスター内の処理ノードに、他のクラスターノードからは見えないローカルストレージがあるアーキテクチャ。シェアードナッシングシステムの例は、 Teradataおよび Netezzaです。
共有メモリアーキテクチャ:複数のCPU(またはノード)がメモリの共有プールにアクセスできるアーキテクチャ。最新のサーバーのほとんどは、共有メモリタイプです。共有メモリは、分散システムで実行するのがはるかに難しいキャッシュやアトミック同期プリミティブなどの特定の操作を容易にします。
同期化:複数のプロセスまたはスレッドによる共有リソースへの一貫したアクセスを確保するためのさまざまな方法を説明する一般的な用語。一部のネットワークアーキテクチャ(TeradataのBYNETなど)にはネットワークプロトコルに同期プリミティブがありますが、これは共有メモリシステムよりも分散システムで行うのがはるかに困難です。また、同期にはかなりのオーバーヘッドが伴います。
準結合:分散システムの2つの異なるノードに保持されているデータの結合に使用されるプリミティブ。本質的には、結合を解決するために1つのノードから別のノードにバンドルされて渡される結合する行に関する十分な情報で構成されます。大規模なクエリでは、これには大量のネットワークトラフィックが含まれる可能性があります。
最終的な一貫性:分散システムのすべてのノードでの即時更新(読み取り時の一貫性)と、書き込み時のパフォーマンス(したがってトランザクションスループットの向上)をトレードオフするトランザクションセマンティクスの説明に使用される用語。結果整合性は、パフォーマンスの最適化として Quorum Replicationを使用して、データの複数のコピーが別々のノードに保持されている分散データベースでのトランザクションコミットを高速化する副作用です。
Lamportのアルゴリズム:共有メモリのないシステム間で相互排除(同期)を実装するためのアルゴリズム。通常、システム内の相互排除には、アトミックな読み取り-比較-書き込み、または共有メモリシステムでのみ実用的なタイプの同様の命令が必要です。他の分散同期アルゴリズムも存在しますが、Lamportのアルゴリズムは最初のものであり、最もよく知られています。ほとんどの分散同期メカニズムと同様に、Lamportのアルゴリズムはクラスターノード間の正確なタイミングとクロックの同期に大きく依存しています。
2フェーズコミット(2PC):複数の物理システムを含むデータベースの更新が一貫してコミットまたはロールバックされることを保証するプロトコルファミリ。2PCがシステム内で使用される場合でも、トランザクションマネージャーを介して複数のシステムで使用される場合でも、大きなオーバーヘッドが発生します。
2フェーズコミットプロトコルでは、トランザクションマネージャーは参加ノードに、トランザクションがコミットされることを保証できるようにトランザクションを永続化するように要求し、このステータスを通知します。すべてのノードが「ハッピー」ステータスを返すと、ノードにコミットのシグナルを送ります。すべてのノードがコミットが完了したことを示す応答を送信するまで、トランザクションはまだ開いていると見なされます。コミットが完了する前にノードがダウンした場合、トランザクションマネージャは、トランザクションがコミットされたことを示す肯定応答を受け取るまで、ノードが再起動したときにノードを再クエリします。
Multi-Version Concurrency Control(MVCC):データの新しいバージョンを別の場所に書き込み、新しいバージョンがコミットされるまで他のトランザクションが古いバージョンのデータを参照できるようにすることにより、競合を管理します。これにより、データベースの競合が減少しますが、新しいバージョンを書き込み、古いバージョンを廃止としてマークするための追加の書き込みトラフィックが発生します。
選択アルゴリズム:複数のノードを含む分散システムは、障害モードが多いため、単一システムよりも本質的に信頼性が低くなります。多くの場合、クラスター化されたシステムがノードの障害に対処するには、何らかのメカニズムが必要です。選挙アルゴリズムは、「リーダー」ノードが100%決定または信頼できない場合に、分散計算を調整するためにリーダーを選択するために使用されるアルゴリズムのクラスです。
水平分割:テーブルは、キーによって複数のノードまたはストレージボリュームに分割できます。これにより、大きなデータボリュームを小さなチャンクに分割し、ストレージノードに分散できます。
シャーディング:シェアードナッシングアーキテクチャでは、データセットを複数の物理ノードに水平に分割できます。このパーティショニングが透過的でない場合(つまり、クライアントがパーティションスキームを認識し、明示的にクエリするノードを決定する必要がある場合)、これはシャーディングと呼ばれます。一部のシステム(Teradataなど)は、ノード間でデータを分割しますが、場所はクライアントに対して透過的です。この用語は通常、このタイプのシステムと組み合わせて使用されることはありません。
一貫性のあるハッシュ:キーに基づいてパーティションにデータを割り当てるために使用されるアルゴリズム。ハッシュキーの均等な分散と、バケット数を効率的に伸縮させる機能が特徴です。これらの属性は、ノードの追加またはクラスターのドロップオフによりサイズが動的に変化する可能性があるノードのクラスター全体でデータを分割またはロードするのに役立ちます(おそらく障害のため)。
マルチマスター複製:クラスター内の複数のノードにまたがる書き込みを他のノードに複製できるようにする手法。この手法は、一部のテーブルをサーバー間でパーティション分割または分割し、他のテーブルをクラスター全体で同期できるようにすることで、スケーリングを容易にします。書き込みは、クォーラムではなくすべてのノードに複製される必要があるため、トランザクションのコミットは、クォーラム複製システムよりもマルチマスター複製アーキテクチャの方が高価です。
非ブロッキングスイッチ:内部ハードウェア並列処理を使用して、内部ボトルネックのないポートの数に比例したスループットを実現するネットワークスイッチ。単純な実装ではクロスバーメカニズムを使用できますが、これはNポートに対してO(N ^ 2)の複雑さを持ち、より小さなスイッチに制限されます。より大きなスイッチでは、ノンブロッキングミニマルスパニングスイッチと呼ばれるより複雑な内部トポロジを使用して、O(N ^ 2)ハードウェアを必要とせずに線形スループットスケーリングを実現できます。
分散DBMSの作成-どれくらい難しいのでしょうか?
いくつかの技術的な課題により、実際にこれを行うことは非常に困難です。分散システムを構築する複雑さが増すこととは別に、分散DBMSのアーキテクトは、いくつかの厄介なエンジニアリングの問題を克服する必要があります。
分散システムでのアトミック性:トランザクションによって更新されたデータが複数のノードに分散している場合、ノードのコミット/ロールバックを調整する必要があります。これにより、シェアードナッシングシステムに大きなオーバーヘッドが追加されます。共有ディスクシステムでは、すべてのノードがすべてのストレージを見ることができるため、単一のノードがコミットを調整できるため、これは問題ではありません。
分散システムの一貫性:上記の外部キーの例を使用するには、システムは一貫した状態を評価できなければなりません。たとえば、外部キー関係の親と子が異なるノードに存在する可能性がある場合、古い情報がトランザクションの検証に使用されないようにするために、ある種の分散ロックメカニズムが必要です。これが強制されていない場合、たとえば、子の挿入を許可する前に親の存在が確認された後に親が削除されるという競合状態になる可能性があります。
制約の施行の遅延(つまり、DRIを検証するコミットまで待機する)には、トランザクションの間ロックを保持する必要があります。この種の分散ロックには大きなオーバーヘッドが伴います。
データの複数のコピーが保持されている場合(半結合からの不必要なネットワークトラフィックを回避するためにシェアードナッシングシステムで必要な場合があります)、データのすべてのコピーを更新する必要があります。
分散システムでの分離:トランザクションに影響するデータが複数のシステムノードに存在する場合、ロックとバージョン(MVCCが使用されている場合)はノード間で同期する必要があります。特に、データの冗長コピーが保存されるシェアードナッシングアーキテクチャでの操作のシリアル化を保証するには、Lamportのアルゴリズムなどの分散同期メカニズムが必要です。これには、ネットワークトラフィックの大幅なオーバーヘッドも伴います。
分散システムでの耐久性:共有ディスクシステムでは、ノード間で分散同期プロトコルが依然として必要であることを除き、耐久性の問題は共有メモリシステムと本質的に同じです。DBMSはログへの書き込みをジャーナルし、データを一貫して書き出す必要があります。シェアードナッシングシステムでは、データの複数のコピーまたは異なるノードに保存されたデータの一部が存在する場合があります。ノード間でコミットが正しく行われるようにするには、2フェーズコミットプロトコルが必要です。また、これには大きなオーバーヘッドが発生します。
シェアードナッシングシステムでは、ノードが失われると、システムがデータを利用できなくなる可能性があります。このデータを軽減するために、複数のノードにデータを複製できます。この状況での一貫性は、データが通常存在するすべてのノードにデータを複製する必要があることを意味します。これにより、書き込み時にかなりのオーバーヘッドが発生する可能性があります。
NoSQLシステムで行われる一般的な最適化の1つは、クォーラムレプリケーションと結果整合性を使用して、トランザクションをコミット済みとして報告する前にクォーラムに書き込むことによりデータの一定レベルの復元性を保証しながら、データを遅延複製できるようにすることです。次に、データのコピーが存在する他のノードにデータが遅延複製されます。
「結果整合性」は、トランザクションがコミットされるとすぐにデータを一貫して表示する必要がある場合に受け入れられない可能性がある整合性の大きなトレードオフであることに注意してください。たとえば、金融アプリケーションでは、更新された残高がすぐに利用可能になります。
共有ディスクシステム
共有ディスクシステムは、すべてのノードがすべてのストレージにアクセスできるシステムです。したがって、計算は場所に依存しません。多くのDBMSプラットフォームもこのモードで動作します。OracleRACはそのようなアーキテクチャの例です。
共有ディスクシステムは、ストレージノードと処理ノード間のM:M関係をサポートできるため、大幅に拡張できます。SANには複数のコントローラーがあり、複数のサーバーがデータベースを実行できます。これらのアーキテクチャには、中心的なボトルネックとしてスイッチがありますが、クロスバースイッチにより、このスイッチは多くの帯域幅を持つことができます。一部の処理は、ストレージ帯域幅のトラフィックを削減できるストレージノードにオフロードできます(OracleのExadataの場合のように)。
スイッチは理論的にはボトルネックですが、利用可能な帯域幅は、共有ディスクアーキテクチャが大規模なトランザクションボリュームに非常に効果的にスケーリングすることを意味します。ほとんどの主流のDBMSアーキテクチャは、「十分な」スケーラビリティと高い信頼性を提供するため、このアプローチを採用しています。ファイバチャネルなどの冗長ストレージアーキテクチャでは、処理ノードとストレージノードの間に少なくとも2つのパスがあるため、単一障害点はありません。
シェアードナッシングシステム
シェアードナッシングシステムは、少なくとも一部のデータがノードに対してローカルに保持され、他のノードからは直接見えないシステムです。これにより、中央のスイッチのボトルネックが解消され、ノードの数に応じてデータベースを(少なくとも理論的には)拡張できます。水平分割により、データをノード間で分割できます。これは、クライアントに対して透過的である場合と透過的でない場合があります(上記のシャーディングを参照)。
データは本質的に分散されているため、クエリには複数のノードからのデータが必要になる場合があります。結合に異なるノードからのデータが必要な場合、半結合操作を使用して、あるノードから別のノードへの結合をサポートするのに十分なデータを転送します。これにより、大量のネットワークトラフィックが発生する可能性があるため、データの分散を最適化すると、クエリのパフォーマンスに大きな違いが生じる可能性があります。
多くの場合、データはシェアードナッシングシステムのノード間で複製され、準結合の必要性を減らします。通常、ディメンションはファクトテーブルよりも桁違いに小さく、ノード間で簡単に複製できるため、これはデータウェアハウスアプライアンスで非常にうまく機能します。また、通常はバッチでロードされるため、レプリケーションのオーバーヘッドはトランザクションアプリケーションよりも問題になりません。
シェアードナッシングアーキテクチャの固有の並列性により、データウェアハウスに特有の一種のテーブルスキャン/集計クエリに適しています。この種の操作は、処理ノードの数にほぼ比例してスケーリングできます。ノード間の大規模な結合は、半結合操作が大量のネットワークトラフィックを生成する可能性があるため、オーバーヘッドが大きくなる傾向があります。
大量のデータを移動することは、複数の更新のオーバーヘッドにより、このタイプのアーキテクチャが共有ディスクほど魅力的ではないトランザクション処理アプリケーションにはあまり役立ちません。したがって、このタイプのアーキテクチャは、データウェアハウスアプリケーションでは広く使用されない傾向があります。
シャーディング、クォーラムレプリケーション、結果整合性
クォーラムレプリケーションは、高可用性のためにDBMSがデータをレプリケートする機能です。これは、SANのような高可用性機能が組み込まれていない安価な汎用ハードウェアで動作することを目的としたシステムに役立ちます。このタイプのシステムでは、読み取りパフォーマンスと冗長ストレージのためにデータが複数のストレージノードに複製され、ノードのハードウェア障害に対するシステムの回復力を高めます。
ただし、すべてのノードへの書き込みのレプリケーションは、MノードおよびN書き込みに対してO(M x N)です。これにより、トランザクションのコミットを許可する前に書き込みをすべてのノードに複製する必要がある場合、書き込みが高価になります。クォーラムレプリケーションは、書き込みをノードのサブセットにすぐに複製し、バックグラウンドタスクによって他のノードに遅延書き込みすることを可能にする妥協案です。書き込みは、トランザクションがクライアントにコミットされたと報告される前にノードの最小サブセット(クォーラム)に複製されることを保証することにより、ある程度の冗長性を提供しながら、より迅速にコミットできます。
つまり、クォーラム外のノードを読み取ると、バックグラウンドプロセスが残りのノードへのデータの書き込みを完了するまで、古いバージョンのデータを見ることができます。セマンティクスは「結果整合性」と呼ばれ、アプリケーションの要件によっては受け入れられる場合と受け入れられない場合がありますが、リソースの使用においてトランザクションコミットがO(n)よりもO(1)に近いことを意味します。
シャーディングでは、クライアントがデータベース内のデータのパーティション化を認識する必要があり、多くの場合、「一貫性のあるハッシュ」と呼ばれるアルゴリズムのタイプを使用します。断片化されたデータベースでは、クライアントがキーをハッシュして、クエリを発行するクラスター内のサーバーを決定します。要求はクラスター内のノード全体に分散されるため、単一のクエリコーディネーターノードにボトルネックはありません。
これらの手法により、クラスターにノードを追加することで、データベースをほぼ線形の速度でスケーリングできます。理論的には、クォーラムレプリケーションは、基になるストレージメディアが信頼できないと見なされる場合にのみ必要です。これは、コモディティサーバーを使用する場合に役立ちますが、基盤となるストレージメカニズムに独自の高可用性スキームがある場合は価値が低くなります(たとえば、ミラーコントローラーとホストへのマルチパス接続を備えたSAN)。
たとえば、GoogleのBigTableは、クォーラムレプリケーションを使用するクラスター化されたファイルシステムであるGFS上にありますが、クォーラムレプリケーションを実装していません。BigTable(またはシェアードナッシングシステム)は、複数のコントローラーを備えた信頼性の高いストレージシステムを使用し、コントローラー間でデータをパーティション分割できます。並列アクセスは、データのパーティション分割によって実現されます。
RDBMSプラットフォームに戻る
これらの手法をRDBMSで使用できないという固有の理由はありません。ただし、このようなシステムではロックとバージョン管理が非常に複雑になり、そのようなシステムの市場は非常に特殊化される可能性があります。主流のRDBMSプラットフォームはいずれもクォーラムレプリケーションを使用していません。また、RDBMS製品(少なくとも重要な機能を備えた製品)については特に知りません。
共有ディスクおよび非共有システムは、非常に大きなワークロードに拡張できます。たとえば、Oracle RACは、63個の処理ノード(それ自体が大型のSMPマシンである可能性があります)およびSAN上の任意の数のストレージコントローラーをサポートできます。IBM Sysplex(zSeriesメインフレームのクラスター)は、複数のメインフレーム(それぞれが独自のかなりの処理能力とI / O帯域幅を持つ)と複数のSANコントローラーをサポートできます。これらのアーキテクチャは、ACIDセマンティクスを備えた非常に大きなトランザクションボリュームをサポートできますが、信頼できるストレージを想定しています。Teradata、Netezza、およびその他のベンダーは、非常に大量のデータに対応するシェアードナッシング設計に基づいた高性能分析プラットフォームを作成しています。
これまでのところ、安価だが超大容量の完全なACID RDBMSプラットフォームの市場は、シャーディングとマルチマスターレプリケーションをサポートするMySQLによって支配されています。MySQLは書き込みスループットを最適化するためにクォーラムレプリケーションを使用しないため、トランザクションのコミットはNoSQLシステムよりも高価です。シャーディングは非常に高い読み取りスループットを可能にします(たとえば、FacebookはMySQLを広範囲に使用します)。
興味深い議論
BigTableは、以下の Michael Hausenblasが指摘したように、シェアードナッシングアーキテクチャ(本質的には分散キーと値のペア)です。私の最初の評価にはMapReduceエンジンが含まれていました。これはBigTableの一部ではありませんが、通常は最も一般的な実装(Hadoop / HBaseやGoogleのMapReduceフレームワークなど)で使用されます。
このアーキテクチャとストレージと処理の間に物理的な親和性がある(つまり、ノードに共有SANではなくローカルストレージがある)Teradataと比較すると、BigTable / MapReduceはグローバルに見える並列ストレージシステムによる共有ディスクアーキテクチャであると言えます。
HadoopなどのMapReduceスタイルのシステムの処理スループットは、非ブロッキングネットワークスイッチの帯域幅によって制限されます。1 ただし、ノンブロッキングスイッチは、設計に固有の並列処理のために大きな帯域幅の集合体を処理できるため、パフォーマンスに対する重要な実用的制約となることはほとんどありません。これは、理論的にはネットワークスイッチが中心的なボトルネックであっても、共有ディスクアーキテクチャ(おそらく共有ストレージシステムと呼ばれる)が大きなワークロードに対応できることを意味します。
元のポイントは、この中心的なボトルネックは共有ディスクシステムに存在しますが、複数のストレージノード(BigTableタブレットサーバーやSANコントローラーなど)を備えたパーティションストレージサブシステムは、大きなワークロードに対応できることです。ノンブロッキングスイッチアーキテクチャは、(理論的には)ポートと同じ数の現在の接続を処理できます。
1もちろん、利用可能な処理およびI / Oスループットもパフォーマンスの制限を構成しますが、ネットワークスイッチはすべてのトラフィックが通過する中心点です。