スケーリングについて聞いたことがあると思います。アーキテクチャはスケーラブルである必要があり、需要を満たすためにスケールアップできる必要があります。データベースについて話すとき、それはどういう意味ですか?スケーリングは舞台裏でどのように見えますか?このトピックは広大であり、すべての側面をカバーする方法はありません。この2つのブログ投稿シリーズは、データベースのスケーラビリティのトピックについての洞察を提供する試みです。
なぜスケーリングするのですか?
まず、スケーラビリティとは何かを見てみましょう。つまり、データベースシステムによるより高い負荷を処理する機能について話しているのです。これは、アクティビティの短期間のスパイクに対処する問題である可能性があり、データベース環境で徐々に増加するワークロードに対処する問題である可能性があります。スケーリングを検討する理由はたくさんあります。それらのほとんどには、独自の課題があります。スケールアウトしたい状況の例を見ていくことができます。
これは最も一般的なものです。負荷が増加し、既存のリソースで処理できなくなります。何でもかまいません。 CPU負荷が増加し、データベースクラスターは妥当で安定したクエリ実行時間でデータを配信できなくなりました。データベースがCPUバウンドではなく、I / Oバウンドになるまでメモリ使用率が増加したため、データベースノードのパフォーマンスが大幅に低下しました。ネットワークもまた、首を絞めることができます。クラウドインスタンスが割り当てられているネットワーキングに関連する制限を見て驚かれるかもしれません。実際、ネットワークはクラウド内のすべてであるため、これは対処しなければならない最も一般的な制限になる可能性があります。アプリケーションとデータベース間で送信されるデータだけでなく、ストレージもネットワーク経由で接続されます。また、ディスクの使用量である可能性もあります。ディスクスペースが不足しているだけか、最近はかなり大きなディスクを使用できる可能性があるため、データベースのサイズが「管理可能な」サイズを超えている可能性があります。スキーマ変更などのメンテナンスが課題になり、データサイズが原因でパフォーマンスが低下し、バックアップの完了に時間がかかります。これらのケースはすべて、スケールアップが必要な場合に有効なケースである可能性があります。
スケーリングが必要なもう1つの例は、ワークロードの突然の増加です。何らかの理由(マーケティング活動、コンテンツのバイラル化、緊急事態、または同様の状況)により、インフラストラクチャでデータベースクラスターの負荷が大幅に増加します。 CPUの負荷が上限を超え、ディスクI / Oによってクエリの速度が低下しているなど。前のセクションで説明したほとんどすべてのリソースが過負荷になり、問題が発生し始める可能性があります。
強調したい3番目の理由は、より一般的な理由です。ある種の計画された操作です。これは、より多くのトラフィック、ブラックフライデー、負荷テスト、または事前に知っているほとんどすべてのものをもたらすことを期待する計画的なマーケティング活動である可能性があります。
これらの理由には、それぞれ独自の特徴があります。事前に計画を立てることができれば、プロセスを詳細に準備し、テストして、いつでも実行できます。ワークロードにそのようなものが存在する限り、「トラフィックが少ない」期間にそれを実行することをお勧めします(存在する必要はありません)。一方、負荷の突然の急上昇は、特に生産に影響を与えるほど重大な場合は、準備ができていても安全であっても、即座に対応する必要があります。サービスがすでに影響を受けている場合は、待つのではなく、それを求めてください。
スケーリングには、主に垂直と水平の2つのタイプがあります。どちらにも長所と短所があり、どちらもさまざまな状況で役立ちます。それらを見て、両方のシナリオのユースケースについて話し合いましょう。
このスケーリング方法はおそらく最も古い方法です。ハードウェアがワークロードを処理するのに十分な強度を備えていない場合は、強化してください。ここでは、与えられたタスクを処理するのに十分な機能を備えた既存のノードにリソースを追加することについて簡単に説明しています。これには、私たちが乗り越えたいいくつかの影響があります。
最も重要な点は、すべてが同じままであるということです。データベースクラスターに3つのノードがありましたが、まだ3つのノードがあり、さらに機能があります。環境を再設計したり、アプリケーションがデータベースにアクセスする方法を変更したりする必要はありません。構成に関しては、実際には何も変更されていないため、すべてがまったく同じままです。
垂直スケーリングのもう1つの重要な利点は、特にクラウド環境で非常に高速にできることです。プロセス全体は、ほとんどの場合、既存のノードを停止し、ハードウェアに変更を加え、ノードを再起動することです。仮想化を使用しない従来のオンプレミスセットアップの場合、これは注意が必要な場合があります。スワップに使用できるCPUの速度が速くない場合や、ディスクをより大きくまたはより高速にアップグレードする場合も時間がかかる場合がありますが、クラウド環境の場合は、パブリックまたはプライベートのどちらでもかまいません。これは、インスタンスの停止、インスタンスのより大きなサイズへのアップグレード、インスタンスの開始の3つのコマンドを実行するのと同じくらい簡単です。仮想IPと再接続可能なボリュームにより、インスタンス間でデータを簡単に移動できます。
垂直スケーリングの主な欠点は、単純に限界があることです。利用可能な最大のインスタンスサイズで実行していて、ディスクボリュームが最速の場合、他にできることはほとんどありません。また、データベースクラスターのパフォーマンスを大幅に向上させることもそれほど簡単ではありません。これは主に初期インスタンスサイズに依存しますが、すでに非常にパフォーマンスの高いノードを実行している場合は、垂直スケーリングを使用して10倍のスケールアウトを達成できない場合があります。 10倍高速になるノードは、単純に存在しない可能性があります。
水平スケーリングの主な利点は、理論的には空が限界であるということです。スケールアウトの人為的なハード制限はありませんが、制限は存在しますが、これは主に、クラスター内の通信がクラスターに追加されるすべての新しいノードでますます大きなオーバーヘッドになるためです。
もう1つの重要な利点は、ダウンタイムを必要とせずにクラスターをスケールアップできることです。ハードウェアをアップグレードする場合は、インスタンスを停止してアップグレードしてから、再起動する必要があります。クラスターにノードを追加する場合は、それらのノードをプロビジョニングし、データベースを含む必要なソフトウェアをインストールして、クラスターに参加させるだけです。オプションで(クラスターにデータを使用して新しいノードをプロビジョニングするための内部メソッドがあるかどうかによって異なります)、独自にデータを使用してプロビジョニングする必要がある場合があります。ただし、通常は自動化されたプロセスです。
対処しなければならない主な問題は、ノードを追加すると環境全体の管理が難しくなることです。どのノードが使用可能かを判断できる必要があります。そのようなリストは、新しいノードが作成されるたびに維持および更新する必要があります。ノードとその状態を追跡するために、ディレクトリサービス(ConsulまたはEtcd)などの外部ソリューションが必要になる場合があります。これは明らかに、環境全体の複雑さを増します。
もう1つの潜在的な問題は、スケールアウトプロセスに時間がかかることです。新しいノードを追加し、それらをソフトウェア、特にデータでプロビジョニングするには時間がかかります。その量は、ハードウェア(主にI / Oとネットワークスループット)とデータのサイズによって異なります。大規模なセットアップの場合、これはかなりの時間になる可能性があり、スケールアップをすぐに実行する必要がある状況ではブロッカーになる可能性があります。操作が適切に実行されていない程度にデータベースクラスターが影響を受ける場合、新しいノードを追加するための待機時間は受け入れられない可能性があります。
スケーリングを試みる前に、環境がいくつかの要件を満たしている必要があります。手始めに、アプリケーションは複数のノードを利用できる必要があります。 1つのノードのみを使用できる場合、オプションはほとんど垂直スケーリングに制限されます。このようなノードのサイズを増やすか、ベアメタルサーバーにハードウェアリソースを追加してパフォーマンスを向上させることができますが、それが最善の方法です。パフォーマンスの高いハードウェアの可用性によって常に制限され、最終的には次のようになります。さらにスケールアップするオプションはありません。
一方、アプリケーションで複数のデータベースノードを利用する手段がある場合は、水平スケーリングの恩恵を受けることができます。ここで停止して、実際に複数のノードを最大限に活用するために必要なことについて説明しましょう。
初心者向けに、読み取りと書き込みを分割する機能。従来、アプリケーションは1つのノードにのみ接続していました。そのノードは、アプリケーションによって実行されるすべての書き込みとすべての読み取りを処理するために使用されます。
スケーリングの観点から、クラスターに2番目のノードを追加しても何も変わりません。一方のノードに障害が発生した場合、もう一方のノードがトラフィックを処理する必要があるため、両方のノードの負荷の合計が1つのノードで処理するには高すぎることはありません。
3つのノードを使用すると、2つのノードを十分に活用できます。これにより、読み取りトラフィックの一部をスケールアウトできます。1つのノードの容量が100%の場合(最大で70%で実行したい場合)、2つのノードは200%を表します。 3つのノード:300%。 1つのノードがダウンしていて、残りのノードをほぼ限界までプッシュする場合、クラスターが劣化していれば、単一ノードの容量の170〜180%で作業できると言えます。これにより、3つのノードすべてが使用可能な場合、すべてのノードに60%の負荷がかかります。
現時点では、読み取りのスケーリングについてのみ説明していることに注意してください。 。どの時点でも、レプリケーションによって書き込み容量を向上させることはできません。非同期レプリケーションでは、ライター(マスター)は1つだけであり、データセットがすべてのノードで共有されるGaleraのような同期レプリケーションでは、1つのノードで発生するすべての書き込みを残りのノードで実行する必要があります。集まる。
3ノードのGaleraクラスターでは、1つの行を書き込む場合、実際には、ノードごとに1つずつ、3つの行を書き込みます。ノードやレプリカを追加しても違いはありません。 3つのノードに同じ行を書き込む代わりに、5つのノードに書き込みます。これが、データセットがすべてのノード間で共有されるマルチマスタークラスターで書き込みを分割する理由です(たとえば、MySQL NDBクラスターなどのデータがシャーディングされるマルチマスタークラスターがあります。ここでは、書き込みスケーラビリティのストーリーはまったく異なります)。あまり意味がありません。総書き込み容量に関して実際には何も変更されていませんが、すべてのノード間で発生する可能性のある書き込みの競合に対処するオーバーヘッドが追加されます。
非同期レプリケーション設定で読み取りをスケーリングする場合は、書き込みから読み取りを分割する機能が必須です。書き込みトラフィックを1つのノードに送信してから、読み取りをレプリケーショントポロジ内のすべてのノードに送信できる必要があります。前述したように、この機能は、クラスター内の複数のノードに書き込みを分散しようとした場合に発生する可能性のある書き込みの競合を取り除くことができるため、マルチマスタークラスターでも非常に役立ちます。読み取り/書き込み分割をどのように実行できますか?それを行うために使用できるいくつかの方法があります。このトピックを少し掘り下げてみましょう。
最も単純なシナリオであり、頻度も最も低くなります。アプリケーションは、どのノードが書き込みを受信し、どのノードが読み取りを受信するかを構成できます。この機能はいくつかの方法で構成できます。最も単純なのはノードのハードコードされたリストですが、バックグラウンドスレッドによって更新される動的ノードインベントリのラインに沿ったものにすることもできます。このアプローチの主な問題は、ロジック全体をアプリケーションの一部として作成する必要があることです。ノードのハードコードされたリストを使用すると、最も単純なシナリオでは、レプリケーショントポロジを変更するたびにアプリケーションコードを変更する必要があります。一方、サービスディスカバリの実装などのより高度なソリューションは、長期的に維持するのがより複雑になります。
別のオプションは、コネクタを使用して読み取り/書き込み分割を実行することです。すべてにこのオプションがあるわけではありませんが、一部にはあります。例としては、php-mysqlndまたはConnector/Jがあります。アプリケーションへの統合方法は、コネクタ自体によって異なる場合があります。アプリケーションで構成を行う必要がある場合もあれば、コネクタ用の別の構成ファイルで構成を行う必要がある場合もあります。このアプローチの利点は、アプリケーションを拡張する必要がある場合でも、新しいコードのほとんどを外部ソースで使用および保守できることです。このような設定の処理が簡単になり、必要なコードが少なくなります(存在する場合)。
最後に、最良のソリューションの1つはロードバランサーです。考え方は単純です。データをロードバランサーに渡して、読み取りと書き込みを区別し、適切な場所に送信できるようにします。これは、データベースの検出とクエリのルーティングをアプリケーションから分離できるため、ユーザビリティの観点からは大幅な改善です。アプリケーションが実行する必要があるのは、ホスト名とポートで構成される単一のエンドポイントにデータベーストラフィックを送信することだけです。残りはバックグラウンドで行われます。ロードバランサーは、クエリをバックエンドデータベースノードにルーティングするように機能しています。ロードバランサーはレプリケーショントポロジの検出を行うこともできます。または、etcdまたはconsulを使用して適切なサービスインベントリを実装し、Ansibleなどのインフラストラクチャオーケストレーションツールを使用して更新することもできます。
これで、このブログの最初の部分は終わりです。 2つ目では、データベース層をスケーリングするときに直面する課題について説明します。また、データベースクラスターをスケールアウトするいくつかの方法についても説明します。