6

2 つの異なるデータセンター (米国とヨーロッパ) にいくつかのバックエンド サーバーがあります。これらのサーバーは、CPM基本的に広告を配信しているだけです。

MySQLそれに加えて、広告主の広告キャンペーンの資金残高を提供する大規模でファットなマスターサーバーがあります。繰り返しになりますが、すべての広告キャンペーンはCPM基本的に配信されています。

バックエンドからインプレッションが配信されるたびに、インプレッション価格に応じて広告キャンペーンの残高を減らさなければなりません。

たとえば、1 インプレッションあたりの価格は 1 セントです。バックエンド A は 50 インプレッションを配信し、残高を 50 セント減少させます。Backed B は 30 インプレッションを配信し、残高が 30 セント減少します。

したがって、私が見る主な問題は次のとおりです。

  • バックエンドは、毎秒約 2 ~ 3,000 インプレッションを配信しています。そのため、MySQL でその場でお金の残高を減らすことは、良い考えではありません。

  • バックエンドは、米国および EU のデータセンターにあります。MySQL マスター サーバーは米国にあります。ネットワーク遅延が問題になる可能性があります [EU バックエンド] <-> [US マスター]

私が見る可能な解決策として:

  • Cassandra分散型カウンター収納として使用。私はこの解決策を可能な限り長く認識しようとします。

  • バックエンドによるお金の一部の予約。たとえば、バックエンド A がマスターに接続し、$1 を予約しようとしています。$1 は予約されており、バックエンドでローカル (Redisたとえばローカル) に保存されているため、光速でデクリメントしても問題はありません。私が見る主な問題は、バックエンドが配信スキームから無効になっている場合 (バランサーから「切断」されている場合)、バックエンドからマスターサーバーにお金を返すことです。とにかく、それは非常に優れたソリューションのようであり、現在の技術スタックにとどまることを可能にします.

  • 助言がありますか?

UPD: 1 つの重要な追加事項です。広告のインプレッションを高精度で配信することはそれほど重要ではありません。リクエストされたよりも多くのインプレッションを配信できますが、それ以下になることはありません。

4

5 に答える 5

5

残高を減らす代わりに、各バックエンドから報告されたすべての作業のログを保持し、必要なときにキャンペーンのアカウントから報告されたすべての作業の合計を差し引いて残高を計算してはどうでしょうか?

テーブル:

campaign (campaign_id, budget, ...)
impressions (campaign_id, backend_id, count, ...)

報告作業:

INSERT INTO impressions VALUES ($campaign_id, $backend_id, $served_impressions);

必要な場合にのみキャンペーンの残高を計算します。

SELECT campaign.budget - impressions.count * $impression_price AS balance
FROM campaign INNER JOIN impressions USING (campaign_id);
于 2014-01-27T17:01:43.083 に答える
4

これは、おそらく最も古典的な広告配信/インプレッション カウントの問題です。基本的に、いくつかの目標のバランスをとろうとしています。

  1. 広告インベントリを十分に提供していないため、可能な限り多くの収益を上げていません。
  2. 広告枠を過剰に提供しないため、間違いを顧客に請求できないため、無料で提供されます。
  3. インプレッションの配信が速すぎないのは、通常、顧客は特定のカレンダー期間に広告を掲載することを望んでおり、午前 2 時から午前 3 時までの 1 時間ですべてを配信すると、顧客は不満を抱き、何の役にも立たないからです。

特定のスポットで利用可能なインプレッション数が必ずしもわからないため (トラフィックに依存するため)、これは注意が必要です。クリック率。

これには単一の「正しい」パターンはありませんが、何年にもわたるコンサルティングを通じて成功を収めてきたのは次のとおりです。

  • バックエンド データベースを権限のあるストアとして扱います。スケーラビリティとフォールト トレランスの目標をサポートするために、必要に応じて顧客ごとに分割します (可能な停止を一部の顧客に限定します)。データベースは、たとえば 7 日間で 1000 インプレッションの広告掲載オーダーがあることを認識しています。これは定期的に (数分から数時間) 更新され、残りのインベントリといくつかの基本的な統計が反映され、キャッシュが失われた場合にキャッシュをブートストラップします。

  • 広告サーバー レベルで残高を気にする必要はありません。インプレッション数、レート、ターゲットのみを扱います。ロギングとオフライン処理を通じて、事後にそれをお金の残高に決済します。

  • 非常に軽量で高速なキャッシュ (Web サーバーの近く) から広告インベントリを配信します。このキャッシュは、残りのインプレッション数と広告掲載オーダーの目標配信速度をキャッシュし、実際の配信速度を計算します。

  • 配信されたすべてのインプレッションを関連データとともに記録します。

  • サービス速度を定期的に収集し、データベースにプッシュします。

  • 定期的にログを収集し、実際に配信された在庫を計算してデータベースにプッシュします。(停止、DoS、スパムなどにより、ログから再計算する必要がある場合があります。)

