如何在Django中锁定关键区?

23 投票
6 回答
18401 浏览
提问于 2025-04-15 12:53

我找不到一个好的方法来在Django中锁定一个关键部分。虽然我可以使用锁或信号量,但Python的实现只适用于线程,所以如果生产服务器进行分叉(也就是创建多个进程),这些锁就没用了。有没有人知道有什么方法(我现在在考虑posix信号量)可以确保在多个进程之间保持锁定,或者如果没有这种方法,有没有办法阻止Django服务器进行分叉。

6 个回答

16

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

所有匹配的条目在事务块结束之前都会被锁定,这意味着其他事务无法对它们进行修改或获取锁。

17

如果你使用的是关系型数据库管理系统(RDBMS),你可以利用它的“锁定”机制。举个例子,当一个“选择并更新”(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;
9

当你的应用突然需要在多个服务上运行时,就需要一个分布式锁管理器。我为这个目的写了elock。还有一些更大的工具,而其他人则选择忽略所有建议,使用memcached来做同样的事情。

请不要把memcached用作比轻量级建议锁更复杂的用途。它的设计初衷就是用来忘记东西的。

在做网页应用时,我喜欢假装文件系统不存在。这样可以更好地扩展。

撰写回答