web-dev-qa-db-ja.com

シングルライターの原則を理解する

Mechanical Sympathyブログの Single-Writer Principle に関する記事では、複数のプロデューサーからメッセージを受信できるようにする必要があるため、キューがどのように(パフォーマンスの観点から)悪いのかを説明しています。 「Disruptor」のように、システムで単一のConsumer-Producerペアのみを使用する。

しかし、それを正確に実装する方法を理解できていません。

例:データオブジェクト(人やメッセージなど)を追跡するサービス(FacebookやTwitterなど)があるとします。ここで、他のデータオブジェクトに何らかの影響を与える新しいデータオブジェクトを挿入する必要があると仮定します(たとえば、新しいユーザーがサインアップし、他のユーザーが彼の友達かどうかを尋ねる必要があるか、または新しいメッセージが公開され、サブスクライバーに通知する必要があるそれ)。

新しいデータオブジェクトがあらゆる種類のクライアント(つまり、プロデューサー)のあらゆる方向から入ってくると考えると、ある種のキューなしでそれをどのように実装するのでしょうか。 oneサーバーでoneスレッドだけを使用してサインアップサービスを正確に実行することはできません。サインアップは成功しますか?

言及された記事のコメントに対する1人のユーザーが正確にそれを尋ね、そして response は、プロデューサーに結果を公開するだけであり、次に、それらの個々のプロデューサーからそれらを収集し、それらを集約する1つの追加プロセスです。その後、それらを再発行します。これにより、「1人」のプロデューサーのみが発行できるようになります。

それも単なる変装のキューではないですか?それらすべてのプロデューサーを歩くことも時間と労力を費やすことになるでしょう?そもそも、この実装が、プロデューサーを適切なキューに書き込もうとするときに同期させるよりも望ましいのはなぜですか。

6
BVN

あなたの質問には多くの要素があります。


その記事は非常に興味深いですが、普遍的な真実ではなく、目を見張るものとして扱ってください。この記事では、あまりにも多くのものが(多くの抽象化レベルで)混ざり合っているため、そこから中心的なテーマを特定することはできません。 (この批判に対する謝罪。)

その記事の冒頭は次のようになります。

  • 観察:最近のマルチコアCPUとそのキャッシュは、 キャッシュコヒーレンシプロトコル を使用しています。 。]
    • この部分は明白です。 CPUメーカーが公表している事実です。
  • 論文(記事の著者から):データ受け渡しコードを特定の方法で記述した場合、OSロックを使用した場合よりも効率が良くなるはずです。またはCAS。
    • この部分は 改ざん可能なステートメント です。独自の実験を実行して、論文がユースケースに関連しているかどうか、および実際のコンピューターでテストしたときに主張が支持されるかどうかを確認できます(紙での議論とは対照的です)。

この記事の説得は、本質的に分散化の説得、またはボトルネックの単一ポイントの除去です。

  • システムがアクター間のポイントツーポイント通信を利用する場合、各プロデューサー/コンシューマーペア専用のチャネルを使用して実装すると、CPUレベルでの競合が最小になります。

それはハードウェアの観察とどのように関連していますか?

  • メモリの読み取り/書き込み命令の並べ替えを回避するには、コンパイラ、JIT、またはVMランタイムを指定する必要があります。
  • キャッシュコヒーレンシプロトコルはすでにこのユースケースを処理しているため、ハードウェアメモリ同期プリミティブを使用する必要はまったくありません。
  • 記事の表では、ハードウェアメモリの同期プリミティブを追加しないことで、書き込みスループットが少なくとも20倍向上する可能性があると述べています。
    • 警告:CPUのすべての世代(ファミリ)は異なります。私はこれらの数字を当然とは思わないでしょう。パフォーマンスが非常に重要な場合は、独自のベンチマークを実行しているはずです。

欠点:

  • mのプロデューサーとNのコンシューマーがあり、すべてのプロデューサーがすべてのコンシューマーと対話する必要がある場合は、(M*N) 1つだけではなく、その間の任意の数とは対照的に、同じ数の専用通信チャネル。
  • また、各データは、少なくとも1つのCPUキャッシュラインを占有する必要があります。それ以外の場合、キャッシュコヒーレンシ引数はもう関係ありません。
  • 専用チャネルが固定サイズのリングバッファである場合、固定容量になるため、コンシューマが追いつかなかった場合はデータを破棄するか、プロデューサにデータを追加できないと通知された場合にプロデューサが選択する必要があります。それ。

次の質問がありました。

  • 本質的に相互排除を必要とするアルゴリズムとシステム要件についてはどうですか?

