Как заблокировать критический раздел в Django? - PullRequest
19 голосов
/ 14 июля 2009

Я не могу найти хороший чистый способ заблокировать критическую секцию в Django. Я мог бы использовать блокировку или семафор, но реализация Python предназначена только для потоков, поэтому, если рабочий сервер разветвится, они не будут соблюдаться. Кто-нибудь знает способ (сейчас я думаю, что семафоры posix), чтобы гарантировать блокировку между процессами или запретить способ запретить разветвление сервера Django.

Ответы [ 6 ]

16 голосов
/ 30 ноября 2010

Если вы используете 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;
13 голосов
/ 02 ноября 2015

Используйте встроенную функцию select_for_update в Django.
https://docs.djangoproject.com/en/1.8/ref/models/querysets/#select-for-update
Из документов:
Возвращает набор запросов, который блокирует строки до конца транзакции, генерируя инструкцию SQL SELECT ... FOR UPDATE для поддерживаемых баз данных.

Например:

entries = Entry.objects.select_for_update().filter(author=request.user)

Все совпадающие записи будут заблокированы до конца блока транзакции, что означает, что другие транзакции не смогут изменить или получить блокировки для них.

9 голосов
/ 20 июля 2009

Вам нужен распределенный диспетчер блокировок в точке, где ваше приложение внезапно должно работать более чем на одном сервисе. Я написал elock для этой цели. Есть больших , а другие решили игнорировать каждое предложение и сделали то же самое с memcached.

Пожалуйста, не используйте memcached для чего-то большего, чем легкая консультативная блокировка. Он предназначен, чтобы забыть вещи.

Мне нравится делать вид, что файловых систем не существует, когда я создаю веб-приложения. Делает масштаб лучше.

5 голосов
/ 14 июля 2009

Вы можете использовать простую блокировку файлов как механизм взаимного исключения, см. Мой рецепт здесь . Это не подходит для всех сценариев, но вы мало что сказали о том, почему вы хотите использовать этот тип блокировки.

3 голосов
/ 20 июля 2009

Я закончил тем, что нашел решение, основанное на блокировке файлов. Если кто-то здесь использует его, помните, что консультативные блокировки и 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()
2 голосов
/ 24 февраля 2011

Я не писал эту статью, но нашел ее чрезвычайно полезной, столкнувшись с такой же проблемой:

http://chris -lamb.co.uk / 2010/06/07 / распределяя-запорно-питон-и-Redis /

В основном вы используете сервер Redis для создания центрального сервера, который предоставляет функции блокировки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...