2

外部ゲートウェイを使用して SMS を送受信するクライアント サーバー ベースのアプリケーションがあります。効率とパフォーマンスを向上させるために、既存のアーキテクチャを再設計/変更することを考えています。同じことに関する考えや提案を歓迎します。ピーク時は約10分ですのでご注意ください。クライアント - サーバー - ゲートウェイから 1 時間あたり 3000 件の SMS が送信されます。1 日に送信される SMS の合計量は、8000 ~ 10,000 の間である可能性があります

既存のアーキテクチャ

SMSを送信

  1. クライアントはサーバーに SMS を送信し、サーバーからの一意の smsid (データベースによって生成される) を待ちます (接続を開く)
  2. サーバーはSMSをデータベースに保存し、SMSをゲートウェイに送信します。
  3. ゲートウェイは sms をハンドセットに送信し、一意のレシート ID をサーバーに返します。
  4. サーバーは一意の領収書 ID をデータベースに保存します
  5. サーバーは一意の smsid (手順 2 で生成) をクライアントに返します

ステップ 1 ~ 5 は、1 つの要求 - 応答サイクルです。

SMS の確認

  1. ゲートウェイはサーバーにメッセージのステータスを送信します
  2. サーバーは、データベース内のメッセージのステータスを、送信済み/失敗/不明などに更新します。
  3. クライアントはサーバーを定期的にポーリングして、以前に受信した smsid を使用してメッセージのステータスを受信します。
  4. クライアントは、クライアント側でステータスを更新します。

データベース設計

すべての SMS は、データベース内の 1 つの単一の SMS テーブルに格納されます。当初、データは 2006 年頃にさかのぼり、1 つのテーブルに約 500 万件のレコードがありました。これでデータがアーカイブされ、現在の年のデータのみが表に表示されます。

短所 - クライアントが長時間待機すると、接続タイムアウト エラーが発生し、同じメッセージがサーバーに再送信されることがあります。サーバーはこれが重複メッセージであることを検出する方法がないため、メッセージをゲートウェイに再送信し、その結果、顧客への SMS が重複します。- 複数の SELECT、UPDATE クエリが毎秒 sms テーブルで実行され、データベースにかなりの負荷がかかり、システムに障害が発生することがあります。また、データをアーカイブするメカニズムもありません。

新しいアーキテクチャ

SMSを送信

  1. クライアントはサーバーに SMS を送信し、サーバーからの一意の smsid (データベースによって生成される) を待ちます (接続を開く)
  2. サーバーはSMSをデータベースに保存し、一意のSMSIDをクライアントに返します。

ステップ 1 から 2 は、1 つの要求応答サイクルです。

  1. cron を使用してデータベース テーブルを定期的にポーリングし、SMS を取得してゲートウェイに送信する別のプロセス、または Java マルチスレッドを使用できますか???
  2. ゲートウェイは sms をハンドセットに送信し、一意のレシート ID をサーバーに返します。
  3. サーバーは一意の領収書 ID をデータベースに保存します

SMS が上記と同じままであることを確認する

DB設計

  1. Postgresql の時間/範囲パーティショニングを使用して、受信日または継承に基づいてデータをパーティショニングします。
  2. 毎日 table1 から table2 にデータを移動する別のスクリプト。ユニオン クエリを使用してテーブルを結合し、データのレポートと取得を行います。

データベースのパフォーマンスに基づくより良いアプローチは何ですか?

4

1 に答える 1

0

まず、これを複数のテーブルに分割する必要性について確信が持てません。大きなテーブルよりも小さなテーブルの方がキーのチェックが容易になるような一括操作が行われていない。ただし、あなたの場合に役立つ可能性が高いのは、部分インデックスの概念です。この場合、現在の日次レコードのみを索引付けします。

この点で、現在の日付のレコードのみに対して新しいインデックスを毎日作成し、以前のインデックスを削除することができます。これを行う場合、この部分インデックスをすばやく作成できるように、おそらく日付にもインデックスを付けたいと思うでしょう。

テストする機会があれば、すぐにこれをいくつかのパフォーマンス ノートで編集します。

アップデート

テスト後、単純な日付インデックスでは不十分なようです。あなたがしなければならないことは、デフォルトで true の current_index bool 値を追加するようなものだと思います。次に、WHERE current_index = true のインデックスを作成し、1 日の終わりにこれらを false に設定して、インデックスから除外することができます。

これにより、クエリが高速に維持され、毎日テーブルに新しいインデックスが追加されるのを防ぐことができ、同時に、はるかに小さいインデックスの利点が得られます。これにより、パフォーマンスに関して両方の長所が得られるはずです。

また、これ:cronを使用してデータベーステーブルを定期的にポーリングし、SMSを取得してゲートウェイに送信するプロセスを分離するか、Javaマルチスレッドを使用できますか???

Postgres ドキュメントの LISTEN と NOTIFY を見てください。db テーブルをポーリングしないでください。通知をポーリングするだけです。これにより、かなりのオーバーヘッドが節約されます。ただし、安全ではないため、ペイロードの NOTIFY に依存しないでください。アプリケーションがポーリングする必要があることを知るための「トリガー」として使用してください。

基本的にこれが行うことは、サーバーに非常に軽量の非同期通知を送信することです (トリガーでこれを行うことができます)。その後、アプリはポーリングすることをお勧めします。ノーディファイング トランザクションがコミットされると、通知が送信されます。

于 2012-09-08T05:43:43.400 に答える