Мне нужна простая таблица, которая действует как очередь. Мое ограничение сервера MySQL – я не могу использовать таблицы InnoDB, только MyISAM.
Клиенты / работники будут работать в одно и то же время, и им нужно будет получать разные задания каждый раз.
Моя идея – сделать следующее (псевдокод):
$job <- SELECT * FROM queue ORDER BY last_pop ASC LIMIT 1; UPDATE queue SET last_pop WHERE id = $job->id return $job
Я попробовал блокировку таблицы и «GET_LOCK», но ничего не происходит, рабочие иногда получают одинаковые задания.
Вам нужно повернуть свой заказ, чтобы не было временного окна.
Потребительский POP (каждый потребитель имеет уникальный $ consumer_id)
Update queue set last_pop = '$consumer_id' where last_pop is null order by id limit 1; $job = Select * from queue where last_pop = '$consumer_id' order by id desc limit 1;
Поставщик PUSH
insert into queue (id, last_pop, ...) values (NULL, NULL, ...);
Очередь упорядочивается во времени столбцом id и назначается POP на user_id.
Просто для информации есть еще один вариант, который использует Gearman вместо таблицы, чтобы сделать очередь: Rasmus Lerdorf написал очень хорошую статью об этом .
Олег,
Решение правильное. $consumer_id
должен быть уникальным идентификатором для процессора. Например, если у вас было несколько заданий cron на одной машине, вы могли бы использовать их pid
в качестве consumer ID
.
UPDATE является атомарным, поэтому он отмечает ровно одну строку в очереди как потребляемую вашим ID
.
Для некоторых приложений у меня также есть поле состояния для завершенного , так что если last_pop's user_id установлен, но готовый флаг не установлен, а задание старше X, его можно пометить для перезапуска.