システムデザインシリーズ:ゼロから高性能データストリーミングシステムを構築するための究極のガイド!

ビューティー&ファッションのエキスパートが教える究極の美容&ファッションガイド!

出典:Unsplash

サンプル問題の設定:レコメンデーションシステム

「データストリーミング」という言葉は非常に複雑で、「データストリーミングパイプライン」となるとなおさらです。その意味や難しい用語について話す前に、ソフトウェアシステムの存在理由である問題から始めましょう。

私たちの問題は非常に単純です。電子商取引のウェブサイト(Amazonのようなもの)のためのレコメンデーションシステムを構築する必要があります。つまり、特定のユーザーの好みに基づいて、そのユーザーに適した一連の製品を返すサービスです。まだそれがどのように機能するかについては詳しく説明しません(後で詳しく説明します)、今のところはこのサービスにデータがどのように送信され、そして返されるかに焦点を当てます。

データは「イベント」という形式でサービスに送信されます。これらのイベントのそれぞれは、ユーザーが行った特定のアクションを示します。たとえば、特定の製品のクリックや検索クエリなどです。簡単に言えば、ウェブサイト上のユーザーのすべてのインタラクション、シンプルなスクロールから高価な購入までが「イベント」として考えられます。

著者の画像

これらのイベントは、ユーザーについての情報を提供します。たとえば、ゲーム用のパソコンを購入したいユーザーは、ゲーム用のキーボードやマウスにも興味を持っているかもしれません。

定期的に、私たちのサービスはユーザーのレコメンデーションのフェッチ要求を受け取ります。その仕事は簡単で、ユーザーが興味を持つ製品のリストを返すことです。

著者の画像

今の時点では、このレコメンデーションリストがどのように作成されるかは気にしません。この「レコメンデーションサービス」が何らかの魔法の手順(これに関する詳細な説明は後で行いますが、今のところはこれらの手順のロジックについてはあまり気にしません)を実行し、ユーザーの好みを特定します。

レコメンデーションは通常、多くのシステムでは後回しにされがちですが、実際にはそれほど重要です。お使いのアプリケーションのほとんどは、このようなレコメンデーションサービスに大いに依存してユーザーアクションを推進しています。たとえば、この論文によれば、Amazonのウェブセールスの35%が推奨されたアイテムによって生成されました。

しかしながら、課題はデータの規模にあります。たとえそれが中程度の人気のあるウェブサイトであっても、ピーク時には1秒間に何十万から何百万ものイベントを受け取ることがあります!そして、新商品や大規模なセールがある場合、さらに多くなる可能性があります。

そして、問題はそこで終わりません。このデータ(前述の魔法の手順を実行する)をリアルタイムで処理し、ユーザーにリアルタイムでレコメンデーションを提供する必要があります!セールがある場合、レコメンデーションの更新に数分の遅れが生じるだけで、事業に大きな損失をもたらす可能性があります。

データストリーミングパイプラインとは何ですか?

データストリーミングパイプラインは、先述のようなものです。連続データ(イベントなど)を受け取り、複数の処理ステップを実行し、結果を将来の利用のためにストアに保存するシステムです。

私たちの場合、イベントは複数のサービスから提供され、処理ステップにはユーザーに関するレコメンデーションを計算するいくつかの「魔法の手順」が含まれます。そして、各ユーザーのレコメンデーションをデータストアに更新します。特定のユーザーのレコメンデーションのクエリを受け取った場合は、以前に保存したレコメンデーションを単純に取得して返します。

この記事の目的は、このようなデータの規模をどのように処理し、それを取り込み、処理し、後で使用するために出力するかを理解することです。実際の処理の手順のロジックを理解することよりも、このスケールのデータの取り扱い方に焦点を当てることです(ただし、楽しみのためにそれに少しだけ掘り下げます)。

データストリーミングパイプラインの作成:ステップバイステップ

