300ノードのRedisクラスタをわずか3つのLavikノードに移行する
Migrate Your 300-Node Redis Cluster to Just 3 Lavik Nodes (lavik.dev)
要約
この記事は、大量のデータを扱うアプリケーションにおいて、メモリ容量の制約から生じるスケーリングの課題とコストについて論じています。Lavikは、NVMe SSDをストレージとして活用し、DRAMベースのRedisよりも高いスループットと低コストを実現することで、この課題を解決するソリューションとして提案されています。300ノードのRedisクラスタをわずか3つのLavikノードに集約することで、大幅なコスト削減と運用負荷の軽減が可能になることを示しています。
全文翻訳
300ノードのRedisクラスタをわずか3つのLavikノードに移行する
メモリがいっぱいだ。CPUにはまだ空きがある。それでも、保持されるデータの次の増加は、別のRedisシャード、別のレプリカ、そして運用する別のペアのサーバーを意味する。容量に制約のあるアプリケーションにとって、それは高価な成長方法だ。Lavikは容量を決定するリソースを変更する。アプリケーションの値はNVMe SSD上にライブし、公開された比較でDRAM上のRedisよりも高速な毎秒114万GETを測定したエンジンによって提供される。その組み合わせは、より魅力的な設計を開く。メモリに制約のあるフリートを少数のストレージ密度のホストに統合し、次世代のエージェント状態のためのスペースを確保する。131
[画像: 150のプライマリ–レプリカペアの300 Redisノードと、L16as_v4上のLavikプライマリとフォロワー、およびE2s_v4のMetaのみのVoterとの比較。データノードはMetaメンバーも実行し、3つのMeta投票と2つのデータセットコピーを提供する。]
容量モデル: 300 E2s_v4 Redis VMと、2つのL16as_v4 LavikデータVMおよび1つのE2s_v4 MetaのみのVoterとの比較。各VMには1つのMetaメンバーが実行されており、プライマリとフォロワーのみがデータセットを保持する。12829
1. エージェントはより多くの状態を、そしてそれに高速にアクセスする必要がある
人間向けのアプリケーションは、ユーザーごとにプロファイル、セッション、および機能セットを保持する可能性がある。エージェントアプリケーションは、これらのすべてをリサーチアシスタント、コーディングアシスタント、およびそのユーザーの代わりに機能する複数のバックグラウンドワーカーのために保持できる。各エージェントは実行状態、観測結果、および作業コンテキストを蓄積する。時々実行されるエージェントでも、再開時に状態がすぐに必要になる場合がある。容量はエージェントの数、その状態のサイズ、およびそれがどれだけ有用であり続けるかによって増加する。リクエストのボリュームが同じ速度で増加する必要はない。1
10億のエージェントで、それぞれ1KBの機能しかなくても、約1TBの値が生成される。それを10KBに増やすとデータセットは10TBに達し、100KBでは、キー、インデックス、またはレプリケーションの前で100TBに達する。アプリケーションは、使い慣れたRedisクライアントとデータ構造を介して、低レイテンシの読み取りと更新を依然として必要とする。保持されるすべての値を高価なDRAMに保持すると、その組み合わせの費用対効果が悪くなる。Lavikは、NVMe SSDの容量をこれらのレイテンシに敏感なワークロードに実用的にすることを目指して設計されている。16
10億エージェントあたりの値ペイロード · 小数単位
| エージェントあたりのバイト数 | 一意の値ペイロード | 値のみの2つのコピー |
|---|---|---|
| 1 KB | 1 TB | 2 TB |
| 10 KB | 10 TB | 20 TB |
| 100 KB | 100 TB | 200 TB |
ソースと計算入力1
2. メモリを追加するためだけにサーバーを追加するのはやめる
2つのvCPU、16GiB RAM、ローカルSSDなしの300のStandard_E2s_v4 Azure VMを、150のプライマリと150のレプリカとして構成することを検討する。このフリートは600のvCPUと4,800GiBのRAMを購入し、そのうち2,400GiBはプライマリ側にある。メモリが最初に満杯になったとき、このフリートを拡張すると、主にRAMを増やすために追加のCPU、ネットワーク、およびオペレーティングシステムを購入することになる。アプリケーションは、比例して多くのコンピューティングを必要とせずに、より多くの保持プロファイルやより長いセッションライフタイムを必要とする可能性がある。これはRedisのコスト最適化の中心的な機会である。トラフィックを提供するのに必要なプロセッサとは独立してストレージ密度を選択する。128
同じAzureリージョンと購入モデルを両方のデプロイメントに使用する。East US 2、Linux従量課金、米ドル。Standard_E2s_v4の月額料金は0.126ドル、Standard_L16as_v4の月額料金は1.376ドル。1ヶ月あたり730時間で、300のRedis VMのコストは27,594ドルになる。Lavikは2つのL16as_v4データVMと1つの小型E2s_v4 Voterを使用し、合計で2,100.94ドルになる。各データVMには16のvCPU、128GiBのRAM、および3.84TBのローカルNVMe SSDが含まれており、VoterはローカルSSDやデータセットコピーを必要としない。2728291
フラッシュを追加しても、レイテンシの問題が自動的に解決されるわけではない。RedisはFlexのフラッシュアクセスをミリ秒単位で説明しており、広範なアクセスパターン、大きなワーキングセット、およびRAMとフラッシュ間の頻繁な移動を推奨していない。ミリ秒単位のレイテンシ予算を持つアプリケーションにとって、ミリ秒単位のフラッシュパスは遅すぎる。異なるプロファイルやコンテキストを繰り返し参照するエージェントワークロードでは、この違いが重要になる。ストレージエンジンは、アクセスがRAMを超えて広がる場合でも、大きなデータセットを効率的に提供する必要がある。2526
月額VM料金は25,493.06ドル(92.4%)減少し、年間節約額は305,916.72ドルになる。Lavikの3つのVMは、デプロイメント全体で34のvCPUと272GiBのRAMを提供し、2つのNVMe搭載ノードがデータを処理し、より小型のVMがフェイルオーバークォーラムを完了する。Redisの300VMは600のvCPUを提供し、その多くはメモリに制約のあるワークロードでは必要ないかもしれない。ストレージ密度はサービングフリートを削減し、Voterの役割を分離することで、データサイズの追加マシンに支払うことを回避する。この表は、両方のシステムでセルフホストVMの価格を示している。OSディスク、バックアップ、トラフィックは追加のデプロイメントコストである。127116
Azure East US 2 · Linux従量課金 · USD · 月730時間。VM時間料金は各SKUを特定し、月額および年額料金は完全なデプロイメントをカバーする。
| デプロイメント | USD / VM時間 | 月額USD | 年額USD | 100万オペレーションあたりのUSD (平均1M QPS) |
|---|---|---|---|---|
| Redis · 300 × Standard_E2s_v4 | $0.126 | $27,594.00 | $331,128.00 | $0.01050 |
| Lavik · 2 × L16as_v4 + 1 × E2s_v4 | $1.376 (L16as_v4); $0.126 (E2s_v4) | $2,100.94 | $25,211.28 | $0.00080 |
3. NVMe SSDを中心に容量を構築する
Lavikデプロイメントを2つのStandard_L16as_v4 VMと1つのStandard_E2s_v4 VMから構築する。プライマリとフォロワーはそれぞれ16のvCPU、128GiBのRAM、および4つの960GBローカルNVMeデバイスを持ち、データVMあたり合計3.84TBになる。それぞれがDataプロセスとMetaメンバーを実行する。E2s_v4は、2つのvCPUと16GiB RAMで3番目のMetaメンバーを実行し、自動フェイルオーバーのための3メンバーRaftクォーラムを完了する。このVoter専用VMは、アプリケーションデータを保持せず、コントロールプレーンメタデータを格納する。このトポロジーは、2つの完全なデータセットコピーと3つのMetaVoterを持つ。
プライマリとフォロワーはそれぞれ完全なコピーを保持するため、単一コピーの容量基準は3.84TBのままとなる。Voter VMを含めると、デプロイメントのコストはTB月あたり547.12ドルになる。Redisの150のプライマリは2,400GiB、約2.577TBを提供し、TB月あたり10,707.88ドルのコストになる。これらは、データベースオーバーヘッドと運用上の空き容量予約前の容量正規化されたVMコストである。プライマリVMが失敗した場合、フォロワーと専用Voterは、適格なフォロワーの昇格を調整するために2/3のMetaマジョリティを保持する。生き残ったフォロワーは残りのデータコピーを保持し、Voterはコントロールプレーン参加を提供する。127117
月額VMコスト(プライマリ容量TBあたり、データベースオーバーヘッドと運用ヘッドルーム前)。レプリカ容量は1回カウントされる。
| デプロイメント | 単一コピー容量分母 | USD / TB月 |
|---|---|---|
| Redis · 300 × E2s_v4 | 2,400 GiB RAM (≈ 2.577 TB) | $10,707.88 |
| Lavik · 2 × L16as_v4 + 1 × E2s_v4 | 3.84 TB NVMe SSD | $547.12 |
Lavikは、リクエストパス上で最も価値のあるDRAMを使用する。キーインデックス、メタデータ、アクティブバッファ。値はNVMe SSD容量を使用する。これにより、値バイトの増加とインデックスメモリの増加が分離され、エージェントプロファイルと保持コンテキストが大きくなるにつれて特に有用になる。RAMのサイズは、アプリケーションのキー数とキー長、およびバッファ、hugepages、レプリケーションバックログによって決まる。公開された大規模データセット実験では、10億キーのレイアウトは125.8GiBのホストに収まり、その値は約1テラバイトを占める。913
SPDKはストレージパスを明示する。Lavikはユーザースペースキューペアを介してNVMe操作を送信し、完了をポーリングすることで、カーネルブロックI/O送信パスとそのsyscallおよびウェイクアップオーバーヘッドを排除する。非同期リクエストは、ワーカーが他のコマンドで進捗する間、ストレージ作業をインフライト状態に保つ。ポーリングはCPU時間を迅速な完了処理と引き換えにする。キューの深さ、完了バッチ処理、CPU配置は、その時間をどれだけ効果的に使用できるかを決定する。最新のNVMeデバイスは、並列キューと内部並行性を提供する。エンジンはそれらを活用するために十分な独立した作業を提供する必要がある。4513
LavikのBycorfワーカーは、コルーチン、オーナーローカルミュータブル状態、およびワーカー間の明示的なディスパッチを使用する。1つのコマンドがストレージを待っている間、他の実行可能な作業を進めることができる。オーナーシップは、共通の操作をそれらを変更する状態の近くに保ち、コア間の協調を減らす。これは毎秒100万オペレーションでは重要である。スケジューリング、同期、または割り当てのオーバーヘッドがわずかでも、かなりのCPU需要につながる。実行とストレージを一緒に設計することで、LavikはSSDの並列性を利用できる。ただし、すべてのI/Oを要求処理スレッドの停止につなげることはない。689
最適化はリクエストパス全体に及ぶ。適格なディスクGETは、接続ワーカー上の承認済みインデックススナップショットを使用でき、高速パスが適用される場合にオーナーディスパッチを回避する。解析は最大128コマンドのバッチを処理し、小さなパイプライン応答は64KiB書き込みにまとめることができる。ワーカーごとのアペンドストリームは、各論理スロットのステージングバッファ割り当てを回避する。これらを組み合わせることで、協調、システムコール、バッファオーバーヘッドが削減される。Redis互換インターフェースはアプリケーションにとって使い慣れたままである。その下の実装は、効率的な並列ストレージアクセスを中心に構築されている。89
大きなオブジェクトも同様の注意を払う。Lavik 0.1.0は、文字列、ハッシュ、セット、リスト、ソートセット、ストリームのグループ化ストレージをサポートする。大きな文字列は8KiBセグメントを使用し、コレクションは独立してアドレス指定されたグループを使用する。焦点を絞った操作は、オブジェクト全体を書き換えるのではなく、関連する部分を操作できる。頻繁に変更される機能とより大きな保持状態を持つエージェントプロファイルの場合、そのレイアウトは、小さな更新とレコード全体の不要な作業との違いを生む。NVMeのパフォーマンスは、I/Oがどのようにスケジューリングされるかと、各操作がどれだけ多くのデータに触れるかの両方に依存する。10
[画像: RESPトラフィックはコルーチンワーカーに入り、インデックスはメモリに残り、非同期SPDKキューペアはNVMe SSDに到達する。カーネルTCPとMeta権限は別々である。]
Lavikのリクエストパス: コルーチンワーカー、メモリ内キーインデックス、非同期SPDK I/OによりNVMeストレージがビジー状態になる。6894
4. DRAM上のRedisよりも高速 — 値はSSD上
直接ベンチマークは、Lavik 0.1.0 SPDKとRedis 8.10.2およびValkey 9.1.2を同じ16vCPU Azureサーバーで比較する。別のロードジェネレーターは、プライベートネットワーク上で一様ランダムなGETとSETを発行する。値は1KiB、パイプライン深度は1である。RedisとValkeyはDRAMから値を提供し、LavikはNVMeストレージパスを使用する。この表は、スループットとクライアント観測レイテンシを同時に示しており、読者はアプリケーションのレイテンシ予算に対して動作点を選択できる。
1,280接続時、Lavikは毎秒1,145,772 GET QPSと971,950 SET QPSを提供する。GETスループットはRedisより12.5%、Valkeyより18.1%高く、SETスループットはRedisより2.2%高い。その時点でのLavikのGET P99は3.999msであり、Redisの4.415msと比較して優れている。これは、NVMeバックド容量がインメモリサーバーよりも高いスループットで提供できるというアーキテクチャの結果であり、アプリケーションにパフォーマンスとストレージコストのトレードオフを強いるのではなく、統合を検討する価値があることを示している。1613
同じ1,280接続実行 · QPSは整数オペレーションに丸められ、すべてのレイテンシ列はミリ秒単位
| システム / オペレーション | QPS | 平均 | P50 | P95 | P99 | P99.9 |
|---|---|---|---|---|---|---|
| Lavik 0.1.0 SPDK GET | 1,145,772 | 1.117 | 1.031 | 1.511 | 3.999 | 7.135 |
| Lavik 0.1.0 SPDK SET | 971,950 | 1.317 | 1.119 | 2.783 | 4.479 | 7.199 |
| Redis 8.10.2 GET | 1,018,735 | 1.256 | 1.087 | 2.479 | 4.415 | 7.103 |
| Redis 8.10.2 SET | 951,053 | 1.346 | 1.135 | 2.943 | 4.511 | 7.231 |
| Valkey 9.1.2 GET | 970,288 | 1.319 | 1.119 | 2.511 | 4.415 | 7.455 |
| Valkey 9.1.2 SET | 808,103 | 1.583 | 1.455 | 2.559 | 4.047 | 7.199 |
レイテンシは、サーバーがどれだけ負荷がかかっているかにも依存する。10億キーの動作点(80接続)では、Lavikは毎秒385,514 GET QPSを0.439ms P99.9で提供する。640接続では、毎秒100万GET以上に達する。インフラチームはこれらの曲線を使用して、必要なスループットとテールレイテンシの組み合わせを選択できる。バーストのためのヘッドルームを維持することは、スループットチャートの最高点のみから本番デプロイメントをサイジングするよりも有用である。13
10億キーのデータセットには1.024TBの生の値が含まれており、サーバーのRAMの約7.6倍である。このデータセットで、毎秒1,069,126 GET QPSに達する。したがって、Lavikのパフォーマンスはメモリサイズのデータセットをはるかに超えて拡張される。より小型インスタンスの結果も同様の容量ストーリーを語っている。2つのvCPUと16GiBの名目RAMで、データセットを100万から1億の1KiB値に増やしても、ピークGETスループットは215,521から215,463 QPSに変化する。SETは、より小さなデータセットのピークの95.2%を維持する。これは、コンパクトなサービスと大規模なエージェントプラットフォームの両方にとって価値がある。容量は、サービングノードの同等の増加を要求することなく成長できる。1314
[画像: 1000万および10億キーを持つLavik、および1000万キーを持つRedisとValkeyのGETおよびSETスループット曲線。]
80〜1,280接続でのGETおよびSET。10Mキーの実行は30秒のウィンドウを使用し、1Bキーの実行は60秒のウィンドウと異なるクライアントシードを使用する。1316
エージェントの状態も更新が必要である。個別のio_uring YCSB実験では、Lavikは50/50の読み取り/更新ミックスで毎秒529,501オペレーション、95/5ミックスで577,373オペレーションを処理する。これらは構造化レコードオペレーションである。1億レコードと10個の128バイトフィールドに対するHGETALL読み取りとLAVIK.HREPLACE更新。これらは、純粋なGETワークロードを超えたLavikの設計の関連性を示している。これには、エージェントがタスクを進めるにつれて内容が変化する機能レコードも含まれる。15
個別のio_uring YCSB実験 · 1億レコード、10 × 128 Bフィールド、256ワーカー、レプリカなし
| Lavikワークロード | 総QPS | READ P99.9 ms | UPDATE P99.9 ms |
|---|---|---|---|
| 50% HGETALL / 50% HREPLACE | 529,501 | 5.083 | 2.831 |
| 95% HGETALL / 5% HREPLACE | 577,373 | 1.818 | 1.578 |
ソースと計算入力15
毎秒100万オペレーションは、持続すれば1日あたり864億オペレーションに相当する。このレベルの測定されたサービングパフォーマンスとNVMeストレージ密度を組み合わせることで、メモリに制約のあるフリートを再評価する強力な根拠となる。実際のトラフィックエンベロープ(コマンドミックス、ピーク需要、バースト、レイテンシターゲット)から始め、そのエンベロープにコンピューティングを割り当てる。NVMe SSDに、アプリケーションが記憶する必要があるすべての容量を提供する。113
5. ノードが少ないほどクラスタの機械が少なくなる
メモリ駆動の成長は、エンジニアが運用しなければならないトポロジーも拡大する。Redis Clusterは16,384のハッシュスロットを分散し、フルメッシュクラスタバスを使用する。その仕様では、各ノードはN-1の送信およびN-1の受信バス接続を持つ。クラスタ全体では、これはN(N-1)の開始接続となる。300ノードで89,700、600ノードで359,400、1,000ノードで999,000となる。これらはアプリケーショントラフィックとは別のクラスタバス接続である。エージェントの状態が拡大するにつれて、より多くのノードを通じてメモリを追加すると、このコーディネーションファブリックのサイズも増加する。2
クラスタは、ゴシップ、ハートビートプローブ、および障害レポートを使用して、メンバーシップとヘルスを維持する。ローカル障害の疑いは、他のノードからのレポートと調整する必要がある。フェイルオーバーには、承認と構成エポックが必要である。ネットワークパーティションまたはローリング再起動中、エンジニアはどのプライマリ、レプリカ、およびパスが到達可能であるかを理解する必要がある。メンバーが増えると、リクエスト処理容量が十分であっても、診断すべき配置と関係が増える。フリートの運用コストには、VM料金だけでなく、この作業も含まれる。2
リシャーディングは、データ移動、所有権変更、およびクライアントリダイレクトを追加する。メンテナンスは、パッチ適用、再起動、監視、およびレプリカ配置を追加する。ストレージ密度の高いLavikデプロイメントは、容量に必要なDataプロセスの数を減らし、それぞれが成長する余地を与える。LavikのMetaサービスはトポロジーと権限を管理し、ネイティブリプリケーションはフォロワーを維持する。容量に制約のあるアプリケーションにとって、フリートを削減することは、メモリのために購入したサーバーと、それらを管理することに伴う運用作業という2つの費用を同時に解決する。36117
6. ワークロードを移動し、サービス要件を維持する
[画像: 単一の対数グラフは、容量駆動のVM数を比較する。オーバーヘッド前の10TBでは、Redisは1,166VMに達する。3つの独立したLavikデプロイメントの合計は9VMになる。6つのデータVMと3つのMetaのみのVoterである。]
対数容量モデル(オーバーヘッド前)。Redisは16GiBプライマリとペアあたり1つのレプリカを使用する。各独立したLavikデプロイメントは、2つの3.84TBデータVMと1つの小型MetaのみのVoterを追加する。3つのVMすべてがカウントされる。12829
最も強力な統合候補は認識しやすい。メモリの圧力により拡張が強制され続ける一方で、CPU使用率とトラフィックはフリートのサービング容量を下回っている。代表的なワークロードを選択し、そのコマンド、キー数、値の分布、および最もビジーな期間に合わせてLavikをサイジングする。要求の厳しいテールレイテンシターゲットやCPU集約型のコマンドミックスでは、追加のサービング容量が必要になる場合がある。アーキテクチャ上の利点は同じままである。保持データは、DRAM容量のみを通じてノード数を決定する必要がなくなる。16
最初からデプロイメントに可用性を組み込む。VMを適切な障害ドメインに配置し、Meta状態を耐久性のあるディスクに保持する。AzureのローカルNVMeは一時的なストレージであるため、VM間のレプリケーションを外部バックアップとペアにする。レプリケーション、有効期限、および再利用がアクティブな状態でサービングレイテンシを測定し、意図したデータセットサイズでプライマリ障害とフォロワー再構築をリハーサルする。LavikのMetaはトポロジーと権限のためにRaftを使用し、Dataレプリケーションは非同期である。アプリケーションのリカバリポイントとリカバリタイムターゲットをそれに応じて設定し、フェイルオーバードリルでそれらを確認する。291171
RedisShakeを使用して既存のRedisデプロイメントから移行する。コマンドとキーの形状をインベントリし、管理されたLavikターゲットを作成し、ベースラインをコピーし、増分変更を追跡する。カットオーバー前にキー数、値、有効期限を照合する。最終的なキャッチアップのためにソース書き込みを一時停止し、クライアントを切り替え、新しい書き込みを考慮したロールバック手順を維持する。ソースシャード数はターゲットの物理レイアウトを決定する必要はない。リンクされた移行ガイドは、リリースピン留めされた構成と、統合設計を実行可能な移行に変換する手順を提供する。12
7. エージェント状態の成長スペースを与える
保持状態が1TBから10TB以上に成長すると、追加テラバイトあたりのコストが製品制約となる。Lavikは異なる基盤を提供する。Redis互換のNVMeキーバリューストアで、DRAM上のRedisよりも測定されたスループットが高く、効率的な大規模オブジェクトストレージとApache 2.0オープンソースライセンスを備えている。アプリケーションが使用するコマンドから始め、代表的なデータセットをロードし、ユーザーにとって重要なレイテンシ予算を測定する。300のRedisノードから3つのLavikノードへの移行は、ワークロードの実際のコンピューティング需要を中心に構築し、そのデータに成長スペースを与える機会である。610131
ベンチマークとサイジングの注意点
ベンチマーク設定: Azure Standard_L16aos_v4、Japan West zone 2、AMD EPYC 9V74、16論理CPU(SMT付き8物理コア)、125.8GiB RAM、および6つの1.92TB NVMeデバイス。F32als_v6クライアントは、プライベートアクセラレーテッドmlx5ネットワーキングとLinux TCP over 16スレッドを使用する。1000万キーウィンドウは30秒間、相関シードで実行され、10億キーウィンドウは60秒間、異なるシードで実行される。Lavikは8GiBのhugepages、デフラグ有効、ポーリングあたり16完了を使用する。選択されたRedis I/Oスレッド数は、GETとSETで16、ValkeyはGETで16、SETで8を使用する。すべての実行は、データレプリカなしの単一サーバーを使用する。RedisとValkeyはAOFとスケジュール済みスナップショットを無効にする。13
測定詳細: 各曲線ポイントは1つの測定ウィンドウである。レイテンシは、ウィンドウ全体のmemtier結果から取得される。P95は埋め込みHDRヒストグラムからデコードされる。混合ワークロード実験はio_uring、12のLavikワーカーと4つのシステム/IRQ CPU、256のクライアントワーカー、およびレプリカなしの300秒ウィンドウを使用する。これらのレポートは表示されたワークロードをカバーしている。本番環境の選択では、アプリケーション自身の値のサイズ、コマンドミックス、およびレプリケートされたテールレイテンシも測定する必要がある。161315
サイジングとコスト基準: Azure比較では、300のE2s_v4 VMと、2つのL16as_v4データVMおよび1つのE2s_v4 MetaのみのVoterを比較する。両方ともEast US 2でLinux従量課金価格を使用し、月730時間稼働する。年額コストは12ヶ月分である。容量正規化は1つの論理コピーをカウントする。RedisプライマリRAMの2,400GiBとLavik NVMe SSDの3.84TB(両方ともオーバーヘッド前)。対数グラフは、容量が増加するにつれて独立した3VM Lavikデプロイメントユニットを繰り返す。スループット測定は、個別のL16aos_v4ベンチマーク設定を使用する。百万オペレーションあたりのコストは、平均100万QPSを想定している。VM価格には、マネージドディスク、外部バックアップ、トラフィック、人件費、税金は含まれていない。127282913