2017-08-02 10 views
1

ようなシナリオで最高の再試行ポリシーは何です:ベスト再試行ポリシー

Databaseは、データエントリを作成することに成功したが、その後、応答がApplicationに達するのに時間がかかりすぎます。したがって、作業を実行するにはApplicationが作成を再試行し、もちろんDatabaseは "already exists"エラーを返します。ですから、Applicationの視点からは、創造は失敗したようですが、実際は成功しました。さらに悪いことに、これが一連のステップの途中にある場合は、Applicationが前の手順でロールバックをトリガーするかどうかを判断する方法がありません。

Applicationでタイムアウトの長さを長くすることは、IPネットワークが決して100%信頼できるものではなく、ネットワーク内で応答が失われる可能性が非常に低いため、受け入れられないソリューションです。

作成する前に<data>の存在を確認すると動作する可能性があります。しかし、それは並行性が考慮されるときだけです。私の場合、Databaseへの複数のクライアントが存在する可能性があり、競争条件の可能性については確信していません。

+-------------+            +-----------+  
| Application |            | Database |  
+-------------+            +-----------+  
     |               |   
     | CREATE <data>           |   
     |--------------------------------------------------------->|   
     |               |   
     |               | creating 
     |               |--------- 
     |               |  | 
     |               |<-------- 
     | -------------------------------\       |   
     |-| timeout waiting for response |       |   
     | |------------------------------|       |   
     |               |   
     |             SUCCESS |   
     |<---------------------------------------------------------|   
     | -----------------------------------------------\   |   
     |-| response from a timed out session is ignored |   |   
     | |----------------------------------------------|   |   
     |               |   
     | retry CREATE <data>          |   
     |--------------------------------------------------------->|   
     |               |   
     |        ERROR: <data> ALREADY EXISTS |   
     |<---------------------------------------------------------|   
     | ---------------------------------------------------\  |   
     |-| no idea whether the creation actually took place |  |   
     | |--------------------------------------------------|  |   
     |               |   
+0

アプリケーションで「ネットワーク接続のタイムアウト」エラーが発生していませんか? –

+0

@NevilleKはいそうです。そしてそれが再試行を引き起こすものです。 – Sah

答えて

0

最近のほとんどのデータベースが既に存在する場合アトミックが存在しない場合にデータを挿入、更新(または何もしない)だろう「アップサート」の文を書いていくつかの方法を提供します。こうすることで、アプリケーションは安全に再試行でき、データがすでに作成されている場合はエラーが発生せず、データ作成はidempotentになります。いくつかの一般的なデータベースのための

例:

  • MySQL

    -- Do nothing if data exists 
    INSERT IGNORE ... 
    -- Update if data exists 
    INSERT ... ON DUPLICATE KEY UPDATE ... 
    
  • PostgreSQL

    -- Do nothing if data exists 
    INSERT ... ON CONFLICT DO NOTHING 
    -- Update if data exists 
    INSERT ... ON CONFLICT ... DO NOTHING 
    
  • Oracle

    -- Do nothing if data exists 
    MERGE INTO ... USING ... 
    WHEN NOT MATCHED THEN INSERT ... 
    -- Update if data exists 
    MERGE INTO ... USING ... 
    WHEN NOT MATCHED THEN INSERT ... 
    WHEN MATCHED THEN UPDATE ... 
    

アトミックオペレーションまたはトランザクションがオプションでない場合、再試行は有害ではないように、あなたはあなたのデータベース操作を書くことができ、およびデータベースが既にある場合は最初にチェックすることをループ内の各操作を行います所望の状態にして、そうでなければ操作を試み、失敗したときに再試行する。つまり、(擬似コード)のようなもので:あなたはより詳細な情報を提供する場合

max_retries = n 
retries = 0 
WHILE NOT database_in_desired_state 
    IF retries < max_retries THEN 
     perform_database_operation 
     retries = retries + 1 
    ELSE 
     fail 

あなたはUPDATE some_table SET field = value, version = version + 1 WHERE version = expected_version例えば(条件付きまたは重複した操作が許可されないように、ユニーク制約などの追加の操作を行うことによって再試行が無害化することができます

複数のリモートシステムで長い一連の操作を実行している場合は、障害が発生した場合に全体の操作をロールバックする必要があります。すべてのインタラクションを単一の(分散した)トランザクションでラップする方法はありません。手動でワイルドバックする補償トランザクションを作成する必要がありますkはこれまでのところエラーで完了しました。もちろん、補償トランザクションも失敗する可能性があり、その処理方法を検討する必要があります。1つの方法は、失敗したトランザクションまたは不整合な状態を探す周期的なクリーンアップタスクを持つことです。

+0

私たちが使用するデータベースはLDAPベースです。多くの場合、顧客が要求するほとんどの場合、いくつかのLDAP操作で処理を完了し、プロセス間で別のモジュールとのやりとりが混在する必要があります。 – Sah

+1

LDAPの要件を明確にしてください - あなたが「データベース」と言ったときに大部分の人がRDBMSを考えると、多くの悪い回答が得られます。 –

+0

私はそれを見ている方法で、それはデータベースによって解決できる問題ではなく、アプリケーションの側でより多くのポリシーを選択できるので、より一般的な質問をするようにしていました。しかし、次に質問をするときには、あなたのアドバイスを考慮に入れます。 – Sah

0

すべては文脈によって異なります。

はい、ネットワーク接続は失敗する可能性がありますが、リスクの大きさを判断する必要があります。エンタープライズ・グレードの機器を使用してプロフェッショナル・ホスティング・セットアップを使用している場合、これはまったく起こりません。この場合、ネットワークの問題を処理するために、アプリケーションに多くの追加ロジックを組み込むことはしません。データの整合性を保つために、データベースのトランザクション管理機能を使用する必要があります。 アプリケーションでネットワーク例外が検出されたら、ユーザーにエラーを表示してから、再度開始するように要求できます。

環境が本質的に信頼できない場合(公共のインターネットを介して接続している場合など)、共通アーキテクチャのパターンは同期動作ではなくメッセージバスを使用することです。

信頼性の低いネットワーク条件を処理するための同期コードの作成は簡単ではありません。投稿された擬似コード@markuskから始めますが、そのクローズに追加してデータベース接続を再オープンします。

関連する問題