BLOG
スケーラブルな分散システムを構築する

投稿:2018年1月18日   |    更新:2022年3月9日

予防は最高の薬です

分散システムを構築する最善の方法は、 分散を避けることです。その理由は簡単で、分散コンピューティングの欠陥を迂回することができます(一部の楽観主義者の考えとは異なり、分散コンピューティングの欠陥はまだ残っています)。

私の個人用のラップトップにはSignalFXのステッカーが はってあります。これは、さまざまなトランスポートメカニズムの速度のリストです。そもそもこのステッカーは、特にデータセンター間を移動するときに、複数のディスクやネットワークを使うのを避けるようにと言っています。それに従い、機械的な共感を抱くならば、単一ノード上で毎秒何百万件ものトランザクションを実行できる取引プラットフォームをサポートできる、LMAXのように市場を破壊するような素晴らしいものを構築することができます。メモリや単一のマシン上で処理させるようにするとさらに多くの処理ができます。おそらく15秒分の作業をやり直しても問題ない場合は、メモリ内ですべての作業を行い、1分に4回チェックポイントをディスクに書き出すだけです。そのようなシステムは非常に高速に動作し、完全にスケールアウトするという問題を回避できます。

281779bea2913da6b0388caa6ab9cfee

自分自身をだますことはできません – 分散システムは常に複雑さを増し、生産性を低下させます。もし誰かが別のことを言うのなら、その連中はおそらくいんちきなものを売っているのでしょう。

なぜそうしているのかを調べ、前提をすべて問い直してください

「高可用性」と呼ばれる要件のせいで、すべてのコードを1つのノードに置くことが不可能になります。この要件は、しばしば、複数のシステムが引き込まれるまで非常に高価なステップを引き起こします。ここでは、2つの要件、チャレンジの仮定とチャレンジの要件があります。この特定のシステムには本当にファイブナイン(訳注:99.999%)の可用性が必要ですか、それとももっと 緩い可用性を与えるレイヤーに移行できますか?特にあなたのソフトウェアがそれ自体を証明する必要や、HA(高可用性)やその他の鐘や笛を鳴らす必要があるのならば、成熟度の低い最適化を施してしまう可能性があります。そうではなく、今すぐにスキップして、市場投入を早め、後で追加する戦略を立ててください。ビジネスのステークホルダーが「はい」と言うなら、「HA」にする必要がありますが、トレードオフと、時間とお金を使う実際には使えないものに時間とお金を費やすことになるかもしてないことを相手が知っていることを確認する必要があります(顧客がその製品や機能を気に入らないようになるという結果も考えられます。顧客が好きになることを知っている製品や機能だけを作ってればリスクはなく、あなたが始めたベンチャーは退屈な雲の上に止まってしまいますが)。

CAPの定理を説明すると利害関係者に、可用性や一貫性を持たせられるということは言えますが、両立は無理です(もう一度言っておくと、楽観主義者の中にはそれは問題ないという人がいますが、間違っていると思います)。 たとえば、通知を送るシステムを構築した場合、たいていは、一貫して通知を送るシステム(一貫性がありますが可用性の低い通知)とか、ほとんど常に通知を送理続けるシステム(可用性はある一貫性が低い)を作ることはできます。 通常、最終的に一貫性のある(AP)システムは、調整が少なくてすむため、構築が楽で、拡張と操作が簡単です。可用性の要件を取り除けるかどうかを検討してみてください。 普通は、APソリューションで問題解決を図ることを検討することは価値がありますので。

忘れないで – 何かを避けられないなら、少なくとも単純にする方向で交渉してください。 複雑な分散システムを実装しないことが、分散システムを構築する最善の方法です。

人生をシンプルにする

複雑さは我々の商売の敵なので、どんなコードを書いていても、どのようなシステムを設計していても、この「複雑さが膨れ上がったらハンマーで叩き潰す」というモグラ叩きゲームをプレーする必要があります。 複数のシステムにまたがるソフトウェアを書いたらすぐにこれはさらに大事になります。分散システムは本質的に複雑なので、偶発的に複雑さが増すことには我慢しないようにしてください。分散システムの中には、他のものより実装が簡単なものがいくつかあります。単純なものに固執し続けることです。

HA用に配布する

可用性を向上させるにはいくつかの方法があります。ノードのクラスタを作り、すべてを調整できます(作業状態を常に保存しておくと、どのノードでもなんでも拾えるようになります)が、それには多くの調整が必要です。 調整はシステムを壊れやすくするので、おそらく維持できないのではないでしょうか。 コーディネーションを避けるためのさまざまな選択肢があり、依然として優れた可用性を保てます。

  • 同じ作業を複数のシステムで並行処理させ、1つのシステムの出力のみを使うこと。 すべてがセカンダリノードにレプリケートされるため、プライマリノードに障害が発生すると、レプリケーションによってバックアップノードが確実に「ホット」になり、瞬間的に引き継ぐことができます。調整が必要なのは最初にどのノードを実行し、どのノードを2次バックアップにするかを決めることだけです。
  • 予備の待機系を持つこと。 プライマリノードは定期的に共有ストレージ上で作業を継続し、作業が停止すると、セカンダリがそれを読み込んで引き継ぎます。 ここでの調整は、通常、テイクオーバーが必要かどうかを知るために、常にセカンダリがプライマリを監視するようにしておくことです。

