29 ポイント 投稿者 xguru 2022-08-17 | 3件のコメント | WhatsAppで共有
  • 1秒あたり200万件のメッセージを処理する NoSQL DB クラスタ(ScyllaDB)を運用中
  • DB性能に最も大きな影響を与えるのは物理ディスクハードウェアのレイテンシ
    → クエリ量が低い水準では問題にならないが、ある時点を超えると、1~2msかかる読み取り時間だけでもディスク読み取り待ちキューが発生し、クエリ自体がタイムアウトする
  • ディスクレイテンシは通常マイクロ秒単位なのに、なぜディスク操作に1~2msもかかるのか?
  • Discord は大半のハードウェアを Google Cloud で運用
    • NVMe ベースのローカル SSD をサポートしているが、独自にテストしたところ安定性の問題があり、重要なデータストアに使うには不安があった
    • Persistent Disk はサーバーへリアルタイムに接続・切断でき、ダウンタイムなしでリサイズ可能で、いつでもスナップショットを作成でき、標準でレプリケーションされるよう設計されている
      → 問題は、サーバーに直接接続されておらず、ネットワーク経由でつながっていること
  • ローカルネットワーク接続のレイテンシがどれだけ低くても、PCI/SATA より低くはならない
    → ネットワークは 1~2ms、直結ディスクは 0.5ms
  • ローカル SSD は、HDD のようにハードウェア障害が起きるとそのディスク上のデータを失い、ホスト自体に問題が起きるとスナップショットも取れず、データを完全に失う事態が起こりうる
    → そのため Discord は Local SSD を使わず、Persistent Disk を使用

問題分析

  • ローカル SSD と Persistent Disk の長所だけを集めたストレージがあれば理想だが、そのようなものはない。長所の一部だけを取り込むとしたら?
  • Discord では書き込みレイテンシは問題ではない。性能に影響するのは「読み取りレイテンシ」
  • 「ダウンタイムなしのディスクリサイズ」は必須機能ではない。サイズは事前に予測可能
  • 最終要件は
    • GCP にそのままとどまりつつ
    • データバックアップのために Point-in-Time スナップショットを使い
    • 読み取りレイテンシの最小化を最優先にし
    • 既存データベースのアップタイム保証を犠牲にしないこと
  • 読み取りは GCP の Local SSD を活用し、書き込みは Persistent Disk に行えればよさそう
    → ソフトウェアレベルでこうした Super-disk を作れるだろうか?

Super-Disk を作る

  • 要件は基本的に Write-Through キャッシュだった。GCP のローカル SSD をキャッシュとして使い、PD を保存レイヤーとして使う
  • DB サーバーに Ubuntu を使っているため、Linux カーネル層でディスクレベルのキャッシュを適用できる(dm-cache、lvm-cache、bcache などのモジュール)
  • しかし実験してみると、キャッシュディスクに不良セクタが発生した場合、読み取り処理全体が失敗した
    • 不良セクタが発生したらストレージレイヤーから読み出して上書きしなければならないが、評価したディスクキャッシュソリューションにはその機能がなかった
    • 不良セクタ発生時に、データベースがデータ整合性の問題でシャットダウンしてしまう
  • 追加要件として「ローカル SSD に不良セクタが発生しても生き残れること」が加わった
  • そこで Linux カーネルの「md」を調査
    • md はソフトウェア RAID の作成をサポートする
    • SSD と PD をミラーリングするだけでは問題は解決しない。読み取りの半分以上が PD から行われてしまうため
    • md には従来の RAID にはない「write-mostly」がある
      • 特定のディスクを write-mostly に指定すると、通常の読み取り対象から外され、ほかに選択肢がないときだけ読み取りが行われる。「低速に接続されたデバイスに有用」
      • つまり、SSD と PD を RAID1 にまとめ、PD を write-mostly に設定すれば要件を満たせる
  • 最後に残った問題は、GCP の Local SSD の容量がちょうど 375GB であること
  • Discord では特定のアプリケーション向けに、DB インスタンスあたり 1TB 以上が必要な場合もある
  • そこで複数の SSD を RAID0 にまとめることにした
  • 最終構成は
    • RAID0 でまとめたローカル SSD 4台を md0
    • md0 と Persistent Disk を RAID1 にまとめた md1 を構成

DB 性能

  • 結果はまさに予想どおりだった
  • ピーク時でもディスク操作がキューに積み上がらず、クエリレイテンシが変化しない
  • 性能が向上し、各サーバーあたりの処理クエリ量も増えた
  • RAID を使ったことがある人なら「これで本当に動くのか?」と疑問に思うかもしれないが、実際にはさまざまなことがあり、残りは別途詳しく紹介する予定

3件のコメント

 
eajrezz 2022-08-19

以前はGolangのパフォーマンスに満足できず、Rustでサーバーまで書いていたのを見ると、Discordという会社のギークさも相当なものだと思います。

 
psyrenpark 2022-08-17

大したことではないのに、大げさな手段で防いでいる感じです。

 
xguru 2022-08-17

HNでは「それって単にGCPの問題じゃない?」という話もありますが..
https://news.ycombinator.com/item?id=32474093
こういう試みも可能なんだな、程度に知っておくとよさそうです。