如何锁定Django中的关键部分?

时间:2009-07-14 02:44:27

标签: python django

我找不到一个很好的方法来锁定Django中的一个关键部分。我可以使用锁或信号量,但python实现仅用于线程,因此如果生产服务器分叉那么那些将不会被尊重。有没有人知道一种方式(我现在正在考虑posix信号量)以保证跨进程的锁定,或者禁止这种方式阻止Django服务器分叉。

6 个答案:

答案 0 :(得分:16)

如果使用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;

答案 1 :(得分:13)

使用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)

所有匹配的条目将被锁定,直到事务块结束,这意味着将阻止其他事务更改或获取锁定。

答案 2 :(得分:9)

在您的应用突然需要在多个服务上运行时,您需要一个分布式锁管理器。我为此目的写了elock。有bigger ones和其他人选择忽略每个建议,并使用memcached完成相同的操作。

请不要将memcached用于轻量级咨询锁定。它旨在忘记一些东西。

我喜欢假装在制作网络应用时不存在文件系统。使规模更好。

答案 3 :(得分:5)

您可以使用简单文件锁定作为互斥机制,请参阅我的食谱here。它不适合所有场景,但是你没有说明为什么要使用这种类型的锁定。

答案 4 :(得分:3)

我最终得到了一个我自己涉及文件锁定的解决方案。如果这里的任何人最终使用它,请记住咨询锁和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()

答案 5 :(得分:2)

我没有写这篇文章,但我发现面对同样的问题非常有帮助:

http://chris-lamb.co.uk/2010/06/07/distributing-locking-python-and-redis/

基本上,您使用Redis服务器创建一个公开锁定功能的中央服务器。