Redis — возможность потери данных при обрезке очереди

У меня есть своего рода установка производитель-потребитель, в которой производители (несколько производителей в разных потоках) помещают данные в очередь Redis, а потребитель (один потребитель в одном потоке) отслеживает эту очередь. Когда длина очереди достигает, скажем, >= 10000 элементов, потребитель должен извлечь первые 10000 элементов из очереди, удалить их из очереди и выполнить над ней какие-то вычисления.

Используя клиент redis-py, я использую следующий код для извлечения первых 10000 элементов и их удаления:

logs = REDIS_CLIENT.lrange(task_queue, 0, 9999)
REDIS_CLIENT.ltrim(task_queue, start=10000, end=REDIS_CLIENT.llen(task_queue))

(Документация для lrange и ltrim)

Мой вопрос: есть ли здесь возможность потери данных? Например, возможно ли, чтобы задачи ставились в очередь в период между вызовом функции ltrim() и фактическим обрезанием очереди (в этом случае самые новые журналы будут потеряны, поскольку значение end будет более старой длиной)? Или блокировка помещается в очередь до завершения операции ltrim?


person Krithik Vaidya    schedule 25.05.2020    source источник


Ответы (1)


ДА, вы можете потерять данные, так как между ltrim и llen есть временное окно.

Чтобы закрыть это временное окно, вы можете установить -1 в качестве конечного смещения:

REDIS_CLIENT.ltrim(task_queue, start=10000, end=-1)

-1 означает конец списка, и вам не нужно явно указывать конечное смещение.

person for_stack    schedule 25.05.2020
comment
Верно. Кроме того, когда функция ltrim() начинает выполнение, ставится ли какая-то блокировка в очередь до тех пор, пока она не завершит свое выполнение? - person Krithik Vaidya; 25.05.2020
comment
Явной блокировки нет. На самом деле Redis — однопоточный, и все команды гарантированно атомарны. - person for_stack; 25.05.2020