話すことはたくさんありますが、取り込み、処理、出力、クエリについては、一つずつアプローチしていきましょう。各ステップを小さな分離された問題として考えてください。各ステップでは、最も直感的な解決策から始め、なぜそれが機能しないのかを確認し、機能する解決策を構築していきます。

データ取り込み

パイプラインの始まりから始めてみましょう、データ取り込みです。データ取り込みの問題は非常に理解しやすいです。単純に複数のソースからイベントを取り込むことが目標です。

Image by Author

しかし、最初には問題が簡単に見えるかもしれませんが、いくつかの微妙なニュアンスがあります。

  1. データの規模が非常に大きく、秒間数十万件のイベントにまで及びます。
  2. これらのイベントはリアルタイムで取り込まれなければならず、数秒の遅延さえも許容できません。

まずはシンプルに始めましょう。最も直感的な方法は、各イベントをリクエストとして推薦システムに送ることですが、この解決策には多くの問題があります。

  1. イベントを送信するサービスは、推薦サービスからのレスポンスを待つ必要はありません。それによってサービスのレイテンシが増加し、推薦サービスから200が送信されるまでブロックされます。代わりに、ファイアアンドフォーゲットリクエストを送信するべきです。
  2. イベントの数は非常に変動し、日中に増減するでしょう(例えば、夜間やセール時に増える)。イベントの規模に基づいて推薦サービスのスケールを拡張する必要があります。これは管理して計算する必要があります。
  3. 推薦サービスがクラッシュした場合、ダウンしている間にイベントが失われてしまいます。このアーキテクチャでは、推薦サービスは単一障害点です。

これをApache Kafkaのようなメッセージブローカーや「イベントストリーミングプラットフォーム」を使用して修正しましょう。それが何かわからない場合は、簡単に言うと、特定のトピックに対してメッセージをパブリッシャーから取り込み、サブスクライバーがトピックに対してリスン(またはサブスクライブ)し、トピックにメッセージがパブリッシュされると、サブスクライバーはメッセージを受信します。次のセクションでKafkaのトピックについて詳しく説明します。

Kafkaについて知っておく必要があることは、プロデューサーとコンシューマーの間で疎結合なアーキテクチャを容易にするということです。プロデューサーはKafkaのトピックにメッセージをパブリッシュでき、そのメッセージがコンシューマーがいつ、どのように、またはメッセージを消費するかを気にする必要はありません。コンシューマーは自分の時間でメッセージを消費し、処理できます。Kafkaはスケーリングも非常に容易で、イベントのスケールが増加する場合でも、Kafkaは単により多くのイベントを保持し、推薦サービスをスケールアップさせることができます。

Image by Author

各サービスはイベントをApache Kafkaに送信します。推薦サービスはこれらのイベントをKafkaから取得します。これがどのように役立つかを見てみましょう。

  1. イベントは非同期に処理されるため、サービスは推薦サービスからのレスポンスを待つ必要がありません。
  2. Kafkaのスケーリングは簡単であり、イベントの規模が増えると、Kafkaは推薦サービスのスケールアップと同時により多くのイベントを保存します。
  3. 推薦サービスがクラッシュしても、イベントは失われません。イベントはKafkaに永続化されるため、データが失われることはありません。

これでイベントをサービスに取り込む方法がわかりましたので、次はアーキテクチャの次の部分、イベントの処理に移りましょう。

データ処理

データ処理はデータパイプラインの重要な部分です。イベントを受け取ったら、ユーザーのために新しい推薦を生成する必要があります。たとえば、ユーザーが「モニター」を検索した場合、この検索に基づいてユーザーの推薦を更新する必要があります。ユーザーがモニターに興味があるということを追加するかもしれません。

アーキテクチャについて詳しく話す前に、これを忘れて少し推薦の生成方法について話しましょう。これはまた、機械学習が関連しています。次の投稿を続けるために理解することは非常に重要ではありませんが、非常に興味深いので、基本的な説明をお伝えします。

