Senior
Jak synchronizować pracowników przez Redis, aby dwóch pracowników nie przetwarzało jednocześnie tego samego obiektu?
sobes.tech AI
Odpowiedź od 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.