どちらの場合も、調整の単位は「トランザクションごと」から「構成ごと」に移行します。分散した作業トランザクションの扱いは難しいので、構成レベルの調整を取り除くことができれば、そうしてください。しばしば、これにはいくつかの作業が含まれます。「正確に1つ」の作業プロセスは、マシンが死ななければ「ほとんど正確に1つ」のプロセスになり、何も見逃さなかったことを確実にするためには最後の1分まで再生してみる必要があります。場合によっては、重複したオペレーションが表示されるのを避けることはできませんし、要件に関してステークホルダーとチャットする必要があります。正直なリスクアセスメント(1年に何回くらいそのマシン群は死ぬのか)と、正直なインパクトアセスメント(どのくらい各要素が重複する作業をしたのかと、ユーザーにどのくらい不便を感じさせたのか)と正直な難易度アセスメント(ぜい弱性を生じさせ、これにより可用性が低下するような余分な作業と複雑さがどれくらい増えたか)を実施しましょう。

場合によっては、データセンターに障害が発生した場合にも可用性が必要になることがあります。そのような場合には注意が必要です。システムが脆く、早くなりすぎるので、最小限の調整で済むようにしたいと考えるようになるでしょう。

パフォーマンスのために分散させる

一つのノードだけですべての作業を完了させることはできない場合もあります。まず、そんなポジションをとらないようにしてください。目をしっかり開いて、サイクルを無駄に使っているところを探してください。LMAXの人々は、1台のマシンで1秒あたり7桁のトランザクションを実行できることを示しました。より大きなインスタンスが必要ならAmazonを使うべきでしょう。私はまともなソフトウェアとは、より速いハードウェアを手に入れれば迅速に修正できるようなマルチコア対応のものだと、今のところは思っています。より多くのコアでより速く実行できるようにコードを書けない場合は、たぶんノードを追加しても高速化は期待できないのではないでしょうか? LMAXレベルのエンジニアリングがなくても、少なくとも1秒あたり5桁のビジネスオペレーションをソフトウェアが処理できると問題を解決するためにマシンを追加する必要がある場合(これは大きな問題です)、調整が最小限になるように計画してください。

想定してよいと思います。 1ノードでは1秒間に数百個も処理できないのでスケールアウトしたい、というのなら、最初の設計をしたボードに戻ってください。おそらく、あなたのコードには対処が必要な別の問題があるのです。

問題を解決するためにマシンを追加する必要がある場合(これは大きな問題です)、調整が最小限になるように計画してください。

  • トランザクションの調整ではなく構成の調整をする。さらなる協調の必要なしに各ノードがそれ自身のチャンクをプロセスに実行させるための調整スキームをノードに使わせます。あるノードが使えなくなったときに各ノードが再配布できるようにすれば、HAを非常に簡単に追加できます。
  • どんな調整も全く必要としないように、並行できる作業を見つけること。 ステートレスなWebサーバーが良い例としてここに挙げられますが、調整されていないノードの束を投入できるのはそこだけに限りません。

ストレージは安いのだから活用しよう

コマンド/クエリ分離イベントソーシングなどのアーキテクチャパターンは、データストレージを複数の特殊なステージにデカップリングし、複製することがよくあります。これらの特殊なステージは、分散設計をサポートするためにはうまくいきます。ローカルに保存するものと分散するものを選択できるため、調整を最小限に抑えるハイブリッドソリューションになるからです。たとえば、アップデートコマンドを分散Kafkaクラスタに書き込むことはできますが、そこからの下流のすべてはローカルで操作できます(たとえば、コンシューマがアップデートコマンドを処理し、クエリに使用されるElasticSearchノードを個別に更新します)。 「実際の」データは、利用可能性が高く、メッセージストリームで調整されます。システムは、検索、分析などの特殊な処理のためにそのデータのビューを使用します。このようなシステムは、中央のデータベースシステムがすべての操作のネクサスであり、必然的にボトルネックになる古典的な構成(データベースシステムがスケーラビリティのために構築されたものであろうとなかろうと)よりも簡単に維持できます。

データを冗長に保存し、複数の独立したシステムがそれぞれ独自の最適化された形式のデータを使用するようにしてください。そうすれば調整の必要性が低くなり、最終的にはストレージコストは比較的小さな増加で済むようになります。

NIH症候群を避ける-車輪はすでに他の場所で再発明されている

Googleのスケールでシステムを運用するのでない限り、分散型であなたが実装しようと取り組んでいるシステムは、一から自分で構築する必要があるほど特別なものではないはずです。あなたが投資をしているのはビジネス上の問題を解決するためであって、ツールやインフラストラクチャを構築するためではないでしょうから、2017年の今、自分のための特別な何かを探す理由はないのです。分散システムを正しく実装するのは難しいので、失敗する可能性が高いのです(パーシステンスと暗号化についても同じアドバイスができます)。独自の問題を抱えていて自分自身で何かを発明する必要があると思っている場合は、実はちゃんとじっくり世間を見ていないか、何百ものオープンソースプロジェクトのどれかが使える形に、自分の問題を定義し直す努力をしていない可能性があります。あなたは「ビジネス」を推進しており、分散ソリューションをずっと簡単に、したがって信頼性を高める形で要件の形を変えるのを助けています。あなたが抱えている問題の、ユニークではない部分を解決するための、正しいソフトウェアを見つけましょう。そうすればあなたは自分の会社を特別なものにすることに集中できるようになります。

そう、ツールを作ること(tool-smithing)は楽しい – 私も大好きで、一日中やっていても飽きません。そして、確かに、独特の雪のかけらみたいに見えるような形であなたの問題をフレーミングすることは、自尊心のためには良いことです。でもそれは辞めて、ビジネスを成功に導くために本当の問題を解決してください。

book-markカテゴリー :ベストプラクティス