본문 바로가기

좋아하는 것_매직IT/96.IT 핫이슈

Discord가 네트웍 디스크의 지연시간을 최소화한 방법 (discord.com)

반응형

Discord가 네트웍 디스크의 지연시간을 최소화한 방법을 소개합니다.

Discord가 네트웍 디스크의 지연시간을 최소화한 방법에 대해서 요약을 해보면요...

아래는 주요내용을 간단하게 정리한 글입니다. 

  • 초당 200만개의 메시지를 처리하는 NoSQL DB 클러스터(ScyllaDB)를 운용 중
  • DB성능에 가장 큰 영향을 미치는 것은 피지컬 디스크 하드웨어의 레이턴시
    → 쿼리량이 낮은 수준에서는 상관없지만, 특정 시점을 초과하면 1~2ms가 걸리는 읽기 시간 만으로도 디스크에서 읽는 대기열이 발생하며 쿼리 자체에 대해 시간 초과가 발생
  • 디스크 레이턴시는 보통 마이크로세컨드 단위인데, 왜 디스크 오퍼레이션에 1~2ms가 걸릴까 ?
  • 디스코드는 대부분의 하드웨어를 Google Cloud에서 운용
    • NVMe 기반의 로컬 SSD를 지원하지만 자체적으로 테스트해보니 안정성 문제가 있어서 중요한 데이터 저장소로 사용하기엔 맘이 편하지 않았음
    • Persistent Disk는 서버에 실시간으로 연결/분리 가능하며, 다운타임 없이 리사이즈 가능, 언제나 스냅샷 생성가능하고, 기본으로 복제되게 설계됨
      → 문제는 서버에 직접 붙어있지 않고 네트웍으로 연결 된다는 것
  • 로컬 네트웍 커넥션 레이턴시가 아무리 낮아도, PCI/SATA 보다 낮지는 않음
    → 네트워크는 1~2ms, 직접연결된 디스크는 0.5ms
  • 로컬 SSD는 HDD처럼 하드웨어 문제가 생기면 그 디스크의 데이터를 잃어버리게 되며, 호스트 자체가 문제가 생기면 스냅샷도 불가능 해서 아예 데이터를 잃어 버리는 상황이 발생
    → 그래서 디스코드는 Local SSD 를 이용하지 않고, Persistent Disk 를 사용

문제 분석

  • 로컬 SSD와 Persistent Disk 의 장점만 모은 저장 장치가 있다면 최고겠지만 그런 것은 없음. 장점중 일부만 가져온다면?
  • 디스코드는 쓰기 지연시간은 문제가 아님. 성능에 영향을 미치는 것은 "읽기 지연시간"
  • "다운타임 없는 디스크 리사이징"은 필수 기능은 아님. 사이즈는 미리 예측 가능
  • 최종 요구 사항은
    • GCP 에 그대로 있으면서
    • 데이터 백업을 위해서 Point-in-Time 스냅샷 사용
    • 읽기 지연시간 최소화를 최우선 순위로
    • 기존 데이터베이스 업타임 보장을 희생하지 않을 것
  • 읽기는 GCP의 Local SSD를 활용하고, 쓰기는 Persistent Disk에 하면 좋을 것 같음
    → 소프트웨어 수준에서 이런 Super-disk를 만들 수 있을까?

Super-Disk 만들기

  • 요구사항은 기본적으로 Write-Through 캐쉬였음. GCP의 로컬 SSD를 캐쉬로 사용하고, PD를 저장 레이어로 사용
  • DB서버로 Ubunut를 사용하고 있어서, 리눅스 커널단에서 디스크 레벨의 캐쉬 적용 가능(dm-cache, lvm-cache, bcache 같은 모듈)
  • 하지만, 실험해보니 캐쉬디스크에 배드섹터 발생시 전체 읽기 작업이 실패함
    • 배드섹터가 발생하면 스토리지 레이어에서 읽어다 엎어써야 하는데, 평가한 디스크 캐슁 솔루션들은 이런 기능이 없었음
    • 배드섹터 발생시 데이터베이스가 데이터 안정성 문제로 셧다운 되어버림
  • 추가 요구사항으로 "로컬 SSD에 배드섹터가 발생해도 살아남아야 함"이 추가됨
  • 그래서 리눅스 커널의 "md"를 조사
    • md는 소프트웨어 RAID를 생성할수 있도록 지원
    • SSD와 PD를 미러링 하는 것으로는 문제가 해결 되지 않음. 절반이상의 읽기는 PD에서 될 것이기 때문에
    • md에는 전통적인 RAID에는 없는 "write-mostly" 가 있음
      • 특정 디스크를 write-mostly로 지정하면 일반 읽기에서는 제외되며, 다른 옵션이 없을 때만 읽기가 실행됨. "느리게 연결된 기기에 유용"
      • 즉, SSD와 PD를 RAID1으로 묶고, PD를 write-mostly로 세팅하면 요구사항을 맞출 수 있음
  • 마지막 남은 문제는 GCP의 Local SSD는 크기가 딱 375GB라는 것
  • 디스코드는 특정 어플리케이션에 대해서는 DB 인스턴스당 1TB 이상이 필요하기도 함
  • 그래서 여러개의 SSD를 RAID0로 묶기로
  • 최종 모습은
    • RAID0 로 묶인 로컬 SSD 4개를 md0
    • md0 와 Persistent Disk를 RAID1으로 묶은 md1 을 구성

DB 성능

  • 딱 예상한 결과가 나왔음
  • 피크시에도 디스크 오퍼레이션들이 큐에 쌓이지 않으며, 쿼리 레이턴시가 변하지 않음
  • 성능 향상이 일어나서 각 서버당 처리 쿼리량이 더 늘어남
  • RAID 사용해본 사람들은 이게 "그냥 동작할까?" 라는 의구심이 들겠지만, 실제로는 다양한 일이 있었고, 나머지는 따로 상세히 소개할 예정

 

좀더 자세한 내용은 아래 discord 홈페이지를 참고하시면 될것 같네요..

오늘의 블로그는 여기까지고요..
항상 믿고 봐주셔서 감사합니다.

728x90
300x250