Discordがデータベースを「Apache Cassandra」から「ScyllaDB」に移行した“納得”の理由数兆分のメッセージデータをどう処理しているのか

Discordでは、Apache Cassandra(Cassandra)を利用していたが運用負荷など幾つかの課題があった。そこで同社は、ScyllaDBへの移行を決断し、ダウンタイムなしで移行を実現したという。Cassandraを巡ってどのような問題を抱えていたのか。どのようにダウンタイムなしで移行を実現したのか。Discordの公式ブログで解説した。

» 2023年04月20日 08時00分 公開
[@IT]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

 ゲーマー向けの無料音声テキストチャットアプリケーション「Discord」を開発、提供するDiscordは2023年3月6日(米国時間)、DBとして利用していた「Apache Cassandra」(以後、Cassandra)における課題に対処するため、「ScyllaDB」に移行していたことを明らかにした。

Cassandra運用における課題とは

 2015年、ゲーム専用グループチャットアプリとしてサービスがスタートしたDiscordは、スタート1年間で1100万人のユーザー、毎日4000万ものメッセージが送受信されるプラットフォームに成長した。以降も成長を続けたDiscordは、2017年には数十億ものメッセージを保存するデータベースとして、MongoDBからCassandraに移行していた。

 移行直後のDiscordでは、数十億のメッセージを保存するため、12のCassandraノードで対応した。しかし、2022年の初頭になると、メッセージは数兆にも増え、それを保存するために177のノードが実行されるようになっていた。ノードは問題が発生しやすく、メンテナンスに多くの時間や労力が必要だった。

メッセージスキーマ メッセージスキーマ

 上記のCassandra Query Language(CQL)ステートメントは、Discordにおけるメッセージスキーマの最小版だ。全てのIDはSnowflakeで時系列にソートできる。メッセージは送信するチャネルごとにパーティション化され、静的な時間ウィンドウであるパケットに分割されている。この分割により、Cassandraでは、特定のチャネルとバケットの全てのメッセージが一緒に保存され、3つのノードに複製される。

 このパーティショニングには潜在的なパフォーマンスの課題があった。Cassandraでは読み取りが書き込みよりもコストがかかる。書き込みはコミットログに追加され、メモリ内の構造体であるmemtable(メモリテーブル)に書き込まれる。一方、読み取りはmemtableを参照したり、複数のSSTable(ディスク上のファイル)を検索したりする必要があった。ユーザーがサーバとやり取りするために、同時に多数の読み取りが発生すると、ホットパーティション(読み取りの集中するパーティション)が生じ、データベースのクラスタ全体が頻繁な遅延を起こすことになった。1つのチャネルとパケットが大量のトラフィックを受け取り、ノードがトラフィックを処理しようとするため、徐々に処理遅延も発生していった。

 その他、クラスタのメンテナンスも頻繁に問題を引き起こした。そのため、Discordのチームはアーキテクチャの変更を検討することにした。

Cassandraと互換性のあるScyllaDBとは

 チームが検討したのはScyllaDBへの移行だ。ScyllaDBはCassandraと互換性のあるデータベースで、JavaではなくC++で書かれており、より高速でより安定性が高いとされている。そこでチームは2020年までに1つのデータベースを除いて全てをSyllaDBに移行させた。

 残った1つが「Cassandra-messages」だった。大規模なクラスタで、数兆件のメッセージとほぼ200のノードを持っているため、簡単には移行できなかったという。

 チームは、Cassandra-messagesの移行と並行してScyllaDBのパフォーマンスの改善に取り組んだ。移行後もホットパーティションが発生する可能性があるためだ。対策として、データベースの上流でシステムを改善し、パフォーマンスを向上させる必要があった。

 そこで、ScyllaDBクラスタとAPIの間に、複雑なクエリを処理するためのデータサービスを構築することにした。言語は、Rustを選んだ。C/C++の速度を犠牲にすることなく、安全性を保つことが期待できたためだ。

 データサービスは、APIとScyllaDBクラスタの間に存在する。このデータサービスが提供する最大の機能は、リクエストをまとめることだ。同じ行を同時に複数のユーザーがリクエストした場合、データベースに対して1回しか参照しないようにする。最初のユーザーがリクエストすると、ワーカータスクがサービスで立ち上がる。以降のリクエストは、そのタスクが存在するかどうかを確認し、存在する場合にサブスクライブする。すると、そのタスクが完了し、データベースから行が取得されると、その行を全てのサブスクライバーに返す。

データサービスによる処理の流れ データサービスによる処理の流れ

 このデータサービスによって、データベースに対するトラフィックの急増を大幅に減少させることができた。

 加えてデータサービスの上流工程で、データサービスの各リクエストにルーティングキーを提供し、同じチャネルのリクエストがサービスの同じインスタンスに送信されるようにした。このルーティング処理で、データベースの負荷をさらに軽減できるようになったという。

ルーティング処理の流れ ルーティング処理の流れ

 データベースの移行に際してチームに求められたのは、ダウンタイムなしで数兆のメッセージを移行することだった。チームはRustでデータ移行ツールを書き換え、データサービスライブラリを拡張して大規模なデータ移行を実行できるようにした。データベースからトークンレンジ(※分散データベースにおいて、各ノードが担当するデータの範囲)を読み取り、ローカルでSQLiteを使用してチェックポイントを作成する。その後、ScyllaDBにデータをフルスロットルで移行する。この移行ツールを利用することで、9日間でデータを移行できると分かった。1秒あたり320万通のメッセージを移行し、ScyllaDBを主要なデータベースに切り替えることに成功した。

 最終的にメッセージデータベースを切り替えたのは2022年5月のことだ。Cassandraのノード数が177だったのに対し、ScyllaDBのノードは半分以下の72ノード、各ノードの容量は、Cassandraノードの4TBからScyllaDBは9TBと倍増した。また、テールレイテンシも大幅に改善された。

 ScyllaDBの威力は2022年12月に開催されたFIFAワールドカップカタール2022でも効果を発揮した。メッセージの送信量が増加しても、RustをベースとしたScyllaDBは、毎秒大量のトラフィックを完璧に処理していたとしている。

Copyright © ITmedia, Inc. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。