ユーザーのインタラクションとその意味をより理解してみましょう。ユーザーが検索、クリック、スクロールのイベントを通じてウェブサイトとやり取りする際、彼らは自身の興味に関して何かを示しています。私たちの目標は、これらのインタラクションを理解し、ユーザーを理解するために活用することです。

ユーザーを考えるとき、おそらく名前や年齢などの個人として考えるでしょうが、私たちの目的では、各ユーザーをベクトルまたは単純な数値のセットとして考える方が簡単です。これは少し混乱するかもしれません(ユーザーを数値のセットと表現するなんてどういうことだろう)、しかし私と一緒に頑張って、これがどのように機能するか見てみましょう。

各ユーザー(または彼らの興味)を2D空間のポイントとして表現できると仮定しましょう。各軸はユーザーの特性を表します。X軸が旅行好きの度合いを、Y軸が写真撮影好きの度合いを表すと仮定しましょう。ユーザーの各アクションは、このユーザーの2D空間内の位置に影響を与えます。

ユーザーが以下のポイントから始まるとしましょう —

Image by Author

ユーザーが「トラベルバッグ」を検索すると、ユーザーは旅行が好きなことを示すので、ポイントは右側に移動します。

Image by Author

もしユーザーがカメラを検索した場合、代わりにユーザーはY軸上で上に移動していたでしょう。

私たちはまた、各製品を同じ2D空間内のポイントとして表現します。

Image by Author

上記の図のユーザーの位置は、ユーザーが旅行が大好きで、写真撮影も少し好きであることを示しています。各製品も、写真撮影や旅行に関連する程度に応じて配置されます。

ユーザーと製品は2次元空間の単なるポイントなので、それらを比較し、数学的な操作を行うことができます。例えば、上記の図から、最も近い製品をユーザーに勧めることができます。この場合、スーツケースです。

上記はレコメンデーションシステムについての非常に基本的な紹介です(詳細は記事の最後で説明します)。これらのベクトル(通常は2次元よりも大きな次元)は、埋め込み(ユーザーの埋め込みは私たちのユーザーを表し、製品の埋め込みはウェブサイト上の製品を表す)と呼ばれます。さまざまな種類の機械学習モデルを使用してこれらを生成することができ、私が説明したもの以上に多くの内容がありますが、基本的な原則は同じです。

問題に戻りましょう。各イベントごとに、ユーザーの埋め込みを更新し(ユーザーをn次元のチャート上で移動させ)、関連する製品を推奨として返す必要があります。

これらの埋め込みを生成するために、各イベントのためのいくつかの基本的な手順を考えてみましょう。

  1. update-embeddings: ユーザーの埋め込みを更新する
  2. gen-recommendations: ユーザーの埋め込みに関連する(または近い)製品を取得する
  3. save: 生成された推奨とイベントを保存する

各イベントのためにPythonのサービスを構築することができます。

Image by Author

これらのマイクロサービスは、Kafkaのトピックを監視し、イベントを処理して次のトピックに送信し、別のサービスが監視することができます。

Image by Author

再度リクエストを送信する代わりに、このアーキテクチャではカフカを使用するため、前に話したすべての利点を得ることができます。単一のPythonマイクロサービスは単一の障害点にならず、スケールを扱うこともはるかに簡単です。最後のサービスsave-workerは、将来の利用のためにレコメンデーションを保存する必要があります。それがどのように機能するかを見てみましょう。

データシンク

イベントを処理し、それに対するレコメンデーションを生成したら、イベントデータとレコメンデーションデータを保存する必要があります。イベントとレコメンデーションデータを保存する場所を決定する前に、データストアの要件を考慮しましょう。

  1. スケーラビリティと高い書き込みスループット- 多数の着信イベントがあり、各イベントがユーザーのレコメンデーションを更新することを忘れないでください。これは、データストアが非常に高い書き込み数を処理できる必要があることを意味します。データベースは高度にスケーラブルであり、直線的にスケールできる必要があります。
  2. シンプルなクエリ- 複雑なJOINを実行したり、さまざまなタイプのクエリを行ったりする必要はありません。私たちのクエリニーズは比較的シンプルで、ユーザーが指定された場合に、事前に計算されたレコメンデーションのリストを返す必要があります。
  3. ACIDの要件なし- データベースは強力なACID準拠の必要性はありません。一貫性、アトミック性、分離性、耐久性に対する保証は必要ありません。

