2013-03-25 6 views
7

Ich verwende einen verzögerten Job in einem Setup, in dem ich mehrere Worker ausführe. Um meiner Frage willen ist es nicht wirklich wichtig, aber sagen wir mal, dass ich 10 Arbeiter betreibe (momentan im Entwicklungsmodus).Mehrere verzögerte Jobprozesse, die denselben Job starten

Das Problem, das ich habe, ist, dass zwei verschiedene Arbeiter manchmal anfangen, an demselben Job zu arbeiten, indem sie die perform-Methode auf meinem Job-Objekt aufrufen.

Nach bestem Wissen verwendet Delayed Job pessimistisches Sperren, um dies zu verhindern, aber es scheint manchmal noch genug Zeit zu haben, um den Job zu stehlen, bevor der erste Arbeiter Zeit hat, ihn zu sperren.

Ich frage nur, ob jemand anderes dieses Problem erfahren hat, oder ob es meine Einrichtung ist, die sich schlecht benimmt. Ich benutze Postrgres und das passiert sowohl in meiner Dev-Maschine als auch auf Heroku, wo ich es hoste.

Ich werde versuchen, es in meinen Jobs zu umgehen, aber es ist immer noch ein bisschen problematisch, dass dies passiert. Im Idealfall würde es niemals passieren, dass ein verzögerter Auftrag aus zwei Prozessen auf demselben Auftrag ausgeführt wird.

Danke!

+0

Ich sehe etwas ähnliches. Es war nicht in der Lage, es vollständig aufzuspüren, aber es scheint, dass zwischen dem Prüfen nach einer Sperre und dem Herstellen der Sperre mehrere Arbeiter den Auftrag ergreifen und ausführen. –

+0

Ich sollte sagen, dass ich die Einstellung gefunden habe '' 'Delayed :: Worker.read_ahead = 1''' in einem Initialisierer schien das Problem zu mildern. –

+0

Hatte das gleiche Problem mit Resque, habe keine Lösung gefunden –

Antwort

0

Wir haben rund 60 Millionen Jobs durch verspätete Arbeit mit 12 Arbeitern ausgeführt und hatten nie einen Bericht darüber. Was ist die SQL, die Ihr verzögerter Job-Mitarbeiter ausführt? Verwenden Sie einen Edelstein, der das Sperrverhalten von Postgres verändert?

Hier ist, was der DJ sql wie für mich aussieht:

UPDATE "delayed_jobs" SET locked_at = '2014-05-02 21:16:35.419748', locked_by = 
'host:whatever.local pid:4729' WHERE id IN (SELECT id FROM "delayed_jobs" 
WHERE ((run_at <= '2014-05-02 21:16:35.415923' 
AND (locked_at IS NULL OR locked_at < '2014-05-02 17:16:35.415947') 
OR locked_by = 'host:whatever.local pid:4729') AND failed_at IS NULL) 
ORDER BY priority ASC, run_at ASC LIMIT 1 FOR UPDATE) RETURNING * 

Sie haben Probleme mit jedem anderen Code haben Sperren? Können Sie zwei Schienen Konsolensitzungen versuchen laufen und tun dies:

Console Session 1:

User.find(1).with_lock do sleep(10); puts "worker 1 done" end 

Console Session 2:

User.find(1).with_lock do sleep(1); puts "worker 2 done" end 

starten gleichzeitig sowohl diejenigen an, und wenn 2 Ende vor 1, Sie haben ein Locking-Problem allgemeiner, dass Job verzögert.