2011-12-09 1 views
2

.net4 IIS7의 병렬 웹 환경에서 파일에 레코드를 쓰는 (추가하는) 가장 좋은 방법은 무엇입니까? 나는 ashx http handler를 사용하여 파일에 빠르게 기록되어야하는 데이터의 작은 부분을 받는다.로드가 높은 .ashx http 핸들러에서 디스크 파일에 레코드를 추가하는 가장 빠르고 안전한 방법은 무엇입니까?

using (var stream = new FileStream(fileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite, 8192)) 
    { 
     stream.Write(buffer, 0, buffer.Length); 
    } 

을하지만 일부 레코드는 아마 때문에 FileShare.ReadWrite의, 깨지거나 불완전 한 것으로 나타났습니다 : 우선 사용. 다음으로 FileShare.Read로 변경하려고했습니다. 거기에 다음 깨진 레코드가 있지만, 때때로이 예외가 있어요 : System.IO.IOException : 프로세스가 파일을 액세스 할 수 없습니다 ... 다른 프로세스에서 사용되고 있기 때문에.

이상적으로 모든 레코드가 결국 기록 될 수 있도록 운영 체제에서 동시 쓰기 요청을 큐에 넣길 바랍니다. 어떤 파일 액세스 API를 사용해야합니까?

답변

1

크기에 따라 두 가지 옵션이 있습니다. 크기가 작 으면 은 아마도입니다. 가장 좋은 방법은 단순히 일부 공유 잠금에 의해 파일에 대한 액세스를 동기화하는 것입니다. 가능한 경우 파일을 계속 열어 두는 것이 좋습니다 (때때로 플러시). 항상 열거 나 닫는 것이 좋습니다. 예를 들면 다음과 같습니다.

class MeaningfulName : IDisposable { 
    FileStream file; 
    readonly object syncLock = new object(); 
    public MeaningfulName(string path) { 
     file = new FileStream(fileName, FileMode.Append, FileAccess.Write, 
      FileShare.ReadWrite, 8192); 
    } 
    public void Dispose() { 
     if(file != null) { 
      file.Dispose(); 
      file = null; 
     } 
    } 
    public void Append(byte[] buffer) { 
     if(file == null) throw new ObjectDisposedException(GetType().Name); 
     lock(syncLock) { // only 1 thread can be appending at a time 
      file.Write(buffer, 0, buffer.Length); 
      file.Flush(); 
     } 
    } 
} 

이는 스레드로부터 안전하며 모든 ashx에서 문제없이 사용할 수 있습니다.

큰 데이터의 경우 동기화 된 리더기 기 큐를 보길 원할 수 있습니다. 즉, 모든 작성기 (ashx 히트)가 대기열에 데이터를 던져서 하나의 전용 작성자 스레드가 대기열에서 대기열에 추가하고 추가 할 수 있습니다. 그건 ashx에서 입출력 시간을 제거하지만 작가가 계속 지킬 수없는 경우 대기열 크기를 제한하려고 할 수 있습니다. 여기에 capped synchronized reader/writer queue의 샘플이 있습니다.

+0

좋아, 자물쇠를 추가하고 파일을 열어 두는 것은 성능 저하없이 트릭을 수행하는 것처럼 보이지만 지금은 또 다른 문제가 있습니다. 거기에 더 많은 하나의 파일을 쓰고, 그것은 매 시간 (새 파일이 만들어집니다), 그래서 열린 파일 스트림을 저장하기위한 스레드 안전 수집이 필요하고 새로운 하나를 추가하는 것이 필요합니다 전환됩니다. 지금은 ConcurrentDictionary 을 사용합니다. 더 빠른 것이 있는지 궁금하십니까? – PanJanek

+0

@PanJanek 현재 시간 이외의 다른 것을 쓰고 있습니까? 왜 사전이 필요한지 잘 모르겠다. –

+0

한 시간에서 여러 시간으로 파일을 변경하는 것 외에도 다른 비즈니스 클라이언트 (요청 매개 변수 중 하나에 의해 식별 됨)의 요청을 다른 파일에 씁니다. 매시간 약 2-3 개의 서로 다른 파일이 열립니다. – PanJanek

0

웹 가든이나 웹 팜을 사용하고 있지 않다면 프로세스 로컬 잠금 (lock() {})을 사용하고 가능한 한 잠금 외부에서 많은 처리를 수행 할 것을 권합니다.

작성하려는 파일이 여러 개인 경우 좋은 해결책은 Better solution to multithreading riddle?을 참조하십시오.