0

いくつかの長いタスクを実行するlibクラス(「アップデーター」)があります。このタスクは手動で(ブラウザで)または2時間ごとに起動できます(このタスクの2時間ごとにスケジュールを実行するいつでもgemを実装しました)。

このタスクが DB で多くの作業を行っていることを見て、いくつかの同時実行エラーが発生する可能性があると思います (たとえば、 when がまだ機能している場合)。私は正しいですか?

次のような Updater クラスの疑似コードを使用して、ミューテックスを使用したソリューションを考えました。

module Updater
  def start
    #do some job
  end
end

正しい解決策は、私が思うに、このようなものです

module Updater
  def start
    mutex.lock
       #do some job
    mutex.unlock
  end
end

私の解決策は正しいですか?

同時実行に関する詳細情報を提供していただけますか (たとえば、Rails でミューテックスを正しく使用する方法、必要なものなど)。検索しましたが、適切な説明のあるものは何も見つかりませんでした。

4

1 に答える 1

1

Ruby Mutexを使用する正しい方法は、ロックを取得し、コード ブロックを実行してから、ロックを再度解放することです。つまり、lock を unlock と組み合わせて呼び出すことです...

@mutex = Mutex.new
..

def start
  @mutex.lock
  begin
    ..
  ensure
    @mutex.unlock rescue nil
  end
end

または同期メソッドを使用するには:

@mutex = Mutex.new
..

def start
  @mutex.synchronize do
    # do something
  end
end

例は、Rack ミドルウェア クラスRack::Lockにあります。ただし、のようなクラス変数を使用したとしても、ミューテックス/セマフォが異なるタスクと異なるプロセス間で保持されない可能性があるため、それがあなたの場合に役立つかどうかは@@mutexわかりません(「タスク」は「rake によって開始された異なるプロセスであると想定しています」タスク」)。Mutex クラスは、複数の同時スレッドからの共有データへのアクセスを調整するために使用できる単純なセマフォを実装するため、スレッド セーフを実現するのに役立ちます。ただし、スレッド セーフに関する優れた RailsCastもあります(残念ながら、ペイウォールの背後にあるだけです)。

あなたの場合、データベースにグローバルロックフラグを作成するか、ファイルシステムにグローバルロックファイルを作成し、プロセスが終了したときtouch lock.txtに再度削除すると役立つ場合があります。rm lock.txtこれらのシェル コマンドは、Rubyで Kernel.system または %x を使用して実行できます。ファイルが存在するFile.exists?("lock.txt")場合、更新を中断できます。

于 2013-01-02T13:15:15.630 に答える