Как спроектировать бэкэнд для помещения запросов в очередь?

0

Я хочу создать такую систему, чтобы пользователи могли отправлять файлы. После отправки файла я запустил некоторые скрипты с файлами. Я хочу запустить эти файлы в порядке, поэтому я хочу поддерживать очередь запросов. Как я могу это сделать с помощью php? Есть ли для этого библиотека с открытым исходным кодом?

Благодарю!

  • 0
    На самом деле вам нужна только одна таблица с двумя столбцами FILE, QUEUE_ORDER
  • 0
    Спасибо за вашу помощь. Как мне запустить сценарии по порядку?
Показать ещё 1 комментарий
Теги:
server
backend

3 ответа

-1

Третья библиотека? Слишком просто нужна целая библиотека. Вы можете использовать Redis (см. Ответ AlanChavez), если вы хотите тратить время и ресурсы, а затем должны быть обеспокоены сбором мусора, когда реальное решение заключается не в том, чтобы вначале вносить мусор в микс.

Ваша очередь - текстовый файл. Когда файл загружается, имя файла добавляется в очередь.

$q= fopen('queue.txt','a');

'a' режим 'a'. Он автоматически перемещает указатель записи в конец файла для добавления записей. Но причина в том, что это важно, потому что, если файл не существует, создается новый.

fwrite($q,"$filename\n");
fclose($q);

Если одновременный файл append записывает в этот файл, OS может разрешить конфликт без ошибок. Нет необходимости в блокировке файлов, совместной многозадачности или транзакционной обработке.

Когда ваш скрипт, который обрабатывает очередь, начинает запускать, он переименовывает прямую очередь в рабочую очередь.

if(!file_exists('q.txt')){
  if(!file_exists('queue.txt')){exit;}
  rename('queue.txt','q.txt');
  $q = fopen('q.txt','r');
  while (($filename = fgets($q, 4096)) !== false) {
    process($filename);
  }
  fclose($q);
  unlink('q.txt');
}
else{
  echo 'Houston, we have a problem';
}

Теперь вы видите, почему важен режим 'a'. Мы переименовываем очередь, и когда происходит следующая загрузка, автоматически создается файл queue.txt.

Если файл записывается, поскольку он переименовывается, ОС будет сортировать его без ошибок. Переименование происходит настолько быстро, что вероятность одновременной записи астрономически мала. И это основная функция ОС, чтобы разобраться в конкуренции файловой системы. Нет необходимости в блокировке файлов, совместной многозадачности или транзакционной обработке.

Это пуленепробиваемый метод, который я использую в течение многих лет.

Замените цитату Apollo 13 процедурой восстановления ошибок. Если q.txt существует, предыдущая обработка не завершилась успешно.

Это было слишком легко.

Потому что это так просто, и у нас много памяти, потому что мы настолько эффективны: пусть будет весело.

Посмотрим, будет ли запись в очередь быстрее, чем AlanChavez "супер быстрый" Redis с его единственным двузначным миллисекундным ответом.

Время в секундах, чтобы добавить имя файла в очередь = 0.000014537 или 14.5μS. Чуть лучше, чем Redis "супер быстрый" 10-99 мс Время отклика, как минимум, 100 000%.

  • 0
    -1 Этот ответ довольно плохой. Вы предлагаете использовать файлы, что произойдет, если возникнет конфликт? Тогда вам нужно будет ввести блокировки в уравнение, чтобы это работало согласованно. Я настоятельно рекомендую вам прочитать немного больше о Redis, так как он обычно используется в качестве очереди. Это не излишне, это легко, и это атомно.
  • 0
    Я не говорю, что с Redis что-то не так. Я просто не большой поклонник сторонних дополнений. Ничто не бесплатно. Сторонние продукты могут помочь вам избежать кривой обучения. Но где-то вдоль линии они будут вам стоить, когда это не будет делать то, что вы ожидаете, и вы застряли без решения или обходного пути. Я проверил Redis, потому что ты рекомендовал это. То, что они предлагают, либо мне не нужно, либо я уже написал свой собственный распорядок. Я занимаюсь кодированием с 1979 года, и в течение 15 лет я в среднем работала более 15 часов в день. Есть не так много процедур, которые я еще не написал.
