sql >> データベース >  >> RDS >> Mysql

データベースのスケーリングパターンを理解するためのガイド

    データベースのスケーラビリティパターンを説明するオンラインの記事はたくさんありますが、それらはほとんどが散在する記事であり、多くのコンテキストなしで無計画に定義された手法にすぎません。それらは段階的に定義されていないことがわかり、どのスケーリングオプションをいつ選択するか、どのスケーリングオプションが実際に実行可能であるか、およびその理由については説明していません。

    したがって、今後の記事でいくつかのテクニックについて詳しく説明する予定です。まず、独自の方法でいくつかのコンテキストを使用して段階的な手法について話し合う方がよいと思います。この記事は高レベルの記事です。ここではスケーリング手法の詳細については説明しませんが、概要を説明します。それでは始めましょう。

    ケーススタディ

    安いコストでライド​​シェアリングを提供するスタートアップを構築したと仮定します。最初は都市をターゲットにしていて、最初の広告の後で数十人の顧客がいることはほとんどありません。

    すべての顧客、旅行、場所、予約データ、および顧客の旅行履歴を同じデータベースに保存するか、ほとんどの場合、単一の物理マシンに保存します。アプリは非常に新しいため、問題を解決するための派手なキャッシュやビッグデータパイプラインはありません。たとえば、顧客が非常に少なく、システムが5分間に1回の旅行を予約することはほとんどないため、これは現時点でのユースケースに最適です。

    しかし、時間が経つにつれて、あなたは市場で最も安いサービスであり、あなたのプロモーションと広告のおかげで、より多くの人々があなたのシステムにサインアップし始めます。たとえば、1分あたり10件の予約を開始すると、その数は徐々に20、1分あたり30件の予約に増加します。

    この時点で、システムのパフォーマンスが低下し始めていることに気付きます。APIレイテンシが大幅に増加し、一部のトランザクションがデッドロックまたは飢餓状態になり、最終的に失敗します。アプリの応答に時間がかかり、顧客の不満を引き起こしています。問題を解決するために何ができますか?

    パターン1-クエリの最適化と接続プールの実装:

    頭に浮かぶ最初の解決策は、キャッシュが予約履歴、支払い履歴、ユーザープロファイルなどの非動的データを頻繁に使用することです。ただし、このアプリケーションレイヤーのキャッシュ後は、APIが公開するレイテンシの問題を解決できません。たとえば、特定の顧客の現在の運転手の位置や最寄りのタクシー、または旅行開始後の特定の時点での現在の旅行費用などの動的データが公開されます。

    データベースがおそらく大幅に正規化されていることを確認したため、冗長な列をいくつか導入します(これらの列はWHEREに頻繁に表示されます またはJOIN ON 非正規化のために頻繁に使用されるテーブルのクエリの句)。これにより、結合クエリが削減され、大きなクエリが複数の小さなクエリに分割され、その結果がアプリケーション層に追加されます。

    実行できるもう1つの並列最適化は、データベース接続を微調整することです。データベースクライアントライブラリと外部ライブラリは、ほとんどすべてのプログラミング言語で利用できます。接続プールライブラリを使用してデータベース接続をキャッシュしたり、データベース管理システム自体で接続プールのサイズを構成したりできます。

    ネットワーク接続の作成には、クライアントとサーバー間の通信が必要になるため、コストがかかります。接続をプールすると、接続数を最適化するのに役立つ場合があります。接続プールライブラリは、接続を多重化するのに役立つ場合があります—複数のアプリケーションスレッドが同じデータベース接続を使用できます。接続プールについては、後で別の記事で詳しく説明できるかどうかを確認します。

    APIのレイテンシーを測定し、おそらく20〜50%以上のレイテンシーの削減を見つけます。これは、現時点では適切な最適化です。

    これで、ビジネスをもう1つの都市に拡大し、より多くの顧客を登録し、1分あたり80〜100件の予約をゆっくりと開始します。お使いのシステムはこのスケールを処理できません。ここでも、APIレイテンシが増加し、データベースレイヤーが放棄されていることがわかりますが、今回は、クエリの最適化によってパフォーマンスが大幅に向上することはありません。システムメトリックを確認すると、ディスクスペースがほぼいっぱいで、CPUが80%の時間ビジーで、RAMがすぐにいっぱいになっていることがわかります。

    パターン2-垂直方向のスケーリングまたはスケールアップ:

    すべてのシステムメトリックを調べた後、システムのハードウェアをアップグレードする以外に簡単な解決策はないことがわかります。 RAMサイズを2倍にアップグレードし、ディスク容量をたとえば3倍以上アップグレードします。これは、垂直スケーリングまたはシステムのスケールアップと呼ばれます。インフラストラクチャチーム、DevOpsチーム、またはサードパーティのデータセンターエージェントに、マシンをアップグレードするように通知します。

    しかし、垂直スケーリング用にマシンをどのように設定しますか?

    より大きなマシンを割り当てます。 1つのアプローチは、古いマシンから手動でデータを移行するのではなく、新しいマシンをreplicaとして設定することです。 既存のマシンに(primary )-一時的なprimary replicaを作成します 構成。複製が自然に行われるようにします。レプリケーションが完了したら、新しいマシンをプライマリに昇格させ、古いマシンをオフラインにします。より大きなマシンがすべての要求を処理することが期待されるため、すべての読み取り/書き込みはこのマシンで行われます。

    涼しい。システムが再び稼働し、パフォーマンスが向上します。

    あなたのビジネスは非常に順調に進んでおり、さらに3つの都市に拡大することにしました。現在、合計5つの都市で事業を展開しています。トラフィックは以前の3倍であり、1分あたり約300件の予約が予想されます。この目標予約を達成する前に、パフォーマンスが再び低下し、データベースインデックスのサイズがメモリ内で大幅に増加し、定期的なメンテナンスが必要になり、インデックスを使用したテーブルスキャンがこれまでになく遅くなっています。マシンをさらにスケールアップするコストを計算しますが、コストに納得していません。今何をしていますか?

    パターン3-コマンドクエリ責任分離(CQRS):

    大きなマシンがすべてのread/writeを処理できるわけではないことを確認します リクエスト。また、ほとんどの場合、どの企業でもwriteのトランザクション機能が必要です。 ただし、readにはありません オペレーション。また、少し一貫性がないか、readが遅れても問題ありません。 運用とあなたのビジネスにも問題はありません。 readを分離するのが良いオプションかもしれない機会があります &write 物理的な機械の賢明な操作。個々のマシンがより多くのread/writeを処理するためのスコープを作成します オペレーション。

    ここで、さらに2台の大きなマシンを使用して、それらをreplicaとして設定します。 現在のマシンに。データベースレプリケーションは、primaryからのデータの配布を処理します マシンからreplica マシン。すべての読み取りクエリをナビゲートします(クエリ(QCQRSで )レプリカへ—任意のreplica 任意の読み取り要求を処理でき、すべての書き込みクエリをナビゲートします(コマンド(CCQRSで )primary 。レプリケーションには少し遅れがあるかもしれませんが、ビジネスのユースケースによるとそれで問題ありません。

    毎日数十万のリクエストを処理する中規模のスタートアップのほとんどは、古いデータを定期的にアーカイブすることを条件に、プライマリレプリカの設定で生き残ることができます。

    次に、さらに2つの都市にスケーリングすると、primary すべてのwriteを処理することはできません リクエスト。多くのwrite リクエストにはレイテンシがあります。さらに、primary間のラグ &replica 顧客とドライバーに影響を与えることがあります。例—旅行が終了すると、顧客はドライバーに正常に支払いますが、顧客のアクティビティはwriteであるため、ドライバーは支払いを確認できません。 primaryに送信されるリクエスト 、ドライバーのアクティビティはread レプリカの1つに送信される要求。システム全体が非常に遅いため、ドライバーは少なくとも30分は支払いを確認できません。これは、ドライバーと顧客の両方にとって苛立たしいことです。どのように解決しますか?

    パターン4-マルチプライマリレプリケーション

    primary-replicaで非常にうまくスケーリングしました 構成ですが、書き込みパフォーマンスを向上させる必要があります。 readで少し妥協する準備ができているかもしれません パフォーマンスを要求します。書き込みリクエストをreplicaに配布してみませんか また?

    multi-primary 構成では、すべてのマシンが両方のprimaryとして機能できます &replicamulti-primaryについて考えることができます マシンのサークルが言うようにA->B->C->D->AB Aからデータを複製できます 、C Bからデータを複製できます 、D Cからデータを複製できます 、A Dからデータを複製できます 。任意のノードにデータを書き込むことができ、データを読み取るときに、応答が返されるすべてのノードにクエリをブロードキャストできます。すべてのノードは同じデータベーススキーマ、同じテーブルセット、インデックスなどを持ちます。したがって、idに衝突がないことを確認する必要があります。 同じテーブル内のノード間で、そうでない場合、ブロードキャスト中に、複数のノードが同じidに対して異なるデータを返します。 。

    通常、UUIDを使用することをお勧めします またはGUID idの場合。この手法のもう1つの欠点は、read クエリのブロードキャストと正しい結果の取得が含まれるため、クエリは非効率的である可能性があります。基本的にはスキャッターギャザーアプローチです。

    今、あなたはさらに5つの都市に拡大し、あなたのシステムは再び苦しんでいます。 1秒あたり約50のリクエストを処理することが期待されます。大量の同時リクエストを処理する必要があります。どうやってそれを達成しますか?

    パターン5-パーティショニング:

    あなたはあなたのlocationを知っています データベースはwriteが高くなっているものです &read トラフィック。おそらくwrite:read 比率は7:3 。これは、既存のデータベースに大きなプレッシャーをかけています。 location テーブルには、longitudeなどの主要なデータがほとんど含まれていません 、latitudetimestampdriver idtrip id など。ユーザーの旅行、ユーザーデータ、支払いデータなどとはあまり関係ありません。locationを分離するのはどうでしょうか。 別のデータベーススキーマのテーブル?そのデータベースを適切なprimary-replicaを使用して別のマシンに配置するのはどうでしょうか。 またはmulti-primary 構成?

    これは、機能によるデータのパーティション化と呼ばれます。さまざまなデータベースで、さまざまな機能によって分類されたデータをホストできます。必要に応じて、結果をバックエンドレイヤーに集約できます。この手法を使用すると、高いread/writeを必要とする機能を適切にスケーリングすることに集中できます。 リクエスト。バックエンドまたはアプリケーション層は、必要に応じて結果を結合する責任を負う必要がありますが、コードがさらに変更される可能性があります。

    今、あなたがあなたの国の合計20の都市にあなたのビジネスを拡大し、まもなくオーストラリアに拡大することを計画していると想像してください。アプリに対する需要の高まりには、より迅速な対応が必要です。上記の方法のどれも今あなたを極端に助けることができません。他の国/地域に拡張するために、エンジニアリングやアーキテクチャを頻繁に変更する必要がないように、システムを拡張する必要があります。どうしますか?

    パターン6-水平スケーリング:

    あなたは多くのグーグルを行い、他の企業がこの問題をどのように解決したかについて多くを読み、水平方向にスケーリングする必要があるという結論に達します。たとえば50台のマシンを割り当てます。すべて同じデータベーススキーマがあり、同じデータベーススキーマに同じテーブルのセットが含まれています。すべてのマシンはデータの一部を保持しているだけです。

    すべてのデータベースには同じテーブルのセットが含まれているため、データの局所性が存在するようにシステムを設計できます。関連するすべてのデータは同じマシンに格納されます。各マシンは独自のレプリカを持つことができ、レプリカは障害回復に使用できます。各データベースはshardと呼ばれます 。物理マシンは、1つまたは複数のshardsを持つことができます —あなたが望む方法はあなたのデザイン次第です。 sharding keyを決定する必要があります 単一のsharding keyが 常に同じマシンを指します。したがって、多くのマシンがすべて同じテーブルのセットに関連データを保持していることを想像できます。read/write 同じデータベースマシン内の同じ行または同じリソースセットのリクエスト。

    シャーディングは一般的に難しいです—少なくともさまざまな会社のエンジニアがそう言っています。しかし、数百万または数十億のリクエストに対応する場合は、そのような難しい決断を下さなければなりません。

    shardingについて説明します 次の投稿で詳しく説明しますので、この投稿でもっと話し合いたいという誘惑を抑えてください。

    シャーディングが設定されているので、多くの国に拡張できると確信しています。あなたのビジネスは非常に成長しているので、投資家はあなたに大陸を越えてビジネスを拡大するように促しています。ここでも問題が発生します。再びAPIレイテンシ。あなたのサービスはアメリカでホストされており、ベトナムの人々は本に乗るのに苦労しています。なんで?あなたはそれについてどうしますか?

    パターン7-データセンターワイズパーティション:

    あなたのビジネスはアメリカ、南アジア、そしてヨーロッパのいくつかの国で成長しています。あなたは毎日何百万もの予約をしていて、何十億ものリクエストがあなたのサーバーにぶつかっています。おめでとうございます-これはあなたのビジネスにとってピークの瞬間です。

    ただし、アプリからのリクエストは、インターネット上の数百または数千のサーバーを経由して大陸を移動する必要があるため、遅延が発生します。データセンター間でトラフィックを分散するのはどうですか?南アジアからのすべてのリクエストを処理するシンガポールのデータセンター、ヨーロッパ諸国からのすべてのリクエストを処理できるドイツのデータセンター、米国のすべてのリクエストを処理できるカリフォルニアのデータセンターをセットアップできます。

    また、ディザスタリカバリに役立つクロスデータセンターレプリケーションを有効にします。したがって、カリフォルニアのデータセンターがシンガポールのデータセンターに複製を行う場合、電力の問題や自然災害によりカリフォルニアのデータセンターがクラッシュした場合、米国のすべてのリクエストはシンガポールのデータセンターなどにフォールバックできます。

    このスケーリング手法は、国を超えてサービスを提供する何百万もの顧客がいて、データの損失に対応できない場合に役立ちます。システムの可用性を常に維持する必要があります。

    これらは、データベーススケーリングの一般的なステップバイステップの手法です。ほとんどのエンジニアはこれらの手法を実装する十分な機会を得ることができませんが、全体として、将来的にはより良いシステムとアーキテクチャの設計を行うのに役立つ可能性がある、そのようなシステムについてより広いアイデアを得る方がよいでしょう。

    次の記事では、いくつかの概念について詳しく説明します。この投稿について、適切なフィードバックがあればお気軽にお知らせください。

    この記事は、もともと著者のメディアアカウントで公開されています:https://medium.com/@kousiknath/understanding-database-scaling-patterns-ac24e5223522



    1. Android用SQLCipherを使い始める方法は?

    2. WordPressはIN()条件でステートメントを準備しました

    3. Oracle Javaの更新に早期にアクセスして、RIAをテストし、これらの更新が公開されたときにファイアドリルを回避するにはどうすればよいですか?

    4. Ubuntu20.10にInfluxDBをインストールする方法