Ich benutze Sidekiq in meiner Rails-App, um 50k + Jobs gleichzeitig in die Warteschlange zu stellen. Unsere Poolgröße ist auf 9 eingestellt.
Die Jobs sind alle verwandt und machen dasselbe. Wir haben ein anderes Modell, das einen Zähler hat. Während jedes Jobs überprüfen wir, ob dieses Modell eine Spalte mit einem Wert über 200 aufweist. Wenn es über 200 liegt, erstellen wir eine weitere Instanz dieses Modells mit Wert = 0 und setzen die Jobs fort. Da jedoch 9 Jobs gleichzeitig ausgeführt werden, lesen alle 9 Jobs den Wert dieser Spalte gleichzeitig mit mehr als 200, und alle erstellen neue Instanzen, was nicht richtig ist.
Was ist der beste Weg, um dieses Problem zu lösen? Wir möchten grundsätzlich, dass alle Jobs vom aktuellsten Wert gelesen werden.
Ich kann keinen spezifischen Code posten, da dies stark von Ihrem Datenbanktyp und den Einstellungen abhängt, aber Sie sollten versuchen, die Datenbank zu sperren.
Worker beim Lesen der Tabelle sollte ihn sperren, bis er mit dem Erstellen des neuen Datensatzes mit dem Wert 0 fertig ist. Sie sollten die Tabelle zum Lesen sperren, damit andere Arbeiter warten müssen, bis dieser eine Worker fertig ist. Es ist auch möglich, separate Zeilen zu sperren, aber ich weiß nicht, ob es in Ihrem Fall funktioniert.
Angenommen, Ihr Modell heißt Counter
.
Finde / erstelle zuerst einen passenden Counter:
counter = Counter.where('count < 200').first_or_create ...
(Hinweis: Dies ist nicht atomar! Wenn Sie nicht mehr als 1 aktiven Zähler haben können, dann sehen Sie:
Race-Bedingungen in Rails first_or_create und
Wie vermeide ich eine Wettlaufsituation in meiner Rails App? )
Als nächstes versuchen , es in der DB atomar zu erhöhen:
%Vor% Wenn das funktioniert hat, success == 1
sonst success == 0
. Wenn es funktioniert, verwenden Sie den Zähler, andernfalls versuchen Sie es erneut.
Redis ist für diese Art von Operation besser geeignet und Sie haben bereits einfachen Zugriff darauf über die Redis-Verbindung von Sidekiq.
%Vor%Vielleicht würde so etwas für dich funktionieren.
Tags und Links ruby-on-rails sidekiq