システムデザインシリーズの初志
システム設計入門書: 和文档 GitHub - donnemartin/system-design-primer: 大規模システムを設計する方法を学びます。システム設計面接の準備をします。Anki フラッシュカードが含まれています。
中国語版: https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md
本来の目的は主にシステム設計を学ぶことですが、中国語版は機械翻訳っぽいので、今でも手作業で簡単なメモを取り、わかりにくい部分はAIを活用して英語版と比較しながら学習しています。翻訳と知識の拡大。
データベース
出典: ユーザーを最初の 1,000 万人までスケールする
データベースとは何ですか
データベース (DataBase、DB) は、コンピューターに保存され、長期にわたって組織化され、共有され、均一に管理されるデータの集合です。データ構造に従ってデータを保存および管理するコンピュータ ソフトウェア システムです。データベースの概念には、データ、データ編成、データ ストレージ、データ管理の 4 つの側面が含まれます。データベースには次の特徴があります。
- データの永続性: データベース内のデータは長期間保存でき、必要に応じてクエリや変更が可能です。
- データ共有: 複数のユーザーとアプリケーションがデータベース内のデータに同時にアクセスして、データ共有を実現できます。
- データの一貫性: データベース内のデータは一貫性を保ち、複数のユーザーが同時にデータを操作する場合、データベースはデータの一貫性を保証します。
- データのスケーラビリティ: データベースは簡単に拡張して、新しいデータや機能を追加できます。
- 高いパフォーマンス: インデックス作成やキャッシュなどのテクノロジを使用することで、データベースはデータの取得と操作の速度を向上させることができます。
データベースの種類
データベースには主に次の種類があります。
- リレーショナル データベース (RDBMS): このタイプのデータベースは、行 (レコード) と列 (フィールド) で構成されるテーブルの形式でデータを保存します。一般的なリレーショナル データベースには、MySQL、Oracle、SQL Server、PostgreSQL などが含まれます。リレーショナル データベースは、明確で理解しやすいデータ構造と、複雑なクエリとトランザクション処理のサポートを特徴としていますが、大量の非構造化データの処理には適していない可能性があります。
- 非リレーショナル データベース (NoSQL): このタイプのデータベースには、主に Key-Value タイプ (Redis、Riak など)、列ファミリー タイプ (Cassandra、HBase など)、ドキュメント タイプ (MongoDB、CouchDB など)、およびグラフ タイプ ( Neo4j、OrientDB など)待ちます。非リレーショナル データベースは、不規則な構造、半構造、または非構造化データの保存に適しており、高い水平スケーラビリティと高いパフォーマンスを備えていますが、データの一貫性が低い場合があります。
- 階層データベース: このデータベースはデータをツリー構造に編成します。データは階層構造に分割され、各ノードがレコードを表します。一般的な階層データベースには、IBM IMS、SAP HANA などが含まれます。
- ネットワーク データベース: このデータベースはデータをグラフまたはネットワーク構造に編成し、データ間の関係はノードとエッジで表されます。一般的なネットワーク データベースには、Neo4j、OrientDB などが含まれます。
- 時系列データベース: この種のデータベースは主に、株価や気象データなどの時系列データを保存するために使用されます。一般的な時系列データベースには、InfluxDB、OpenTSDB などが含まれます。
各データベースの種類には適用可能なシナリオがあり、特定のニーズに応じて適切なデータベースを選択する必要があります。
リレーショナル データベース管理システム (RDBMS)
MYSQL のようなリレーショナル データベースは、テーブルの形式で編成されたデータ項目のコレクションです。
事務
トランザクションはデータベース管理システム (DBMS) における重要な概念であり、論理的に関連する一連の操作シーケンスとして表されます。これらの操作はすべて完了するか、まったく完了しないかのいずれかであり、不可欠な作業単位です。トランザクションはデータの整合性と一貫性を確保するために使用され、データベース内で実行されると、データの追加、変更、削除などの操作を実行できます。
ACID は、リレーショナル データベーストランザクションの特性を記述するために使用されます。
- アトミック性 - 各トランザクション内のすべての操作は完了するか、または完了しません。
- 一貫性 - トランザクションはデータベースをある有効な状態から別の有効な状態に遷移させます。
- 分離 - トランザクションの同時実行の結果は、トランザクションの順次実行の結果と同じです。
- 耐久性 - トランザクションがコミットされた後、システムへの影響は永続的です。
拡大する
リレーショナル データベース拡張機能には、マスター/スレーブ レプリケーション、マスター/マスター レプリケーション、結合、シャーディング、非正規化、SQL チューニングなどの多くのテクノロジが含まれています。
出典: スケーラビリティ、可用性、安定性、パターン
マスター/スレーブ レプリケーション
データベースをマスター データベースとスレーブ データベースに分割します。マスター データベースは読み取りと書き込みの両方の操作を担当し、1 つ以上のスレーブ データベースへのコピーと書き込みを行います。スレーブ データベースは読み取り操作のみを担当します。ツリー形式のスレーブ ライブラリは、書き込みをさらに多くのスレーブ ライブラリにコピーします。マスター ライブラリがオフラインの場合、スレーブ ライブラリがマスター ライブラリに昇格されるか、新しいマスター ライブラリが表示されるまで、システムは読み取り専用モードで実行できます。
マスター/スレーブ レプリケーションの欠点:
- スレーブ ライブラリをマスターに昇格するには、追加のロジックが必要です。
- マスター/スレーブ データベースのデータ整合性の問題、データの遅延、停止データが同期していない
出典: スケーラビリティ、可用性、安定性、パターン
マスター間レプリケーション
両方のメイン ライブラリは読み取り操作と書き込み操作を担当し、書き込み操作中に相互に調整します。メイン ライブラリの 1 つがハングアップしても、システムは読み取りと書き込みを続行できます。
マスター間レプリケーションのデメリット
- どのデータベースに書き込むかを決定するには、ロード バランサーを追加するか、アプリケーション ロジックを変更する必要があります。
- ほとんどのマスター/マスター システムは、一貫性を保証できない (ACID に違反している) か、同期による書き込み遅延が発生しています。
- 書き込みノードが追加され、レイテンシが増加するにつれて、競合を解決する方法がますます重要になります。
- プライマリ サーバーとプライマリ サーバー間のデータ整合性同期の問題。
データの整合性同期の問題が存在する可能性がある状況
- 新しく書き込まれたデータを他のノードにコピーする前にメイン データベースがハングアップすると、データが失われる可能性があります。
- 書き込みは、読み取り操作を担当するレプリカに再実行されます。過剰な書き込み操作によりレプリカがブロックされ、読み取り機能が異常になる可能性があります。
- 読み取りスレーブが多いほど、より多くの書き込みデータをレプリケートする必要があり、レプリケーションの待ち時間が長くなります。
- 一部のデータベース システムでは、メイン データベースへの書き込みは複数のスレッドを使用して並行して書き込むことができますが、リード レプリカは単一スレッドによるシーケンシャル書き込みのみをサポートします。
- レプリケーションは、より多くのハードウェアとさらなる複雑さを意味します。
ジョイント
出典: ユーザーを最初の 1,000 万人までスケールする
フェデレーション (または機能ごとの分割) により、データベースが対応する機能に分割されます。たとえば、1 つのモノリシック データベースではなく、フォーラム、ユーザー、製品の 3 つのデータベースを使用できます。これにより、各データベースの読み取りおよび書き込みトラフィックが削減され、レプリケーションの待機時間が短縮されます。データベースが小さいほど、メモリに収まるデータが多くなり、キャッシュ ヒットの可能性が高くなります。シリアル書き込みのみが可能な集中メイン ライブラリはありませんが、並列書き込みを行うことで負荷容量を増やすことができます。
組合のデメリット
- データベース スキーマに多数の関数とデータ テーブルが必要な場合、ユニオンの効率は良くありません。
- どのデータベースから読み取り、どのデータベースに書き込むかを決定するには、アプリケーションのロジックを更新する必要があります。
- サーバー リンクを使用して 2 つのライブラリのデータを接続する場合は、さらに複雑になります。
- フェデレーションには、より多くのハードウェアとさらなる複雑さが必要です。
断片化
出典: スケーラビリティ、可用性、安定性、パターン
シャーディングでは、異なるデータベースにデータが分散されるため、各データベースはデータ セット全体のサブセットのみを管理します。ユーザー データベースを例にとると、ユーザーの数が増加するにつれて、より多くのシャードがクラスターに追加されます。
フェデレーションの利点と同様に、シャーディングにより読み取りおよび書き込みトラフィックが削減され、レプリケーションが削減され、キャッシュ ヒット率が向上します。また、インデックスの数も減ります。これは通常、クエリが高速になり、パフォーマンスが向上することを意味します。1 つのシャードに障害が発生しても、データ損失を防ぐために何らかの形式の冗長性を使用して、他のシャードは引き続き実行できます。フェデレーションと同様に、シリアルにのみ書き込むことができる集中化されたメイン ライブラリはありませんが、負荷容量を向上させるために並列に書き込むことができます。
一般的には、ユーザー テーブルをユーザーの姓の最初の文字またはユーザーの地理的位置で区切ります。
シャーディングのデメリット
- シャーディングを実装するにはアプリケーション ロジックを変更する必要があるため、複雑な SQL クエリが発生します。
- 不合理なシャーディングは、データ負荷の不均衡を引き起こす可能性があります。たとえば、ユーザー データに頻繁にアクセスすると、そのシャードの負荷が他のシャードよりも高くなります。
- リバランスするとさらに複雑になります。一貫したハッシュに基づくシャーディング アルゴリズムにより、この状況を軽減できます。
- 複数のシャードを結合するデータ操作はより複雑になります。
- シャーディングにはより多くのハードウェアとさらなる複雑さが必要です。
非正規化
非正規化では、書き込みパフォーマンスを犠牲にして読み取りパフォーマンスを犠牲にしようとします。コストのかかる結合操作を回避するための、複数のテーブルにわたるデータの冗長コピー。PostgreSQL や Oracleなどの一部のリレーショナル データベースは 、冗長な情報ストレージを処理し、冗長コピーの一貫性を確保できるマテリアライズド ビューをサポートしています。
結合やシャーディングなどの技術を使用してデータが断片化されると、データセンター間での結合操作の処理がさらに複雑になります。非正規化により、この複雑な結合操作を回避できます。
ほとんどのシステムでは、読み取り操作の頻度は書き込み操作の頻度よりもはるかに高く、その比率は 100:1、さらには 1000:1 に達する場合もあります。複雑なデータベース結合を必要とする読み取り操作は非常にコストがかかり、ディスク操作に多くの時間がかかります。
非正規化の欠点:
- データは冗長になります。
- 制約は、情報の冗長コピーの同期を維持するのに役立ちますが、データベース設計が複雑になる可能性があります。
- 非正規化データベースは、書き込み負荷が高い場合、正規化データベースよりもパフォーマンスが低下する可能性があります。
SQLチューニング
SQL チューニングは幅広いトピックであり、参考として使用できる関連書籍が多数あります。
ベンチマークとパフォーマンス分析を活用して、システムのボトルネックをシミュレートし、発見することが重要です。
- ベンチマーク テスト - ab などのツールを使用して高負荷状況をシミュレートします。
- パフォーマンス分析 -スロー クエリ ログなどのツールを有効にすることで、パフォーマンスの問題の追跡に役立ちます。
ベンチマークとパフォーマンス分析により、次の最適化オプションが見つかる可能性があります。
スキーマの改善
- 高速アクセスのために、MySQL はディスク上の連続したブロックにデータを保存します。
CHAR
固定長フィールドを格納するには型を 使用します 。型は使用しないでくださいVARCHAR
。CHAR
高速でランダムなアクセスに非常に効率的です。を使用した場合VARCHAR
、次の文字列を読み取りたい場合は、まず現在の文字列の最後まで読み取る必要があります。
- タイプを使用して
TEXT
、ブログ投稿などの大きなテキストの塊を保存します。TEXT
ブール検索も許可されます。TEXT
フィールドを使用するには、 テキストのブロックを見つけるポインターをディスク上に保存する必要があります。 - 型を使用して
INT
、最大 2^32 または 40 億までのより大きな数値を格納します。 DECIMAL
型を使用して 通貨を保存すると、浮動小数点表現のエラーが回避されます。BLOBS
実際のオブジェクトを保存するためにこれを使用することは避け 、代わりにオブジェクトが保存されている場所を保存するために使用します。VARCHAR(255)
8 桁の数値として保存される文字の最大数です。一部のリレーショナル データベースでは、バイトの使用率が最大になります。- 該当するシナリオに
NOT NULL
制約を設定して、検索パフォーマンスを向上させます。
正しいインデックスを使用する
- クエリを実行している列 (
SELECT
、GROUP BY
、ORDER BY
、JOIN
) は、インデックスを使用すると高速になります。 - インデックスは通常、データの順序を維持し、対数時間での検索、順次アクセス、挿入、および削除操作を可能にする自己均衡 B ツリーとして表されます。
- インデックスを設定するとデータがメモリに保存されるため、より多くのメモリ領域が必要になります。
- インデックスを更新する必要があるため、書き込み操作は遅くなります。
- 大量のデータをロードする場合は、インデックスを無効にし、データをロードしてからインデックスを再構築する方が高速な場合があります。
コストのかかる結合操作を回避する
- パフォーマンスが必要な場合は、非正規化を実行できます。
分割データテーブル
- ホットスポット データを個別のデータ テーブルに分割すると、キャッシュが容易になります。
クエリキャッシュのチューニング
- 場合によっては、クエリのキャッシュがパフォーマンスの問題を引き起こす可能性があります。
NoSQL
NoSQL は、キー/値データベース、ドキュメント データベース、列データベース、またはグラフ データベースの総称です。データベースは非正規化されており、テーブルの結合はほとんどがアプリケーション コードで行われます。ほとんどの NoSQL は、真に ACID 準拠のトランザクションを実装できず、結果整合性をサポートできません。
BASE は、NoSQL データベースの特性を説明するためによく使用されます。CAP 理論と比較して 、BASE は一貫性よりも可用性を重視します。
- 基本的に利用可能 - システムには可用性が保証されています。
- ソフト状態 - システムの状態は、入力がなくても時間の経過とともに変化する可能性があります。
- 最終的な整合性 - 一定期間が経過すると、システムは入力を受け取らなかったため、システムは最終的に整合性を保ちます。
BASE 機能の例を示します。
- 基本可用性: 基本可用性とは、ネットワークの分断やノード障害などの異常な状況に直面した場合でも、システムが引き続きサービスを提供できることを意味します。たとえば、この電子商取引システムでは、ノードまたはネットワークに障害が発生した場合、システムはユーザー要求を他の正常なノードに転送して、システムが引き続き正常に動作できるようにします。
- ソフト状態: ソフト状態とは、部分的な障害が発生した場合にシステムがデータの不整合を許容できることを意味します。NOSQL データベースでは、通常、強整合性は保証されません。ショッピング カート情報を例にとると、ショッピング カート情報を更新するときにシステムがネットワークの分割やその他の障害に遭遇すると、一部のノードのショッピング カート情報が他のノードの情報と不一致になる可能性があります。ただし、この不一致はシステム内のメカニズムによって一定期間内に修復できます。たとえば、非同期レプリケーション、データ補償、その他の手段を通じて、さまざまなノード上のショッピング カート情報は、最終的には一貫した状態に到達することができます。
- 結果的な整合性: 結果的な整合性とは、システムが障害から回復した後にデータの整合性を確保できることを意味します。NOSQL データベースでは、通常、結果整合性を確保するために、オプティミスティック ロックやバージョン番号などのメカニズムが使用されます。ショッピング カート情報を例にとると、システムはショッピング カート情報が異なるノード上で矛盾していることを検出すると、楽観的ロック メカニズムを通じて競合検出を実行し、最終結果として優先度の高いバージョンを選択できます。同時に、システムはバージョン番号を通じてデータの変更を追跡することもでき、データに不整合が見つかった場合は、ロールバック メカニズムを通じてデータを一貫性のある状態に復元できます。
SQL と NoSQL のどちらを選択するかに加えて 、どのタイプの NoSQL データベースが自分のユースケースに最適かを理解することも役立ちます。次のセクションでは、 キー/値ストア、ドキュメント ストア、列ストア、およびグラフ ストアデータベースについて簡単に説明します。
キーと値のストレージ
抽象モデル: ハッシュ テーブル
キー/値ストアは通常、メモリまたは SSD を使用してデータを保存し、O(1) 時間の読み取りと書き込みを実現します。データ ストアはキーを辞書編集順に維持できるため、キーを効率的に取得できます。Key-Value ストアを使用してメタデータを保存できます。
Key-Value ストアはパフォーマンスが高く、単純なデータ モデルやメモリ内キャッシュなどの頻繁に変更されるデータの保存によく使用されます。Key-Value ストアは限定された操作を提供し、さらに多くの操作が必要な場合、その複雑さはアプリケーション レベルに渡されます。
キー/値ストアは、ドキュメント ストアや、場合によってはグラフ ストアなど、より複雑なストレージ システムの基礎となります。
ドキュメント型ストレージ
抽象モデル: ドキュメントを値としてキーと値で保存する
ドキュメント タイプのストレージは、指定されたオブジェクトに関するすべての情報を保存するドキュメント (XML、JSON、バイナリ ファイルなど) を中心としています。ドキュメント ストレージは、ドキュメント自体の内部構造に基づいてクエリを実装するための API またはクエリ ステートメントを提供します。多くのキーバリュー ストア データベースにはメタデータを値で保存する特性があり、これにより 2 つのストレージ タイプ間の境界線が曖昧になることに注意してください。
基礎となる実装に基づいて、コレクション、タグ、メタデータ、またはフォルダーに従ってドキュメントを整理できます。異なるドキュメントをまとめたり、グループ化したりすることはできますが、それぞれのフィールドがまったく異なる場合があります。
MongoDB や CouchDB などの一部のドキュメント タイプ ストレージでは、複雑なクエリを実装するための SQL のようなクエリ ステートメントも提供されています。DynamoDB は、キー値ストレージとドキュメント タイプ ストレージの両方をサポートします。
ドキュメント タイプのストレージは柔軟性が高く、時々変更されるデータを処理するためによく使用されます。
カラムストレージ
抽象モデル: ネストされた
ColumnFamily<RowKey, Columns<ColKey, Value, Timestamp>>
マッピング
storage 型の基本データ単位は列 (名前と値のペア) です。列は列ファミリーにグループ化できます (SQL テーブルと同様)。スーパー列ファミリーは、通常の列ファミリーにグループ化されます。行キーを使用して各列に独立してアクセスでき、同じ行キー値を持つ列が行を形成します。各値には、バージョンの競合を解決するために使用されるバージョンのタイムスタンプが含まれています。
Google は、初のカラム型ストレージ データベースで あるBigtableをリリースしました。これは、Hadoop エコシステムにおけるアクティブなオープンソース データベース HBase や Facebook の Cassandraに影響を与えました。BigTable、HBase、Cassandra などのストレージ システムはキーをアルファベット順に保存し、キー列を効率的に読み取ることができます。
カラムストレージは可用性が高く、スケーラブルです。通常、ビッグデータ関連のストレージに使用されます。
グラフデータベース
抽象モデル: 図
グラフ データベースでは、ノードはレコードに対応し、アークは 2 つのノード間の関係に対応します。グラフ データベースは、多数の外部キーまたは多対多の関係を含む複雑な関係を表現するために最適化されています。
グラフ データベースは、ソーシャル ネットワークなどの複雑な関係を格納するデータ モデルに高いパフォーマンスを提供します。これらは比較的新しく、まだ広く使用されておらず、開発ツールやリソースを見つけるのは比較的困難です。多くのグラフには、 REST APIを介してのみアクセスできます 。
SQL または NOSQL を選択します
SQLを選択する 理由 :
- 構造化データ
- 厳密モード
- リレーショナルデータ
- 複雑な結合操作が必要
- 事務
- クリアエクステンションモデル
- 開発者、コミュニティ、コード ライブラリ、ツールなど、既存のリソースがさらに充実しています。
- インデックス経由のクエリは非常に高速です
NoSQLを選択する 理由 :
- 半構造化データ
- ダイナミックモードまたはフレキシブルモード
- 非リレーショナルデータ
- 複雑な結合操作は必要ありません
- テラバイト(またはペタバイト)のデータを保存
- 非常にデータ集約的なワークロード
- IOPSの高スループット
NoSQL に適したデータの例:
- 埋設データとログデータ
- ランキングまたはスコアリングデータ
- ショッピングカートなどの一時データ
- 頻繁にアクセスされる (「ホット」) テーブル
- メタデータ/ルックアップテーブル
追加の参考資料:
- データ構造と関係の複雑さ: データに多対多、1 対多、1 対多、多対多の関係などの複雑な構造と関係がある場合は、SQL データベースの方が適している可能性があります。 SQL データベースは複雑な関係やデータ パターンに強力な能力を発揮します。NOSQL データベースは通常、データ構造が比較的単純で、関係がそれほど複雑ではないシナリオに適しています。
- データの読み取りおよび書き込みのパフォーマンス要件: SQL データベースは通常、データの読み取りおよび書き込み時に特定のトランザクション処理とデータ整合性ルールに従う必要があるため、パフォーマンスのオーバーヘッドが発生する可能性があります。システムのデータ読み取りおよび書き込みパフォーマンスに対する要件が高い場合は、通常、読み取りおよび書き込みパフォーマンスが高い NOSQL データベースの使用を検討できます。ただし、NOSQL データベースは SQL データベースほどデータの一貫性が強くない可能性があることに注意してください。
- データ スケール: データ スケールが大きい場合、NOSQL データベースは通常、水平方向の拡張性が優れており、大量のデータのストレージとクエリを処理できます。SQL データベースでは、大規模なデータを処理するときに、より多くのハードウェア リソースと最適化戦略が必要になる場合があります。したがって、データ規模が大きいシナリオでは、NOSQL データベースの使用を検討できます。
- データの一貫性とトランザクション処理: システムにデータの一貫性とトランザクション処理に対する高い要件がある場合は、SQL データベースの方が適している可能性があります。SQL データベースは ACID (原子性、一貫性、分離、耐久性) 原則に従っているため、データの整合性とトランザクションの完全な実行を保証できます。NOSQL データベースは通常、BASE (基本可用性、ソフト状態、結果整合性) 原則に従っており、データ整合性に対する要件は比較的低いです。
- システムの柔軟性とスケーラビリティ: NOSQL データベースは一般に、より柔軟でスケーラブルであり、変化するビジネス ニーズにうまく適応できます。通常、SQL データベースには事前定義されたデータ構造と関係が必要ですが、要件の変更に対応するのがより困難になる場合があります。