-1

Я бы использовал Редис. Redis - супербыстрое хранилище ключей; обычно его время отклика - это двузначные микросекунды. (10 - 99 мкс)

Операции Redis являются атомарными (транзакции либо происходят, либо нет), и вы можете постоянно работать, не используя cron.

Чтобы использовать Redis с PHP, вы можете использовать Predis.

После того, как redis установлен, и Predis настроен для работы с вашим скриптом, при загрузке файла я бы сделал что-то вроде этого:

// 'hostname' and 'port' is the hostname and the port
// where Redis is installed and listening to.  
$client = new Predis\Client('tcp://hostname:port');
// assuming the path to the file is stored in $pathToFile
$client->lpush('queue:files', $pathToFile);

то скрипт, который должен работать с файлами, просто нужно сделать что-то вроде:

$client = new Predis\Client('tcp://hostname:port');
// assuming the path to the file is stored in $pathToFile
while(true){
    $pathToFile = $client->rpop('queue:files');
    if(!$pathToFile) {
        // list is empty, so move on. 
        continue;
    }
    // there was something in the list, do whatever you need to do with it.
    // if there an exception or an error, you can always use break; or exit; to terminate the loop.
}

Учитывайте, что PHP имеет тенденцию использовать много памяти, поэтому я бы либо явно собирал мусор (через gc_enable() и gc_collect_cycles() и unset() переменные, как вы идете).

Кроме того, вы можете использовать программное обеспечение, такое как supervisord чтобы запустить этот скрипт один раз, и как только он закончится, запустите его снова.

В общем, я бы держался подальше от использования базы данных и cron для реализации очередей. Это может привести к серьезным проблемам.

Предположим, например, что вы используете таблицу в качестве очереди.

В первом запуске ваш скрипт вытаскивает задание из базы данных и начинает делать что-то.

Затем по какой-то причине ваш сценарий занимает больше времени, и работа cron снова запускается, и теперь у вас есть 2 скрипта, работающих с одним и тем же файлом. Это может либо не иметь последствий, либо может иметь серьезные последствия. Это зависит от того, что делает ваше приложение.

Поэтому, если вы не работаете с очень маленьким набором данных, и вы точно знаете, что ваш cronjob закончит до того, как будет запущен предыдущий скрипт, и не будет никаких столкновений, тогда вам все будет в порядке. В противном случае, избегайте этого подхода.

  • 0
    Есть вещи о мусоре? Хотя вы слишком усложнили вопрос, вы также создали бесконечный цикл. Вы можете заменить continue; с break; , «Примите во внимание, что PHP имеет тенденцию использовать много памяти»? Ну, может быть, если вы собираетесь внести ненужный мусор в смесь. Вы думаете, 10-99 мс "супер быстро"? «Это может привести к серьезным проблемам». ??? Если вы пишете плохой код. Я собираюсь догадаться, что вы - тот, за кого проголосовали @JohnnyFaldo. Его -2 очка пришли примерно 20 февраля в 17:07? Его ответ лучше твоего. Это ужасный ответ. Смотри мой ответ
  • 0
    @ Неправильно понял, что вы ответили хуже, чем Джонни. Ответ Джонни Фальдо наивен, а ваш просто плох. Вы рекомендуете использовать файлы, использование файлов определенно хуже, чем явный вызов сборщика мусора, и хуже, чем использование баз данных. Что произойдет, когда 2 процесса PHP попытаются открыть один и тот же файл? Вам нужно будет создать блокировку для файла. Это приведет к проблемам параллелизма.
Показать ещё 3 комментария
-2

Я бы использовал базу данных.

  1. Когда пользователь отправляет файл, он добавляет ссылку на его местоположение в файловой системе в базу данных.
  2. У вас работает cron, который проверяет наличие новых представлений и обрабатывает их по порядку, когда это делается, и отмечает, что он обрабатывается в базе данных.
  • 0
    что такое cron? Большое спасибо.
  • 0
    Крон - это запланированное задание.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню