기록해야 기억에 남는다

채팅을 파일로 저장하는 법 (2) 본문

카테고리 없음

채팅을 파일로 저장하는 법 (2)

아케인222 2023. 3. 10. 00:42

 (1) IndexElement, TextElement

(1) IndexElement

 

  • 채팅 생성 timeline (4bytes), file offset (4bytes) 로 구성
  • .idx파일에 8bytes 블록 단위로 기록
  • timeline값을 기준으로 file offset 값을 읽어올 수 있음
  • 기존 설계의 경우 timeline 8bytes, file offset 8bytes 총 16bytes 였으나, 채팅 데이터 양이 그렇게 많지 않고 데이터를 줄이기 위해 int 2개로 처리
    • 이론상 file offset 2^31 - 1 bytes 까지 기록 가능 (이후 overflow가 발생 하므로 long에 기록)
    • 2^31 - 1 bytes의 경우 약 2GB 이므로 이 정도의 채팅 데이터가 쌓이게 되면 index 파일을 하나 더 생성 하는 식으로도 처리 가능

 


(2) TextElement

 

  • userType, sender, data, timeline, createAt으로 구성
  • Index와 달리 한 블록의 크기가 가변적
  • 특정 줄을 찾기 위해 각 줄을 읽어 찾으려면 굉장히 비효율적임
    • Index 파일 블록에서 읽어온 file offset을 이용해 특정 데이터로 Seek 가능

 

  • 파일에 매번 데이터를 입출력 할 경우 File Open/Close 가 반복되므로 성능 저하 발생
  • IndexElement 의 경우 ByteBuffer, TextElement의 경우 CharBuffer를 이용해 데이터를 버퍼에 쌓고, 버퍼가 가득 차면 파일에 flush 하여 성능 개선
  • 아래의 Split / Encoding 작업 전 버퍼에 데이터가 남아있는지 체크하여 잔여 데이터 flush

 


(3) Split

 

  • .txt, .idx, .m3u8 파일을 이용해 .txt 파일을 분할
  • HLS와 비슷하게 .m3u8 파일을 읽어 세그먼트의 크기를 결정함
  • 채팅 timeline값이 단조증가하는 형태로 기록되므로 이분 탐색 가능
  •  
  • 구간 별로 이분 탐색 Lower bound / upper bound 를 이용해 자를 구간 선정

  • 타임라인 값은 중복 된 값이 존재할 수 있으므로 그냥 이분 탐색으로는 정확한 위치를 찾기 힘듬
    • ex) timeline 값이 12인 (방송 시작 12초 경과) 시점에 여러 채팅이 존재할 수 있음 
    • Lower Bound는 해당 값이 들어갈 수 있는 하한선, Upper Bound는 해당 값이 들어갈 수 있는 상한선
    • 자르려는 왼쪽 값의 하한선과 자르려는 오른쪽 값의 상한선을 찾는 것 

 


(4) Encoding

 

  • HTTP2의 경우 헤더 크기를 줄이기 위해 Huffman Encoding을 이용하여 헤더를 압축함
  • 이와 비슷하게 잘린 채팅 세그먼트 크기를 줄이기 위해 허프만 압축을 이용하여 압축

 

  • Huffman Encoding
    • 데이터 Read → 글자 수 별 빈도수 계산 → 허프만 트리 구성 및 Leaf 노드 구성 → Leaf 노드 별 허프만 코드 할당 및 데이터 인코딩 
    •  빈도 수가 많은 글자에는 짧은 이진 문자열을, 빈도수가 적은 문자에는 긴 이진 문자열을 할당 (그리디 알고리즘 성향)
  •  Huffman Decoding
    • 파일 앞에 쓰여진 디코딩 헤더 정보 (허프만 트리를 재구성 하기 위한 정보) 를 읽어 파일 원복
    • 전체 글자 종류, 허프만 트리 정보, 인코딩된 데이터로 구성됨

 


(5) Result

 

  • Split & Encoding 을 통해 각 txt 파일 세그먼트를 ch 파일로 변환

 

 

  • 이후 클라이언트에서 m3u8 다운로드 후 구간에 맞는 ch 파일 요청, 디코딩 작업을 통해 채팅 데이터를 읽음

 

 

 

  • m3u8을 읽어와 ch 파일을 다운받고 디코딩 하여 txt 파일을 생성
  • txt 파일에서 채팅 데이터를 읽어 적절한 값을 출력
  • 시간이 경과됨에 따라 다음 채팅 세그먼트를 다운 받아 같은 방식으로 처리함
    • 로컬에 해당 세그먼트의 파일이 이미 존재하면 로컬 파일을 읽어옴

 

  • timeline 바를 이용해 특정 시점으로 시간을 Seek 할 경우 
    해당 구간에 맞는 채팅 세그먼트를 읽어와 처리 후 출력함을 확인할 수 있습니다.
  • 아래의 Split / Encoding 작업 전 버퍼에 데이터가 남아있는지 체크하여 잔여 데이터 flush