于 2014-01-23T22:20:56.847 に答える
3

広告主の広告キャンペーンの資金残高を提供する、大規模でファットなマスター MySQL サーバー上にサービスを作成します。

このサービスは、地域サーバーに creditLimit を返す getCampaignFund(idcampaign, requestingServerId, currentLocalAccountBalanceAtTheRequestingServer) を実装する必要があります。

クレジット カードのメカニズムを想像してみてください。マスター サーバーは、地域サーバーにある程度の制限を与えます。この制限が減少すると、しきい値によってこのリクエストがトリガーされ、新しい制限が取得されます。ただし、新しいクレジット制限を取得するには、地域サーバーが以前の制限からどれだけ使用したかを通知する必要があります。

地域サーバーは、これらのサービスを追加で実装する場合があります。

  1. currentLocalCampaignAccountBalance getCampaignAccountBalance(idcampaign): 特定のキャンペーンの現在の使用状況を通知するため、メイン サーバーは特定の時間にすべてのキャンペーンを更新する可能性があります。
  2. addCampaign(idcampaign, initialBalance): 新しいキャンペーンを登録し、クレジット制限を開始します。
  3. supendCampaign(idcampaign): キャンペーンへのインプレッションを一時停止します。
  4. resumeCampaign(idcampaign): キャンペーンのインプレッションを再開します。
  5. currentLocalCampaignAccountBalance finishCampaign(idcampaign): キャンペーンを終了し、現在のローカル アカウントの残高を返します。
  6. currentLocalCampaignAccountBalance updateCampaignLimit(idcampaign, newCampaignLimit): 制限を更新します (地域サーバー間のクレジットの再割り当て)。このサービスは、キャンペーンの与信限度額を更新し、以前に取得した与信限度額のアカウント残高を返します。

サービスは優れているため、疎結合のアーキテクチャが得られます。メイン サーバーがしばらくオフラインになっても、地域サーバーはクレジット制限が終了するまで稼働し続けます。

于 2014-01-28T14:23:19.490 に答える
2

これは詳細な標準的な回答ではないかもしれませんが、私の考えを可能な限り [そして少なくとも部分的な] 解決策として提供します。ここで少し推測する必要があります。質問は、mysql のボトルネックを特定するためにどのような測定が行われたかについてあまり言及していないためです。私は、1秒あたり1〜2kのトランザクションがmysqlの範囲外ではないためだと言います。私は、以下の手法をいくつか組み合わせて、これほど高い [そしてはるかに高い] ボリュームを簡単にサポートできました。ここでは特定の順序ではありません。これは、どの測定値がボトルネックであるかに依存するためです。1 チューニング バッファー。2-追加ラム; 3 ソリッド ステート ドライブ。4シャーディング; 5-5.5 以下の場合、mysql 5.6+ にアップグレードします。だから私はいくつかの測定を行い、測定結果によって要求されるように上記を適用します. お役に立てれば。

于 2014-01-24T16:10:05.123 に答える
1

私が想定し

  • 広告は、おそらく少なくとも数千のバッチで購入されます
  • 同時に配信される複数の異なるバッチからの広告があり、それらすべてが同時にほぼ空になるわけではありません
  • インフラストラクチャがダウンしている場合は、追加の広告を配信しても問題ありません。

だから、ここに私がそれをする方法があります。

BigFat バックエンドにはこれらのメソッドがあります

  • getCurrentBatches()しばらく使用できるバッチのリストを提供します。各バッチには、1 秒あたりに配信できる広告数のレートが含まれています。各バッチには、serveMax も含まれています。BigFat と再度対話する前に配信される可能性のある広告の数。
  • deductAndGetNextRateAndMax(batchId, adsServed)最後の呼び出し以降に配信された広告の数を差し引いて、新しいレート (同じ場合もあります) と新しい serveMax を返します。

バッチごとに料金を設定する理由は、1 つのバッチが資金を使い果たし始めると、完全に使い果たされるまで提供される量が少なくなるためです。

1 つのバックエンドが BigFat にしばらく接続しないと、serveMax に達し、他のバッチからの広告のみを配信します。

バックエンドは、serveMax に応じて、秒、分、または時間のレポート期間を持つことができます。数百万のインプレッションが残っている新しいバッチは、レポートが返されるまでの長い間安全に実行できます。

BigFat が呼び出されるdeductAndGetNextRateAndMaxと、配信された広告の数が差し引かれ、設定された最大値までの残りの合計インプレッションの 75% などを返します。これは、バッチの最後に補充されていない場合、バッチが空になった後に配信される広告がいくつかあることを意味しますが、バッチが長時間ほとんど枯渇するよりも、実際に枯渇する方がよいでしょう。

于 2014-01-29T07:43:26.483 に答える