単純に言えば、スケールが非常に大きいデータベースが必要ですが、余分な装飾は必要ありません。

これらの要件には、Cassandraが理想的な選択肢です。分散アーキテクチャのため、Cassandraは直線的にスケールし、非常に高い書き込みスループットに対応できます。

2つのテーブルを使用して、ユーザーごとのレコメンデーションとイベントを保存します。最後のPythonマイクロサービスsaveワーカーはCassandraにイベントとレコメンデーションデータを保存します。

Image by Author

クエリ

クエリは非常にシンプルです。私たちはすでに各ユーザーのレコメンデーションを計算し保持しています。これらのレコメンデーションをクエリするには、単純にデータベースをクエリし、特定のユーザーのレコメンデーションを取得するだけです。

Image by Author

完全なアーキテクチャ

以上です!完全なアーキテクチャが完成しましたので、完全なアーキテクチャを描き出して、どのようなものか確認しましょう。

Image by Author

さらなる学習のために

Kafka

Kafkaは、極めて大きなスケールを扱うためにLinkedInによって開発された驚異的なツールです(LinkedInのブログ記事によれば、2015年には秒間約1300万件のメッセージを扱っていました)。

Kafkaは直線的にスケールし、狂気じみた高いスケールを処理する能力に優れていますが、そのようなシステムを構築するためには、エンジニアがKafkaを知り、理解し、他のツールとの比較をしなければなりません。

私はKafkaについてのブログ記事を書いており、Kafkaとは何か、メッセージブローカーとの違い、LinkedInエンジニアが書いたオリジナルのKafka論文の抜粋について説明しています。この記事が気に入った場合は、Kafkaに関する私の記事もチェックしてください。

システム設計シリーズ:10,000フィートのApache Kafka

Kafkaとは何か、どのように機能し、いつ使用すべきかを見てみましょう!

betterprogramming.pub

Cassandra

Cassandraは、非常に高い書き込みスループットを処理するために設計されたユニークなデータベースです。非常に高いスループットを処理できる理由は、高いスケーラビリティを持つ非中央集権的なアーキテクチャにあります。最近、Cassandraについて、それがどのように動作し、それを使用する場合と使用しない場合について説明したブログ記事を書きました。

システム設計のソリューション:Cassandraを使用する場合と使用しない場合

Cassandraを使用する場合と使用しない場合について知っておくべきすべて

VoAGI.com

レコメンデーションシステム

レコメンデーションシステムは、すばらしい技術であり、私たちが今日使用しているほとんどのアプリケーションで使用されています。どのシステムでも、パーソナライゼーションとレコメンデーションシステムは、ユーザーの検索と発見のフローの核心を形成します。

私は検索システムについてかなり書いてきましたし、検索システムに基本的なパーソナライゼーションの構築方法について少し触れましたが、次のトピックでは、レコメンデーションエンジンの詳細について、それがどのように動作し、どのようにアーキテクチャを設計するかについてより深く掘り下げます。もしそれが興味深いと思われるなら、VoAGIで私に従って、より多くのコンテンツを入手してください! LinkedInでも定期的に読めるように、小さなコンテンツをたくさん投稿しています。例えば、このカフカコネクトについて説明している投稿は、どのように動作し、なぜわずかな図解で非常に人気があるのかを説明しています。

結論

この投稿が楽しめたら嬉しいです。投稿についてのフィードバックや次に話すべきことについての意見があれば、コメントとして投稿してください!

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more