Sobes.tech
Back to questions
Senior
7

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

Companies where asked
Не указано

Answer from AI

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.