프로젝트에서 내가 대기중인 큐가 너무 커서 정상 메모리를 유지할 수 없습니다. 나는 전체 파일을 처음 몇 줄 (~ 100) 줄을 읽고, 처리 한 다음, 새 지침을 추가하고 오래된 명령을 제거하여 업데이트 된 큐를 다시 작성하는 간단한 파일로 구현했습니다. 그러나 큐가 너무 커서이 메모리를 유지할 수 없기 때문에 나는 다른 것을 필요로합니다. 가급적이면 누군가가 나머지 데이터를 보지 않고도 파일의 처음 몇 줄만 떼어내는 방법을 말해 줄 수 있습니다. 나는 데이터베이스 (정렬 된 타임 스탬프를 가진 MySQL)를 사용하는 것에 대해 생각해 봤지만, 부하 및 대역폭의 이유없이 (여러 서버가 모두 DB에서 많은 양의 데이터를 전송하고 수신해야 함)이를 수행하는 것을 선호했다. 제가 일하고있는 언어는 PHP지만, 정말로이 질문은 유닉스 파일에 대한 것입니다. 어떤 도움을 주시면 감사하겠습니다.PHP 큐 파일 구현
답변
파일의 첫 번째 줄을 빠져 나오기는 매우 쉽습니다 (fopen()
다음에 fgets()
이옵니다). 완료된 작업을 제거하기 위해 파일을 다시 쓰는 것은 매우 고통 스럽습니다. 특히 여러 개의 동시 서버가 동일한 대기열 파일에서 작동하는 경우에는 더욱 그렇습니다.
한 가지 대안은 각 작업에 대해 별도의 파일을 사용하는 것입니다. 이러한 파일에 대해 증가하는 ID를 생성하는 동시성에 안전한 몇 가지 방법이있는 경우 가장 오래된 작업에 대해 가장 낮은 ID를 가진 파일을 선택하고 각각의 새 작업에 대해 새 ID를 생성하는 것은 간단합니다. 그러나 두 개의 서버가 같은 파일을 동시에 가져 오게하려면 파일 잠금을 알아 내야합니다.
저는 실제로 잠금을 사용하고 있습니다. - 실제로 필요한 것은 이미 실행 된 행 위로 파일의 시작을 나타내는 포인터를 이동시키는 방법입니다. – hackartist
당신은'ftell()'을 사용하여 큐 파일에서 '여기에서 시작'마커의 위치를 얻고 그것을 별도의 파일에 저장할 수 있습니다. 작은 ~ 10byte 파일의 잠금/읽기/업데이트/쓰기/잠금 해제는 매우 빠르며 대기열의 관련 위치로 쉽게 스크롤 할 수 있습니다. –
좋아, 내가 찾고있는 것보다 소리가 난다. 대기열 파일의 실제 크기가 계속 커지기 때문에 한 번에 하나의 메모리 크기의 청크를 비워야한다. – hackartist
enqueue/fs 전송 중에 작업하는 동안 동일한 문제가있었습니다. 파일을 구걸 할 때 메모리에 복사하고 다시 저장하지 않고 작은 부분을 수정하지 못했습니다. 대신 파일의 끝 부분에서이를 수행 할 수 있습니다. 부분을 읽고 나서자를 수 있습니다. 그것은 실제로 대기열이 아니라 스택입니다. 따라서 메시지 순서에 의존한다면 이는 해결책이 아닙니다. 필자의 경우 파일에서 파일을 읽을 때 파일을 잠그면 잠금이 해제됩니다.
<?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;
}
내가 사용하는 것이 좋습니다하려는 잠금의 경우 :
<?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
이 당신이 큐 파일에서 메시지를 읽을 수있는 방법입니다 :
이
는 큐 파일에 메시지를 쓸 수있는 방법입니다 Symfony LockHandler 또는 간단하게 enqueue/fs를 가져옵니다.- 1. 큐 구현
- 2. 요청 큐 구현
- 3. FIFO 기반 큐 구현?
- 4. 스레드 안전 큐 구현
- 5. 힙을 사용하여 큐 구현
- 6. Java의 큐 구현
- 7. 분산 큐 구현
- 8. 하스켈에서 블로킹 큐 구현
- 9. 스레드 구현 당 큐
- 10. WCF 서비스의 큐 구현
- 11. go에서의 우선 순위 큐 구현
- 12. Java에서 비동기 메시지 큐 구현
- 13. 메시지 큐 솔루션 구현 방법
- 14. C의 우선 순위 큐 구현
- 15. 우선 순위 큐 힙 구현
- 16. CRC64 파일 체크섬 PHP 구현
- 17. Java : 자신의 메시지 큐 구현 (스레드 세이프)
- 18. 여러 redis 마스터 서버에서 큐 구현
- 19. 원형 배열을 사용하여 양단 큐 구현?
- 20. 정렬 된 목록으로 우선 순위 큐 구현
- 21. 큐 충돌
- 22. Yii PHP 프레임 워크 - 구현
- 23. PHP, PCNTL 및 공유 메모리의 큐
- 24. 데이터베이스 큐 및 큐 처리
- 25. 파이썬 : 파일 기반 스레드 안전 큐
- 26. Java에서의 빠른 이중 값 우선 순위 큐 구현
- 27. 스칼라에서 배열을 사용하는 큐 구현 방법을 큐에 넣기
- 28. 리눅스에서 일반 파일을 사용하여 지속성 메시지 큐 구현
- 29. posix 메시지 큐 구현 중 오류 - "함수가 구현되지 않았습니다."
- 30. C++에서 반복 될 수있는 우선 순위 큐 구현
"여러 서버가 모두 DB에서 많은 양의 데이터를 보내고 받아야합니다 *"- 정확히 설계된 (최적화 된) 데이터베이스 서버입니다. – qJake
데이터베이스가 처리 할 수 있다는 것을 알고 있지만,이 프로세스가 끊임없이 실행되고 모든 서버간에 데이터를 수집하는 데 필요한 대역폭이 더 걱정됩니다 ... MySQL의 방식은 최후의 수단이지만, 모든 데이터를 볼 필요없이 처음 몇 줄을 지우도록 파일을 업데이트하는 방법을 알고 있습니다. – hackartist