Redisを超えてスケールする:DragonflyDB実践ガイド

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

モダンなインフラにおけるシングルスレッドの壁

私は10年近く、キャッシュやセッション管理にRedisを利用してきました。Redisは予測可能な速さと驚異的な安定性を備えています。しかし、ワークロードを64個や128個のvCPUを搭載したハイスペックなクラウドインスタンスに移行した際、もどかしいボトルネックに直面しました。膨大な計算リソースにコストを払っているにもかかわらず、Redisインスタンスは1つのCPUコアを使い切る一方で、残りの63コアは完全にアイドル状態だったのです。

これはRedisがシングルスレッドの実行モデルで動作しているために起こります。複雑なロックを回避できるというシンプルさは利点ですが、垂直スケーリング(スケールアップ)がほぼ不可能になります。より多くのパワーを利用するには、通常Redis Clusterをデプロイする必要があります。しかし、これにはアーキテクチャ上のオーバーヘッドや管理の手間伴い、多くのチームが避けたいと考えるものです。

Dragonfly:設計レベルでのマルチスレッド対応

Dragonflyは、このハードウェアの不一致を解決するために構築されました。RedisやMemcachedのAPIと完全な互換性を保ちながら、「シェアードナッシング(shared-nothing)」アーキテクチャを採用したインメモリデータストアです。1つのスレッドがすべての作業を行うのではなく、Dragonflyは各CPUコアに対してスレッドを生成します。各スレッドは、データ辞書の特定のセグメント(スライス)を管理します。

先月、トラフィックの多いマイクロサービスをDragonflyに切り替えました。結果はすぐに現れました。単一のインスタンスで、秒間400万リクエストを余裕で処理できたのです。もしRedisのスループットが頭打ちになっているなら、Dragonflyへの移行は最も論理的なアップグレードパスと言えます。

サーバーへのDragonflyのインストール

Dragonflyはワイヤー互換性を維持しているため、セットアップは非常に簡単です。redis-pyioredisといった既存のクライアントライブラリをそのまま使用でき、アプリケーションのロジックを修正する必要もありません。

方法1:Dockerでの実行(推奨)

開発環境と本番環境の両方において、Dockerは最も効率的なデプロイ方法です。以下のコマンドで開始できます:

docker run --network=host --ulimit memlock=-1 docker.dragonflydb.io/dragonflydb/dragonfly

私は常に--network=hostフラグを使用します。これにより、コンテナネットワークのオーバーヘッドが解消されます。これはミリ秒未満のレイテンシを追求する上で極めて重要です。また、--ulimit memlock=-1フラグも同様に重要です。これはOSがDragonflyのメモリをディスクにスワップするのを防ぎ、パフォーマンスの低下を回避します。

方法2:バイナリの手動インストール

ベアメタルや標準的なVMでの実行を好む場合は、GitHubから最新のリリースを直接取得できます:

wget https://github.com/dragonflydb/dragonfly/releases/latest/download/dragonfly-x86_64.tar.gz
tar -xvzf dragonfly-x86_64.tar.gz
sudo mv dragonfly /usr/local/bin/

次のコマンドで起動します:

dragonfly --logtostderr --port 6379

本番環境向けの設定

Dragonflyは、従来の.confファイルを廃止し、コマンドラインフラグによる設定を採用しています。このアプローチは、モダンなコンテナ化されたデプロイにおいて非常にクリーンです。本番環境で優先すべき設定は以下の通りです:

  • --mem_high_watermark_mb: メモリの上限を定義します。16GB RAMのサーバーであれば、私は12288(12GB)に設定します。これにより、OSやバックグラウンドタスク用に4GBのバッファが確保されます。
  • --proactor_threads: Dragonflyは通常、すべてのコアを自動的に検出します。特定のCPUリソースのみをデータベースに割り当てたい場合に、このフラグを使用します。
  • --snapshot_cron: ポイントインタイムバックアップを処理します。"*/5 * * * *"に設定すると、5分ごとにデータが保存されます。

本番ノードの一般的な起動コマンドは次のようになります:

dragonfly --mem_high_watermark_mb=8192 \
          --proactor_threads=8 \
          --dump_dir=/var/lib/dragonfly \
          --snapshot_cron="0 * * * *" \
          --requirepass="強固なパスワード"

データの移行と準備

レガシーシステムからデータを移行する際、フォーマットの変換が必要になることがよくあります。生のデータセットをSETコマンドに流し込む前に、変換が必要な場面にしばしば遭遇します。

これらのインポートのためにCSVエクスポートを素早くJSONに変換したいときは、toolcraft.app/ja/tools/data/csv-to-jsonを利用しています。ブラウザ上で完結するため、機密データがマシン外に出ることはありません。新しいキャッシュスキーマのプロトタイピングや、Dragonflyへの一括ロード用Pythonスクリプトを準備する際の時間を大幅に節約できます。

検証とモニタリング

Dragonflyを管理するために新しいツールを学ぶ必要はありません。標準のredis-cliがそのまま動作します。

redis-cli -p 6379
127.0.0.1:6379> INFO
# サーバー
dragonfly_version: 1.14.0
...

パフォーマンス向上のベンチマーク

違いを確認するには、同一のハードウェア上で古いRedis構成とDragonflyに対して負荷テストを実行してみてください。redis-benchmarkを高い並列数で使用して、限界値を確認します:

redis-benchmark -h 127.0.0.1 -p 6379 -c 100 -n 1000000 -t set,get -q

最近のAWS c6g.4xlargeインスタンスでのテストでは、DragonflyはスタンドアロンのRedisよりも4倍高いSET操作のスループットを記録しました。さらに重要なのは、高負荷時でもp99テールレイテンシが一貫して低く抑えられていたことです。

Prometheusのネイティブサポート

モニタリング機能は組み込まれています。Dragonflyはデフォルトで:8080/metricsにてPrometheus互換のエンドポイントを公開します。Redisのように別途エクスポーターをインストールする必要はありません。prometheus.ymlにターゲットを追加するだけです:

scrape_configs:
  - job_name: 'dragonfly'
    static_configs:
      - targets: ['localhost:8080']

最後に

Dragonflyは単なる「古いツールの高速版」ではありません。最新のハードウェアにおいてインメモリデータベースがどう機能すべきかを根本から再考したものです。シングルスレッドの制約から解放されることで、システム構成をシンプルに保つことができます。肥大化したRedis Clusterを、単一の非常に効率的なインスタンスに置き換えることが可能です。スループットやクラスターの複雑さに悩んでいるなら、Dragonflyへの切り替えは、リスクが低く、非常に高いパフォーマンスの見返りが得られる選択肢となるでしょう。

Share: