跨多个独立进程使用Python rlock
我正在做一个Django项目,它使用芹菜来安排一些长期任务。Django和Cellery都在完全独立的进程中运行,需要一种方法来协调对数据库的访问。我想使用Python的跨多个独立进程使用Python rlock,python,django,celery,python-multiprocessing,Python,Django,Celery,Python Multiprocessing,我正在做一个Django项目,它使用芹菜来安排一些长期任务。Django和Cellery都在完全独立的进程中运行,需要一种方法来协调对数据库的访问。我想使用Python的multiprocessing.RLock类(或等效类),因为我需要锁是可重入的 我的问题是,如何为单独的进程提供对RLock的访问 我发现的两个最好的解决方案(和)仅限于基于Unix的系统,我们希望避免将自己局限于此 有没有一种跨平台的方法可以在没有共同祖先进程的情况下在进程之间共享锁?我最终使用RabbitMQ作为一种创建分
multiprocessing.RLock
类(或等效类),因为我需要锁是可重入的
我的问题是,如何为单独的进程提供对RLock的访问
我发现的两个最好的解决方案(和)仅限于基于Unix的系统,我们希望避免将自己局限于此
有没有一种跨平台的方法可以在没有共同祖先进程的情况下在进程之间共享锁?我最终使用RabbitMQ作为一种创建分布式锁的方法。有关如何执行此操作的详细信息,请访问RabbitMQ的博客: 简而言之,您为锁创建一个RabbitMQ队列并向其发送一条消息。要获取锁,请在队列上运行
basic\u get
(非阻塞)或basic\u consume
(阻塞)。这将从队列中删除消息,防止其他线程获取锁。一旦您的工作完成,发送否定的ack将导致RabbitMQ重新获取消息,从而允许下一个线程继续
不幸的是,这不允许重入锁
上面引用的链接给出了如何执行此操作的Java代码。弄明白如何将其翻译成Python/Pika已经够烦人的了,我想我应该在这里发布一些示例代码
要生成锁,请执行以下操作:
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()
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")
获取锁:
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()
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")
这不是一个直接的答案,但除非您需要具有强顺序性的硬锁定,否则您可能希望查看消息传递系统,例如。这是一个很棒的消息传递系统,几乎可以在任何东西上运行,并且几乎可以为任何语言提供绑定。+1表示0MQ,以便在以各种语言编写的进程之间进行通信,具有很高的延迟。我不太习惯芹菜和它可能已经涉及(或约束),但也许你也可以考虑使用,已经有一些Python绑定围绕这类功能(,等等),你确实意识到这个要求“没有共同祖先过程”意味着你不能使用<代码>多重处理< /代码>,是吗?彼得,mgc,谢谢你的建议!我需要仔细看看这些是否有效@路易斯,是的。这是问题的关键。我正在寻找一种不用父进程就能获得RLock行为的方法。按照mgc的建议使用redis锁,或者也可以使用django缓存。