6

インフラストラクチャにResqueサーバーの「クラスター」があります。それらはすべて同じ正確なジョブの優先順位などを持っています。保留中のジョブの数と、サーバー上でそれらのジョブを処理するために使用可能なリソースに基づいて、Resqueサーバーの数を自動的に増減します。私は常に最低2台のResqueサーバーを稼働させています。

私の問題は、1回限りの迅速なジョブを実行すると、両方のサーバーがそのジョブを処理することがあるということです。これは悪いです。

次のようなものを使用して、自分の仕事にロックを追加しようとしました。

require 'resque-lock-timeout'

class ExampleJob
  extend Resque::Plugins::LockTimeout

  def self.perform
   # some code
  end
end

このプラグインは、実行時間の長いジョブで機能します。ただし、これらの非常に小さな1回限りのジョブの場合、処理はすぐに行われます。Resqueサーバーは両方とも、姉妹サーバーによって設定されたロックを認識せず、両方ともロックを設定し、ジョブを処理し、ロックを解除して、完了します。

このタイプのジョブを1つの専用サーバーで処理することを除いて、現時点で何をすべきか、またはどのような解決策があるのか​​完全にはわかりません。これは、構成とスケーリングが非常に困難です。私は本当に両方のサーバーがそれを処理できるようにしたいのですが、一方がキューからそれを取得したら、もう一方がそれを実行しないようにしてください。

誰かがいくつかの実行可能な解決策を提案できますか?

4

2 に答える 2

2

作成したロックの値よりも小さいTunique_id を持つロックを探す前に、ミリ秒待機するようにロック インタープリターを記述します。

これによりレースの勝者が決まり、敗者は自己終了します。

TN指定されたキューのプール内のすべてのサーバー間の並列処理の待機時間です。これは、1000 ミリ秒からスケールバックすることでヒューリスティックに判断できます。これは、ジョブが重複して発生していることが再び判明するまで続きます。レイテンシの変動にパディングを与えます。

これは、mutex スレッド セーフに対する Busy-Wait ソリューションと呼ばれます。これは、Mutex を解決しなければならないさまざまなシナリオ (ロックなど) を考えると、許容できるトレードオフの 1 つと見なされます。

モバイルから離れたときにいくつかのリンクを投稿します。ミューテックスに関するウィキペディアのエントリは、これらすべてを説明するはずです。

1. スケジューラーを使用して複製を制御します。2. 実行時間の短いジョブを順番に実行するように設計されたキューに分類します。

TL;DR 完全な解決策はありません。条件との適切なトレードオフのみです。

于 2012-10-28T06:16:33.203 に答える
1

アイテムは を使用してデキューされるため、2 つのワーカーが同じ「ペイロード」を取得することはできませんBLPOP。Redis は、キューに入れられたアイテムを最初に呼び出したクライアントにのみ送信しますBLPOP。ジョブを複数回エンキューしているように聞こえるため、2 つのワーカーが同じ引数で異なるペイロードを取得できます。「resque-lock-timeout」の目的は、同じメソッドと引数を持つペイロードが同時に実行されないようにすることです。ただし、2 番目のジョブがロックを取得しようとする前に最初のジョブがロックを解放した場合、2 番目のペイロードの動作は停止しません。

これが実行時間の短いジョブでのみ発生することは理にかなっています。何が起こっている可能性があります:

payload 1 is enqueued
payload 2 is enqueued
payload 1 is locked 
payload 1 is worked
payload 1 is unlocked
payload 2 is locked
payload 2 is worked
payload 2 is unlocked

長時間実行されるジョブと同様に、次のシナリオが発生する可能性があります。

payload 1 is enqueued
payload 2 is enqueued
payload 1 is locked
payload 1 is worked 
payload 2 is fails to get lock
payload 1 is unlocked

Resque をオフにして、ジョブをエンキューしてみてください。Resque キューのリストで redis を調べます (または を使用して Redis を監視しますredis-cli monitor)。Resque が複数のペイロードをキューに入れたかどうかを確認します。それでもペイロードが 1 つしか表示されない場合は、リストを監視して、別の resque ワーカーがrecreate失敗したジョブを呼び出しているかどうかを確認します。

'resque-lock-timeout' でジョブの処理にかかる時間よりも長くロックを保持したい場合は、release_lock!メソッドをオーバーライドして、ロックを削除する代わりに有効期限を設定できます。

module Resque
  module Plugins
    module LockTimeout  
      def release_lock!(*args)
        lock_redis.expire(redis_lock_key(*args), 60) # expire lock after 60 seconds
      end
    end
  end
end

https://github.com/lantins/resque-lock-timeout/blob/master/lib/resque/plugins/lock_timeout.rb#l153-155

于 2012-10-30T17:07:42.560 に答える