Snap がフォークを選び、それでも本流に戻った理由
Snap は2022年に買収した Redis のフォーク、KeyDB でキャッシュ基盤の100%を運用していました。2年後に Valkey へ移行した理由を紹介します。

私はデータベースをフォークするつもりはありません。それに必要な勇気と高度な技術力を考えると、気が遠くなります。しかし Snap は実行しました。開発元の会社を買収し、商用コードベース全体をオープンソース化し、何年にもわたってキャッシュ基盤の100%をそこで運用するほど徹底していました。KeyDB は、多くの企業にとって想像するしかない規模で Snapchat を支えていたのです。
それでも、最終的に Valkey へ移行しました。
Unlocked San Jose では、Snap の Principal Software Engineer、Ovais Khan が移行の経緯を紹介しました。どう移行したのかも興味深い話でしたが、それ以上に興味を引かれたのはなぜという点でした。なぜ移行したのか、なぜフォークにとどまる価値がなくなったのか、そして戻る先としてなぜ Valkey を選んだのか。
2019年にフォークを選ぶ合理性
KeyDB は2019年、EQ Alpha Technology の John Sully と Ben Schermel のプロジェクトとして始まりました。発想は単純でした。Redis のイベントループはシングルスレッドです。一方、当時のサーバーには32、64、96個のコアがありました。1台から最大限のスループットを引き出すには、その上で Redis ノードのクラスターを動かす必要がありました。これは非効率でしたが、Redis の生みの親である Salvatore Sanfilippo は変更に反対する考えを公表していました。「私の知る限り、Redis に I/O スレッドを導入することはありません。十分に検討した結果、相応の理由もなく複雑さを大きく増すと考えたからです。」彼はコードベースの簡潔さを積極的に守っていました。
KeyDB は逆の道を選びました。スレッドごとのイベントループと共有状態のロック同期により、本格的なマルチスレッド処理を追加しました。さらに、アクティブ・アクティブレプリケーションと、大規模データセットを低コストで扱う FLASH ストレージも追加しました。同じハードウェアで、Redis の数倍の秒間操作数を処理できました。
これはフォークが必要になる典型的な例です。上流プロジェクトは意図的にアーキテクチャを選択していました。その選択は開発元には正しくても、単一ノードの能力をさらに引き出す必要があった特定のユーザー、つまり Snap には適していませんでした。フォークが唯一の道だったのです。
2021年までに、Snap はキャッシュ基盤の広い範囲で KeyDB を運用し、長期的に関与したいと考えるようになりました。2022年5月にチームを買収し、それまで商用だった KeyDB Pro の機能を BSD-3 ライセンスのオープンソースコードベースに取り込みました。その後およそ2年間、Snap 全体が KeyDB 上で動いていました。
フォークで得られるもの
機能を出す段階では、フォークの利点は明確です。Snap は、自社の運用モデルに重要な機能を得ました。
- マルチスレッドでのコマンド実行により、各ノードの能力をさらに引き出す
- ゾーンを考慮した読み取りルーティングにより、AZ 間トラフィックを抑え、データ転送コストを大幅に削減する
- プロセスの fork を使わないバックグラウンド保存により、メモリ使用量が多い場合もスナップショットの動作を予測しやすくする
- 同一ゾーンのレプリカの動作を調整し、アップグレード中のタイムアウトの影響範囲を縮小する
これらが Snap の望む時期に Redis へ入る見込みはありませんでした。フォークによって、準備ができ次第、自分たちで実装する余地が生まれました。
フォークについてブログやカンファレンスで語られるのは、通常ここまでです。機能が必要だった。上流に断られた。自分で作った。そして動いた。フォークは自由をもたらすように感じられます。
フォークの代償
分岐後に上流の Redis に加わる変更は、すべて判断の対象になりました。移植するのか、書き直すのか、見送るのか。どの判断にも長く続く負担が伴います。移植すれば、マージ競合を引き受け続けます。書き直せば、同じ考えの実装が2つに分かれ、次第に離れていきます。見送れば、フォークは上流の機能をすべて含む存在ではなくなり、別物になっていきます。
Ovais は講演で、この点を具体的に説明しました。Snap は KeyDB の基盤である Redis 6.2 から Redis 7.2 へ簡単には移れませんでした。上流に追随するコストが高くなりすぎ、周囲が先へ進む間、6.2 系にとどまっていたのです。その結果、より広いコミュニティが7.2上に構築した機能も使えませんでした。
エコシステムも同様です。クライアントライブラリ、Operator、監視ツール、ベンチマークは、まず上流でテストされます。フォークの動作が十分に近ければそのまま使えますが、そうでなければ自前で保守し始めることになります。
当初は加速装置のように感じられたフォークが、すぐに足かせになっていきました。
Redis のライセンス変更
2024年3月、Redis Ltd. は Redis のライセンスを BSD-3 から SSPL と RSALv2 のデュアルライセンスへ変更しました。いずれも OSI 承認ライセンスではありません。Redis をマネージドサービスとして提供する企業にとって、これは直ちに問題になりました。AWS、Google Cloud、Oracle、Ericsson は最後の BSD 版である Redis 7.2.4 をフォークし、Linux Foundation に寄贈しました。ライセンス変更の8日後、Valkey が誕生しました。
それまでは、KeyDB にとどまる理由は明白でした。KeyDB チームは Snap 社内にいます。コードベースも自分たちのものです。性能も要件を満たしていました。
しかし Valkey の登場により、立ち止まって考えるようになりました。Linux Foundation 傘下のオープンなガバナンス、複数企業から成る Technical Steering Committee があり、単独で支配するベンダーはいません。BSD ライセンスで、今後も維持されます。ロードマップには Snap がかつてフォークして手に入れた I/O スレッド、デュアルチャネルレプリケーション、そして必要な機能への道筋がありました。主要なクラウドプロバイダーもすべて、本格的に開発へ力を注いでいました。
KeyDB の内部事情も変わりました。2025年1月、最初の開発者である John Sully が Snap を退職しました。KeyDB のリポジトリに残した言葉は明快でした。
「KeyDB を作ったとき、キャッシュは優れた性能を備えるべきだと証明したいと思っていました。それは達成できたと思います。今では多くの選択肢があり、完全にオープンソースの Valkey もその1つです。私のテストでは KeyDB と同等の性能に達しています。Snap がこのプロジェクトをどうするかはわかりませんが、Valkey には明確な勢いがあり、最も新しい状態を保っているので、今後は開発の力を Valkey に移すべきだと思います。」
フォークを始めた本人が役目を終えたと言うなら、そのフォークは役目を終えたのです。
利用者に気づかれない移行
Snap のキャッシュは、バイナリを置き換えるだけでは済まない規模です。アプリケーションチームに影響を見せず、コストを同程度に保ち、大きく異なるワークロードでも安全に移行する必要がありました。Ovais は、移行をできるだけ容易にした主な判断を説明しました。
大規模なワークロード管理の鍵は抽象化層
Snap は各クラスターの前に RESP プロキシを置き、ストレージの抽象化層を構築していました。アプリケーションは KeyDB と直接通信しません。プロキシと通信し、そのプロキシが背後の実装と Redis ワイヤープロトコルでやり取りします。この間接化が移行を可能にしました。これがなければ、Snap のすべてのアプリケーションチームが変更を把握する必要がありました。この層があったため、誰も意識する必要がありませんでした。
この仕組みによって、週に約30個のキャッシュを移行できました。講演時点では、ワークロードの70〜80%が Valkey 上に移っていました。
コードを変える前に機能の差を分析する
Snap は本番環境を変更する前に、KeyDB と Valkey を機能ごとに比較しました。KeyDB のマルチスレッドと Valkey の I/O スレッドは動作が異なるため、同等のスループットが出ることを慎重にベンチマークで確認しました。
KeyDB の一部機能は移行の必須条件で、Valkey へ移植する必要がありました。Snap が最初に貢献したのはゾーンを考慮する機能でした。アップグレード中のレプリカの MOVED 動作や、高負荷時の CPU スロットリングもありました。
かなり後になって判明した隠れた差が、MGET でした。KeyDB はスロットをまたいで対応していましたが、Valkey は対応していません。そのため移行後、大規模なバッチ処理でコマンド解析の負荷が問題になりました。Snap はすぐにクロススロット MGET を社内ビルドへ移植し、上流へ追加するためにコアメンテナーと協力しています。
新しい版ではなく、安定した版を基盤にする
Snap は Valkey 8.2 RC から始め、必要な機能を移植しましたが、すぐに9〜10k QPS でクラッシュに遭遇しました。原因は新しい TLS オフロード処理でした。8.0.2 へ戻し、必要な修正を移植して、そこからベンチマークしました。新リリースには安定性を確かめる期間が必要です。移行中にそれを確かめるべきではありません。
ワークロードを分類し、優先順位を決める
Snap はキャッシュを CPU 制約型、大容量メモリ型、高書き込みレート型の3種類に分けました。それぞれ検証内容が異なります。CPU 制約型では主にスループットを確認します。大容量メモリ型で重要なのは、フル同期中のレプリケーションバッファの動作です。スナップショットの完了前にバッファが埋まると、同期が終わらないループに陥ります。高書き込み型では、レプリカのバッファサイズとプライマリの書き込みスロットリングを調整する必要がありました。Valkey のデュアルチャネルレプリケーションは、プライマリではなくレプリカにバッファを置くためです。各分類の中では、重要度の低いものから着手し、最も重要なものを最後にしました。
一巡して得た教訓
2019年にフォークした判断は正解でした。Redis にマルチスレッドが導入される見込みはなく、Snap のワークロードには必要でした。KeyDB は優れたエンジニアリングによって、単一の Redis 互換ノードの限界を押し上げました。
2025年に戻った判断も正解でした。フォークを正当化していた条件が変わったからです。必要な機能に反対していた上流は、もはや重視すべき上流ではありませんでした。Valkey のガバナンスはオープンです。Snap がかつて単独で進めた作業もロードマップに含まれています。そして Redis 6.2 ベースのビルドを1年使い続けるたびに、エコシステムの進む先との距離が広がっていました。
フォークは選択肢を広げる力であると同時に、負債でもあります。その時点でどちらを積み上げているのか、率直に見極める必要があります。Snap はそうしました。速度を得られるときにフォークし、得られるものよりコストが大きくなったときに戻りました。
フォークは悪いことだ、と受け取ってほしくありません。正しい選択となる場合もあります。フォークという判断は永久ではありません。永久だと考えてしまうと、自社も資金を投じたロードマップに沿って競合が機能を提供する一方で、5年前のコードベースを使い続けることになります。
世界が動いたら、それに合わせて動きましょう。
開発を楽しんでください。