Sobes.tech
Назад к вопросам
Senior
4

Как синхронизировать воркеры через Redis, чтобы два воркера не обрабатывали один объект одновременно?

Компании, где спрашивали
Не указано

Ответ от нейросети

sobes.tech AI

Для синхронизации воркеров через Redis и предотвращения одновременной обработки одного объекта можно использовать механизм распределённых блокировок (distributed locks). Один из распространённых подходов — использовать команду SET с параметрами NX (установить, если ключ не существует) и PX (время жизни ключа) для создания блокировки.

Пример на Go с использованием библиотеки go-redis:

import (
    "context"
    "time"
    "github.com/go-redis/redis/v8"
)

func acquireLock(ctx context.Context, rdb *redis.Client, key string, ttl time.Duration) (bool, error) {
    // Попытка установить ключ с уникальным значением и временем жизни
    ok, err := rdb.SetNX(ctx, key, "locked", ttl).Result()
    return ok, err
}

func releaseLock(ctx context.Context, rdb *redis.Client, key string) error {
    return rdb.Del(ctx, key).Err()
}

// В воркере:
ctx := context.Background()
lockKey := "lock:object_id"
lockTTL := 30 * time.Second

locked, err := acquireLock(ctx, rdb, lockKey, lockTTL)
if err != nil {
    // обработка ошибки
}
if !locked {
    // другой воркер уже обрабатывает объект
    return
}

// Обработка объекта

// После обработки снимаем блокировку
_ = releaseLock(ctx, rdb, lockKey)

Важно, чтобы время жизни блокировки (TTL) было достаточно большим, чтобы покрыть время обработки, но не слишком большим, чтобы избежать долгой блокировки при сбое воркера. Для более надёжных решений можно использовать алгоритм Redlock.