そうすれば、記事の説得は当てはまりません。

一方、相互排除にほとんどまたはまったく依存しない、多くの重要な分散アルゴリズムと分散データ構造があり、これらはFacebook、Twitter、AWSなどで使用されます。言うまでもなく、これらは平均的なプログラマーの理解をはるかに超えています。 (私はそれらについてもあまり知りません。)

そして、あなたがその質問をしたように、概念的なキューから実際のキューの実装

  • LMAX Disruptorは特定のキュー実装です(固定容量、CPUキャッシュ対応のリングバッファー、その唯一のプロデューサーは特定のハードウェア同期プリミティブを発行する必要がなく、コンシューマーは他のコンシューマーに対して同期する必要はありません)。
  • FacebookとTwitterで使用される「キュー」は概念的なものです。特に、抽象的に言えば、キュ​​ーよりもデータフローに似ています。このような場合、LMAX Disruptorを使用することはできません。代わりに、Apache Stormなどを使用した可能性があります。

結果アグリゲーターは、(多くのマシンがある場合の)分散コンピューティングにおける有効かつ重要なパターンです。これは紛れもない事実だと思います。

このコメントの質問に対する記事の回答は、そのパターンを借りて単一のマシンにも戻ることができるということです。

ただし、単一のマシンでそれを行うと、マルチプロデューサー、マルチコンシューマーCAS(障害のない)キューを使用することに加えて、何らかの利点がもたらされるかどうかは明確ではありません(疑わしい)。誰かがこの主張を実験結果で反論した可能性があります。

私の失望の1つは、作成者の応答が、まるでそれが異なるためであるかのように、「キューの代替手段」であるとして彼らのアプローチを描写していることです。


最終的に、これが私の教訓です。私は、1つの抽象化レベルから1つの観察を敢えて受け取らないでしょう。一貫性をキャッシュし、それを大きく異なるものに拡張します。分散コンピューティング。

3
rwong

私はここで間違っているかもしれませんが、これは本質的にオーバーヘッドに帰着すると思います。

リンクされた記事 で述べられているように:

非常に競合するデータの場合、システムが実際の作業を行うよりもはるかに多くの時間を競合の管理に費やす状況に陥るのは非常に簡単です。


例を挙げましょう...

プログラマーのオフィスがあり、その全員が毎年のパフォーマンス評価を受けているとします(そうです!死んだ目ボス。上司は、オフィスの業績評価の順序の名前のリストを必要としています。これを行う方法は2つあります(多くありますが、ここでは2つだけ使用します)。

  1. ボスは紙とペンを前に置きます。オフィスにいるすべてのプログラマー(ボブ、アリス、フレッド、および彼らの友人)は、一枚の紙に近づき、ペンをめぐって戦い、彼らの名前を書きます(それぞれがペンを待つ必要があり、その後、線だけを受け取ります)彼らの前にいる誰でもが終わった後の紙の上でwriting)。

    -[〜#〜]または[〜#〜]-

  2. ボブ、アリスなどすべてeach自分の名前を紙に書き、次のデスクの人に渡します。フレッド(列の最後に座っている)は、これらのピースを(orderで-彼が受け取ったもの)を上司に渡します。 (コンピューターが操作できるすべての形式のデータをコンピューターのメモリーに保存できるため、余分な紙は基本的に無料です)

両方のシナリオで、上司は全員の名前のリストを取得し、そのリストは(ほぼ)同じ順序(デスクの場所に基づく)です。ただし、最初のシナリオでは、多くの生産者と1人の消費者がいたため、かなりの時間が待機(ペンと紙が自由になるために)費やされました。 2番目のシナリオでは、各プログラマーはプロデューサーとコンシューマーです-基本的にはリングトポロジー(ただし、ボス側で壊れています)。


「それを正確に実装する方法」

さて、今質問があります!

明らかに、具体的なシナリオなしで議論することは困難です(これにより、SO質問の詳細になります)。しかし、基本的に、それぞれのwriteableのことドメイン/ソリューション/環境/システムは、一度に1つの特定の俳優によってのみ書き込み可能です((scale、そのアクターはスレッド、プロセス、マシン、クラスター、データセンターなどである場合があります。)読み取りはキャッシュ(プロセッサーのキャッシュ、Webサーバーなど)から行われます。

たとえば、Googleが(浅い)Web全体のインデックスを構築する方法は、特定のキーワードを担当するクラスターを使用した分割統治手法に基づいています。クローラーがキーワードのある新しいWebページを見つけた場合、関連するインデックスクラスターのみに通知する必要があります。

1
Tersosauros