Как использовать Redis Lock для предотвращения асинхронного задания в Python - PullRequest
0 голосов
/ 21 февраля 2020

В настоящее время я использую Redis для выполнения QueueJob (Очередь приоритетов) в коде Python (Odoo), и я сталкиваюсь с асинхронной проблемой (Там будут некоторые задания, выполняющие ту же задачу - обновить / удалить в той же записи на в то же время).

Как я прочитал из документации Redis, мне нужно реализовать LOCK для предотвращения асинхронной проблемы. Однако я не понимаю, почему блокировка не работает так, как я ожидаю.

Ниже приведен мой код:

import redis
import redis_lock #(python-redis-lock lib)

class PriorityQueue(object):
    def __init__(self, queue_name):
        ...
        self.redis = redis.StrictRedis(...)
        self.redis_lock = redis_lock.Lock(self.redis, queue_name)


    def first(self):
        if self.redis_lock.acquire(blocking=False):
            print("Perform task")
            job = self.redis.zrevrange(self.queue_name, 0, 0)[0]
            job_data = json.loads(job.decode("utf-8"))
            return ChannelJob(job_data)
        else:
            print("Lock is used by other job")

    def pop(self):
        job = self.redis.zpopmax(self.queue_name, count=1)
        job_data = json.loads(job.decode("utf-8"))
        return ChannelJob(job_data)

redis_lock.acquire () всегда возвращает False, пожалуйста, помогите мне решить эту проблему.

1 Ответ

0 голосов
/ 21 февраля 2020

Вы забыли снять блокировку.

redis_lock.acquire () всегда возвращает False

На самом деле это не так. Впервые хотя бы одно задание получит блокировку. И когда вы забудете снять блокировку, блокировка сохранится . И любой последующий запрос не удался. Для решения этой проблемы вам необходимо снять замки self.redis_lock.release(). Вот пример:

def first(self):
        if self.redis_lock.acquire(blocking=False):
            print("Perform task")
            job = self.redis.zrevrange(self.queue_name, 0, 0)[0]
            job_data = json.loads(job.decode("utf-8"))

            // do the job ; you can also release the lock here.
            job_result = ChannelJob(job_data)
            // release the lock, so other can acquire it.
            self.redis_lock.release()
            return job_result 
        else:
            print("Lock is used by other job")

Чтобы узнать больше о замках: Пожалуйста, перейдите по этой ссылке

...