2011-10-24 22 views
1

私が働いていたプロジェクトでは、通常のメモリを保持するには大きすぎるキューが必要です。私はファイル全体を最初の数行(〜100)行で処理し、処理してから、新しい命令を追加して古いキューを削除して更新キューを書き戻す単純なファイルとして実装していました。しかし、キューが大きすぎてこのようなメモリを保持できなくなったので、私は別のものが必要です。誰かが、残りのデータを見ることなくファイルの最初の数行だけを剥がす方法を教えてもらうことができます。私はデータベース(MySQLはおそらくソートされた挿入タイムスタンプで)を使用することを考えていましたが、負荷と帯域幅の理由でそれを行うことを強く望んでいました(いくつかのサーバーはDBから多くのデータを送受信しなければならないでしょう)。私が働いている言語はPHPですが、本当にこの質問は、私が想定しているUNIXファイルに関するものです。どんな助けもありがとう。PHPキューファイルの実装

+3

"*複数のサーバーがすべてDBからデータを送受信する必要があります*" - まさにこのようなデータベースサーバーが設計(最適化)されています。 – qJake

+0

私はデータベースがそれを処理できることは知っていますが、私が心配しているのは、このプロセスを常に実行し、すべてのサーバー間でデータを撮影するという帯域幅です。MySQLの方法は私の最後の手段ですが、すべてのデータを見る必要なしにファイルを更新して最初の数行を削除する方法を知っています。 – hackartist

答えて

1

ファイルの1行目を吸い取るのはかなり簡単です(fopen()の後にfgets()が続きます)。完了したジョブを削除するためにファイルを書き直すと、特に複数の並行サーバーが同じキューファイルで動作している場合は、非常に苦労します。

代わりに、ジョブごとに別々のファイルを使用することもできます。これらのファイルのインクリメンタルIDを生成する並行処理の安全な方法がある場合は、最も古いジョブのIDが最も小さいファイルを選び、新しいジョブごとに新しいIDを生成するだけです。しかし、2つのサーバが同じファイルを同時に取得するためには、いくつかのファイルをロックアウトする必要があります。

+0

私は実際にロックを使用しています - 私が本当に必要とするのは、すでに実行された行の上にファイルの開始を示すポインタを移動する何らかの方法です。 – hackartist

+0

'ftell()'を使ってキューファイル内の 'ここに開始'マーカーの位置を取得し、それを別のファイルに格納することができます。小さな〜10byteファイルのロック/読み取り/更新/書き込み/ロック解除はかなり速く、待ち行列内の関連する場所に簡単にスクロールさせることができます。 –

+0

ok私が探しているもののように聞こえます...キューファイルの実際のサイズは成長し続けますので、ある時点で1つのメモリサイズのチャンクを一度に空にしなければなりません。 – hackartist

0

私は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を使用します。