Senior
Kaip sinchronizuoti darbininkus per Redis, kad du darbininkai vienu metu neapdorotų to paties objekto?
sobes.tech AI
Atsakymas iš 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.