スケーリングの壁を越えて:高速データ処理に ScyllaDB を選んだ理由

Database tutorial - IT technology blog
Database tutorial - IT technology blog

スケーリングの壁と P99 レイテンシの悪夢

私は長年、構造化データには MySQL、柔軟なドキュメント保存には MongoDB を使い分けてきました。どちらも優れたツールですが、ある特定の壁にぶつかるまでは、の話です。秒間 250 万リクエストを処理するリアルタイム ビッディング システムを構築していた際、チームは予測不能なレイテンシのスパイクという悪夢に直面しました。ミリ秒未満のレスポンス タイムが必要でしたが、従来の NoSQL 構成では遅延が頻発していました。

分散システムを扱ったことがあるなら、水平スケーリングの巨人として Apache Cassandra の名を知っているでしょう。しかし、欠点もあります。それは Java 仮想マシン(JVM)上で動作することです。トラフィックが急増すると、JVM のガベージ コレクション(GC)が「Stop-the-world」と呼ばれる一時停止を引き起こします。

これらの一時停止が、高い P99 レイテンシを生み出します。99% のユーザーには高速なサイトに見えても、運の悪い 1% は単純なクエリに 200 ミリ秒以上待たされる可能性があるのです。高頻度取引やリアルタイム ビッディングにおいて、その 1% の遅延は収益の損失を意味します。これが、私が ScyllaDB に転向した理由です。

ScyllaDB が Cassandra のオーバーヘッドを解消する仕組み

ScyllaDB は Cassandra のドロップイン リプレイスメント(そのまま置き換え可能)ですが、Java エンジンを革新的な C++ アーキテクチャに置き換えています。これは単なる言語の変更ではなく、データベースがハードウェアと通信する方法を根本から変えるものです。

Shard-Per-Core(コアごとのシャード)の利点

標準的なデータベースは、CPU コアを「すべてのシェフが同じ包丁を奪い合っている混雑した厨房」のように扱います。これは CPU ロック コンテンション(競合)と呼ばれます。ScyllaDB は Seastar フレームワークを通じて「シェアード ナッシング(共有なし)」のアプローチを採用しています。各 CPU コアに特定のデータ シャードを割り当て、すべてのコアが独自のメモリ school とネットワーク スタックを独立して管理します。高コストなロック は存在しません。コア数を 2 倍にすれば、スループットもほぼ線形に 2 倍になります。

ガベージ コレクターからの脱却

C++ で記述されている ScyllaDB は、メモリを手動で管理します。バックグラウンド プロセスが突然 RAM をスキャンしてアプリケーションのスレッドを停止させることはありません。これにより、膨大な負荷がかかってもマイクロ秒単位の一貫したレイテンシが実現します。Cassandra Query Language (CQL) をサポートしているため、既存のドライバーやロジックを維持したまま、JVM チューニング スクリプトを削除できるのです。

60 秒でノードを起動する

私は環境をクリーンに保つため、ローカル テストには常に Docker を使用しています。コーヒーを淹れ終わる前に、本番環境レベル theater のエンジンを稼働させることができます。

# 公式イメージをプルする
docker pull scylladb/scylla

# コンテナを起動する
docker run --name my-scylla -d scylladb/scylla

起動したら、nodetool でノードの状態を確認しましょう。このユーティリティはクラスターの健康状態を確認するためのものです。

docker exec -it my-scylla nodetool status

UN ステータス(Up/Normal)を探してください。UJ(Up/Joining)と表示されている場合は、ノードがまだデータのバランシングを行っています。安定するまで 15 秒ほど待ってください。

クエリ駆動型モデリングをマスターする

ScyllaDB とのやり取りは標準的な SQL シェルを使っているような感覚ですが、メンタル モデルは異なります。データの関係性(リレーション)を中心に設計するのではなく、クエリに合わせて設計します。

# CQL シェルを開く
docker exec -it my-scylla cqlsh

まず、**Keyspace**(キースペース)を作成します。これは、クラスター内にデータの物理コピーをいくつ作成するか(レプリケーション ファクター)を定義するデータ コンテナです。

CREATE KEYSPACE itfromzero 
WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};

次に、ユーザーのアクティビティを追跡するテーブルを作成しましょう。ScyllaDB において、プライマリ キー(Primary Key)の決定は最も重要な設計判断です。

USE itfromzero;

CREATE TABLE user_logs (
    user_id UUID,
    activity_time timestamp,
    action text,
    metadata text,
    PRIMARY KEY (user_id, activity_time)
) WITH CLUSTERING ORDER BY (activity_time DESC);

このスキーマでは、user_id が **パーティション キー(Partition Key)** です。これはどの物理ノードにデータを保存するかを決定します。activity_time は **クラスタリング キー(Clustering Key)** で、ディスク上でのデータの物理的なソート順を決定します。これにより、特定のユーザーの最新 50 件のアクションを、1 回の高速なシーケンシャル リードで取得できます。

サンプル ログを挿入します:

INSERT INTO user_logs (user_id, activity_time, action, metadata) 
VALUES (uuid(), toTimestamp(now()), 'login', '{"ip": "10.0.0.5"}');

本番環境でパフォーマンスを破壊しないために

MySQL から移行した開発者の多くは、データの検索に ALLOW FILTERING を使おうとします。しかし、これはやめてください。リレーショナル データベース におけるインデックスのない検索は低速ですが、ScyllaDB では 100 ノードあるクラスターのすべてのノードを同時にスキャンさせることになりかねません。パフォーマンスは瞬時に崩壊します。

プライマリ キー以外のカラムでクエリを実行する必要がある場合は、より良い選択肢があります:

  • Materialized Views(マテリアライズド ビュー): ScyllaDB がシャドウ テーブルを作成し、同期ロジックを自動で処理します。
  • Local Secondary Indexes(ローカル セカンダリ インデックス): 単一パーティション内でのデータ フィルタリングに最適です。

私の経験則:新しいクエリ パターンが必要になったら、新しいテーブルを作成しましょう。ストレージは安価ですが、20 ミリ秒のレイテンシを失う代償は高くつきます。

Python との連携

ScyllaDB は Cassandra とプロトコル互換性があるため、標準の cassandra-driver が完璧に動作します。ロード バランシングや コネクション プーリング も自動的に処理されます。

from cassandra.cluster import Cluster

# ローカル ノードに接続
cluster = Cluster(['127.0.0.1'])
session = cluster.connect('itfromzero')

# データの取得は非常に簡単です
query = "SELECT user_id, action FROM user_logs LIMIT 5"
rows = session.execute(query)

for row in rows:
    # ユーザー ID とアクションを出力
    print(f"ユーザー {row.user_id} が実行: {row.action}")

cluster.shutdown()

結論

ScyllaDB への切り替えにはマインドセットの転換が必要です。複雑な JOIN の利便性は失われますが、代わりに 10TB のデータを 5 ミリ秒の P99 レイテンシで処理できるシステムが手に入ります。Shard-per-core アーキテクチャを受け入れることで、スケーリングに関する悩みは解消されることに気づきました。

IoT プラットフォーム、リアルタイム分析エンジン、あるいは数百万人のユーザーを抱えるメッセージング アプリを構築しているなら、ScyllaDB こそが必要なエンジンです。JVM チューニングの悪夢に悩まされることなく、Cassandra の圧倒的なスケールを享受できます。まずは今日、Docker のシングル ノードから始めてみてください。トラフィックが次の桁に達したとき、その真価を実感するはずです。

Share: