PHP队列文件实现

PHP队列文件实现,php,file,unix,memory,queue,Php,File,Unix,Memory,Queue,对于我正在进行的一个项目,我需要一个队列,该队列太大,无法保存在正常内存中。我一直将它实现为一个简单的文件,在这个文件中,它将读取整个文件,读取前几行(~100行),处理它们,然后写回更新的队列,添加新的指令,删除旧的指令。然而,由于队列变得太大,无法像这样保存在内存中,我需要一些不同的东西。最好有人能告诉我一种方法,只剥离文件的前几行,而不必查看其余的数据。我曾考虑过使用数据库(MySQL可能带有排序的插入时间戳),但出于负载和带宽原因,我更愿意不使用数据库(几个服务器都必须从数据库发送和接收

对于我正在进行的一个项目,我需要一个队列,该队列太大,无法保存在正常内存中。我一直将它实现为一个简单的文件,在这个文件中,它将读取整个文件,读取前几行(~100行),处理它们,然后写回更新的队列,添加新的指令,删除旧的指令。然而,由于队列变得太大,无法像这样保存在内存中,我需要一些不同的东西。最好有人能告诉我一种方法,只剥离文件的前几行,而不必查看其余的数据。我曾考虑过使用数据库(MySQL可能带有排序的插入时间戳),但出于负载和带宽原因,我更愿意不使用数据库(几个服务器都必须从数据库发送和接收大量数据)。我使用的语言是PHP,但我想这个问题更多的是关于unix文件的。任何帮助都将不胜感激

抽出文件的第一行非常简单(
fopen()
后面跟着一个
fgets()
)。重新写入文件以删除已完成的作业将非常痛苦,特别是如果有多个并发服务器在同一队列文件下工作


一种替代方法是为每个作业使用单独的文件。如果您有一些并发安全的方法来为这些文件生成递增ID,那么只需为最早的作业选择ID最低的文件,并为每个新作业生成一个新ID。不过,为了让两台以上的服务器同时抓取同一个文件,您必须找到一些文件锁定方法。

我在处理传输时遇到了同样的问题。我未能修改文件的一小部分,而没有将其复制到内存并保存回去。相反,但在文件末尾可以这样做。您可以读取一部分,然后将其截断。这实际上不是一个队列,而是一个堆栈。因此,如果您依赖于消息排序,这将不是一个解决方案。在我的例子中,我锁定了文件,当从文件中读取文件时,锁被释放

以下是将消息写入队列文件的方式:

<?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;
}

“几个服务器都必须从数据库发送和接收大量数据”-这正是数据库服务器的设计(和优化)我知道数据库可以处理它,但我更关心的是这个过程持续运行和在我所有服务器之间拍摄数据所涉及的带宽。。。MySQL方式是我最后的选择,但如果有人知道一种更新文件的方法来删除前几行,而不必查看所有数据,我真的更喜欢这种方法。我实际上是在使用锁定——我真正需要的是某种方法来移动指针,它表示文件的开始,而不是已经执行的行。你呢可以使用
ftell()。锁定/读取/更新/写入/解锁一个小~10字节的文件会相当快,让您可以轻松地直接滚动到队列中的相关位置。好的,听起来更像我要找的。。。队列文件的实际大小将继续增长,因此我必须在某个时候一次清空一个内存大小的块。。。