[英]How to lock a critical section in Django?
我找不到一个很好的方法来锁定Django中的一个关键部分。 我可以使用锁或信号量,但python实现仅用于线程,因此如果生产服务器分叉那么那些将不会被尊重。 有没有人知道一种方式(我现在正在考虑posix信号量)以保证跨进程的锁定,或禁止这种方式阻止Django服务器分叉。
如果使用RDBMS,则可以使用其“LOCK”机制。 例如,当一个“SELECT FOR UPDATE”事务锁定一行时,与该行的另一个“SELECT FOR UPDATE”事务必须等待。
# You can use any Python DB API.
[SQL] BEGIN;
[SQL] SELECT col_name FROM table_name where id = 1 FOR UPDATE;
[Process some python code]
[SQL] COMMIT;
使用Django内置的select_for_update函数。
https://docs.djangoproject.com/en/1.8/ref/models/querysets/#select-for-update
来自文档:
返回一个查询集,该查询集将锁定行直到事务结束,在支持的数据库上生成SELECT ... FOR UPDATE SQL语句。
例如:
entries = Entry.objects.select_for_update().filter(author=request.user)
所有匹配的条目将被锁定,直到事务块结束,这意味着将阻止其他事务更改或获取锁定。
你可以使用简单的文件锁定为互斥机制,看我的食谱在这里 。 它不适合所有场景,但是你没有说明为什么要使用这种类型的锁定。
我最终得到了一个我自己涉及文件锁定的解决方案。 如果这里的任何人最终使用它,请记住咨询锁和NFS不能很好地混合,所以请保持本地化。 此外,这是一个阻塞锁,如果你想乱搞循环并不断检查,那么代码中有指令。
import os
import fcntl
class DjangoLock:
def __init__(self, filename):
self.filename = filename
# This will create it if it does not exist already
self.handle = open(filename, 'w')
# flock() is a blocking call unless it is bitwise ORed with LOCK_NB to avoid blocking
# on lock acquisition. This blocking is what I use to provide atomicity across forked
# Django processes since native python locks and semaphores only work at the thread level
def acquire(self):
fcntl.flock(self.handle, fcntl.LOCK_EX)
def release(self):
fcntl.flock(self.handle, fcntl.LOCK_UN)
def __del__(self):
self.handle.close()
Usage:
lock = DJangoLock('/tmp/djangolock.tmp')
lock.acquire()
try:
pass
finally:
lock.release()
我没有写这篇文章,但我发现它面对同样的问题是非常有帮助的:
http://chris-lamb.co.uk/2010/06/07/distributing-locking-python-and-redis/
基本上,您使用Redis服务器来创建公开锁定功能的中央服务器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.