Senior
Вазифа дар PostgreSQL: чанд коргар вазифаҳоро аз рӯйхати маълумот мехонанд ва коди промо тайёр мекунанд. Чӣ тавр аз такроршавии корҳо пешгирӣ кардан мумкин аст?
sobes.tech AI
Ҷавоб аз AI
Чтобы несколько воркеров безопасно читать задачи из таблицы и генерировать промокоды без дублирования, нужно обеспечить, что каждая задача будет обработана ровно одним воркером. В PostgreSQL для этого часто используют транзакции с блокировкой строк.
Основной подход — использовать SELECT ... FOR UPDATE SKIP LOCKED:
- Воркеры выбирают задачи, которые ещё не обработаны, блокируя их для себя:
BEGIN;
SELECT * FROM tasks
WHERE status = 'pending'
FOR UPDATE SKIP LOCKED
LIMIT 1;
-
После выбора задачи воркер помечает её как "в обработке" или сразу генерирует промокод и обновляет статус.
-
Коммит транзакции.
SKIP LOCKED позволяет другим воркерам пропускать уже заблокированные задачи, предотвращая конкуренцию и дублирование.
Пример на Go с использованием базы:
func worker(db *sql.DB) {
for {
tx, _ := db.Begin()
row := tx.QueryRow(`
SELECT id FROM tasks
WHERE status = 'pending'
FOR UPDATE SKIP LOCKED
LIMIT 1
`)
var taskID int
err := row.Scan(&taskID)
if err == sql.ErrNoRows {
tx.Rollback()
break // Нет задач
}
// Генерируем промокод и обновляем задачу
promoCode := generatePromoCode()
_, err = tx.Exec(`
UPDATE tasks SET status = 'done', promo_code = $1 WHERE id = $2
`, promoCode, taskID)
if err != nil {
tx.Rollback()
continue
}
tx.Commit()
}
}
Таким образом, каждый воркер получает уникальную задачу без пересечений.