Python을 사용하세요. 대용량 데이터를 배열로 캐시하고 한 번에 파일에 써야 합니까?

StackOverflow https://stackoverflow.com/questions/19839646

  •  28-07-2022
  •  | 
  •  

문제

나는 항상 gevent 기반 크롤러 다운로드 페이지를 가지고 있습니다.크롤러는 생산자-소비자 패턴을 채택합니다. 이 패턴은 {method:get, url:xxxx, other_info:yyyy}와 같은 데이터를 대기열에 제공합니다.

이제 일부 응답을 파일로 모으고 싶습니다.문제는 모든 요청이 끝나면 그냥 열고 쓸 수 없다는 것입니다. 비용이 많이 들고 데이터의 순서가 정확하지 않습니다.

나는 모든 요청에 ​​번호를 매기고, 응답을 순서대로 캐시하고, 파일을 반복하고 조립하기 위해 Greenlet을 열어야 한다고 가정합니다. 의사 코드는 다음과 같습니다.

max_chunk=1000
data=[]
def wait_and_assemble_file(): # a loop
    while True:
        if len(data)==28:
            f= open('test.txt','a')
            for d in data:
                f.write(d)
            f.close()
        gevent.sleep(0)

def after_request(response, index): # Execute after every request ends
    data[index]=response  # every response is about 5-25k

더 나은 해결책이 있습니까?수천 개의 동시 요청이 있으며 메모리 사용이 너무 빨리 증가하거나 한 번에 너무 많은 루프가 발생하거나 예상치 못한 일이 발생할 수 있는지 의심됩니다.

업데이트:

위의 코드는 데이터 캐싱 및 파일 쓰기가 어떻게 수행되는지 보여줍니다.실제 상황에서는 캐싱이 완료되기를 기다리고 다른 파일에 쓰기 위해 100번의 루프가 실행될 수 있습니다.

업데이트2

@IT Ninja는 대기열 시스템 사용을 제안하므로 Redis를 사용하여 대안을 작성합니다.

def after_request(response, session_id, total_block_count ,index): # Execute after every request ends
    redis.lpush(session_id, msgpack.packb({'index':index, 'content':response}))  # save data to redid

    redis.incr(session_id+':count')
    if redis.get(session_id+':count') == total_block_count: # which means all data blocks are prepared
        save(session_name)


def save(session_name):
  data_array=[]
  texts = redis.lrange(session_name,0,-1)
  redis.delete(session_name)
  redis.delete(session_name+':count')
  for t in texts:
    _d = msgpack.unpackb(t)
    index = _d['index']
    content = _d['content']
    data_array[index]=content

  r= open(session_name+'.txt','w')
  [r.write(i) for i in data_array]
  r.close()

조금 더 좋아 보이지만 Redis에 대용량 데이터를 저장하는 것이 좋은 생각인지 의심스럽습니다. 더 많은 제안을 바랍니다!

도움이 되었습니까?

해결책

이와 같은 것은 각 스레드가 자체 파일 핸들러를 갖는 대신 대기열 시스템으로 더 잘 처리될 수 있습니다.이는 각 스레드에 자체 핸들러가 있기 때문에 이 파일을 작성할 때 경쟁 조건이 발생할 수 있기 때문입니다.

리소스에 관한 한, 파일에 전달되는 정보가 그다지 크지 않다는 가정하에 디스크 쓰기 이외의 리소스를 너무 많이 소비해서는 안 됩니다(Python은 이에 대해 정말 좋습니다).그래도 문제가 발생하는 경우 파일을 청크 단위로 메모리에 읽어들이면(그리고 비례적으로 청크로 쓰기) 이 문제를 파일 업로드 옵션으로 사용할 수 있는 한 크게 줄일 수 있습니다.

다른 팁

데이터 크기에 따라 다릅니다. 매우 큰 경우 모든 구조를 메모리에있는 프로그램의 속도를 늦출 수 있습니다.

메모리가 문제가되지 않으면 파일에서 항상 읽는 대신 메모리에 구조를 유지해야합니다. Concurrents 요청으로 파일을 계속 열면 좋은 솔루션이 아닙니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top