Реализация файла очереди PHP - PullRequest
1 голос
/ 24 октября 2011

Для проекта, над которым я работал, мне нужна очередь, которая будет слишком большой для хранения в обычной памяти.Я реализовывал его как простой файл, в котором он считывал весь файл, занимал первые несколько (~ 100) строк, обрабатывал их, а затем записывал обратно обновленную очередь с добавлением новых инструкций и удалением старых.Однако, поскольку очередь стала слишком большой, чтобы держать ее в памяти, как это, мне нужно что-то другое.Желательно, чтобы кто-нибудь сказал мне способ отделить только первые несколько строк файла, не просматривая остальные данные.Я думал об использовании базы данных (MySQL, вероятно, с сортированными временными метками вставки), но я бы предпочел сделать это без причины нагрузки и пропускной способности (все серверы должны были бы отправлять и получать много данных из БД).Язык, на котором я работаю, - это PHP, но на самом деле этот вопрос больше относится к Unix-файлам.Любая помощь будет оценена.

Ответы [ 2 ]

1 голос
/ 24 октября 2011

Высасывание первой строки файла довольно тривиально (fopen(), за которым следует fgets()). Переписать файл для удаления выполненных заданий было бы очень больно, особенно если у вас есть несколько одновременных серверов, работающих с одним файлом очереди.

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

0 голосов
/ 22 июня 2017

У меня были те же проблемы, когда я работал на транспорте enqueue / fs .Я не смог изменить небольшую часть в начале файла, не скопировав его в память и не сохранив обратно.Вместо этого, но это возможно сделать с концом файла.Вы можете прочитать часть, а затем обрезать ее.Это не очередь, а стек.Так что, если вы полагаетесь на порядок сообщений, это не будет решением.В моем случае я блокирую файл, когда файл был прочитан из файла, блокировка снята.

Вот как вы можете записывать сообщения в файл очереди:

<?php
$rawMessage = 'this your message to put to the queue as a string';

$queueFile = fopen('/path/to/queue/file', '+a');

// here it may add some spaces so the message length is multiples of modular.
// that make it easier to read messages from a file.

// lock file

$rawMessage = str_repeat(' ', 64 - (strlen($rawMessage) % 64)).$rawMessage;
fwrite($queueFile, $rawMessage);

// release lock

Вот как вы можете читать сообщения из файла очереди:

<?php

$queueFile = fopen('/path/to/queue/file', '+c');

// lock file

$frame = readFrame($file, 1);
ftruncate($file, fstat($file)['size'] - strlen($frame));
rewind($file);
$rawMessage = substr(trim($frame), 1);

// release lock


function readFrame($file, $frameNumber)
{
    $frameSize = 64;
    $offset = $frameNumber * $frameSize;
    fseek($file, -$offset, SEEK_END);
    $frame = fread($file, $frameSize);
    if ('' == $frame) {
        return '';
    }
    if (false !== strpos($frame, '|{')) {
        return $frame;
    }
    return readFrame($file, $frameNumber + 1).$frame;
}

ДляБлокировка Я бы предложил использовать Symfony LockHandler или просто взять enqueue / fs.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...