Ich endete mit RabbitMQ als eine Möglichkeit, verteilte Sperren zu erstellen. Details dazu finden Sie auf RabbitMQ's Blog: https://www.rabbitmq.com/blog/2014/02/19/distributed-semaphores-with-rabbitmq/.
Kurz gesagt, Sie erstellen eine RabbitMQ-Warteschlange für die Sperre und senden eine einzelne Nachricht an sie. Um die Sperre zu erhalten, führen Sie eine basic_get
(nicht blockierend) oder basic_consume
(blockierend) in der Warteschlange aus. Dadurch wird die Nachricht aus der Warteschlange entfernt und verhindert, dass andere Threads die Sperre erhalten. Sobald Ihre Arbeit beendet ist, wird RabbitMQ durch das Senden einer negativen Bestätigung aufgefordert, die Nachricht erneut zu senden, damit der nächste Thread fortgesetzt werden kann.
Leider sind Reentrant-Sperren nicht zulässig.
Der oben erwähnte Link gibt Java-Code für die Vorgehensweise. Herauszufinden, wie man das in Python/Pika übersetzt, war nervig genug, dass ich dachte, ich sollte hier einen Beispielcode posten.
Um die Sperre zu produzieren:
import pika
with pika.BlockingConnection(pika.ConnectionParameters('localhost')) as connection:
channel = connection.channel()
channel.queue_declare(queue="LockQueue")
channel.basic_publish(exchange='', routing_key='LockQueue', body='Lock')
channel.close()
das Schloss Erwerb:
import pika
import time
def callback(ch, method, properties, body):
print("Got lock")
for i in range(5, 0, -1):
print("Tick {}".format(i))
time.sleep(1)
print("Releasing lock")
ch.basic_nack(delivery_tag=method.delivery_tag)
ch.close() # Close the channel to continue on with normal processing. Without this, `callback` will continue to request the lock.
with pika.BlockingConnection(pika.ConnectionParameters('localhost')) as connection:
channel = connection.channel()
channel.queue_declare(queue='LockQueue')
channel.basic_qos(prefetch_count=1)
channel.basic_consume(callback, queue='LockQueue')
print("Waiting for lock")
channel.start_consuming()
print("Task completed")
Dies ist keine direkte Antwort, aber es sei denn, Sie * hart brauchen * mit starken Sequentialität Verriegelung, könnten Sie suchen möchten bei einem Nachrichtensystem wie [0MQ] (http://zeromq.org/). Ein tolles Nachrichtensystem, das auf fast allem läuft und Bindungen für fast jede Sprache hat. –
+1 für * 0MQ *, um zwischen Prozessen in verschiedenen Sprachen mit einer großen Latenz zu kommunizieren. Ich bin nicht wirklich an Sellerie gewöhnt und was es vielleicht schon beinhaltet (oder einschränkt), aber vielleicht könntest du auch in Erwägung ziehen, ['redis'] (http://redis.io/topics/distlock) zu verwenden, da gibt es bereits einige Python-Bindungen um diese Art von Funktionalität (https://pypi.python.org/pypi/python-re- dislock, https://github.com/glasslion/redlock, https://github.com/SPSCommerce/redlock-py, etc.) – mgc
Sie erkennen, dass diese Anforderung "ohne einen gemeinsamen Vorfahrenprozess" bedeutet, dass Sie 'Multiprocessing' nicht verwenden können, oder? – Louis