Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】Valkey 9.1's hash field TTL triples memory use for the pattern its own docs show

2026年09月11日に「Dev.to」が公開したITニュース「Valkey 9.1's hash field TTL triples memory use for the pattern its own docs show」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

Valkey 9.1でハッシュのフィールドごとに有効期限(TTL)を設定可能になった。しかし、単一フィールドに使うとメモリ消費が従来の約3倍になる。この機能は、既に多くのフィールドを持つハッシュの一部に適用する際に有効だ。単一値のTTLには、従来の文字列キーがメモリ効率に優れる。

ITニュース解説

Valkey 9.1で導入された新しい機能「ハッシュフィールドごとの有効期限(TTL)」について、その使い方と注意点を解説する。これまでValkey(Redis互換のキーバリュー型データベース)では、データ全体(キー)に対して有効期限を設定する機能はあったが、ハッシュという複数のフィールドを持つデータ型の中で、特定のフィールドにだけ有効期限を設定することはできなかった。この新機能は、例えばユーザーごとの認証トークンなど、ハッシュ内の特定の小さなデータにだけ有効期限を設けたい場合に非常に便利だと期待されていた。特に、Valkey 9.1では「HSETEX」という新しいコマンドが追加され、ハッシュのフィールドを設定するのと同時に有効期限も指定できるようになり、開発者はこの機能を積極的に活用できるようになった。

しかし、筆者が実際にこの機能を試したところ、予想外のメモリ消費量の増加が確認された。Valkeyの公式ドキュメントに示されている「1つのユーザーにつき1つの認証トークンをハッシュで管理し、そのトークンにTTLを設定する」というパターンを検証した結果、従来の「認証トークンを個別の文字列キーとして保存し、それにTTLを設定する」方法と比べて、メモリ使用量が約3倍になるという衝撃的な結果が出た。具体的には、20,000件のデータを保存した場合、文字列キーでは1キーあたり約86.68バイトだったのに対し、単一フィールドのハッシュにTTLを設定すると1キーあたり約261.33バイトを消費した。

このメモリ消費量の増加の原因は、Valkeyが内部でデータをどのように保存しているか、その「エンコーディング」に関係している。Valkeyは、メモリを効率的に使うために、データの形状やサイズに応じていくつかのエンコーディング方式を使い分けている。特に、フィールド数が少ないハッシュや、フィールドのデータが小さいハッシュに対しては、「listpack」という非常にコンパクトな形式でデータを保存する。しかし、ハッシュ内のいずれかのフィールドにTTLが設定されると、たとえフィールドが1つしかなくても、Valkeyはそのハッシュのエンコーディングを「hashtable」という形式に強制的に切り替えてしまう。hashtable形式は、より柔軟なデータ管理や高速な検索に適している反面、listpackに比べてメモリのオーバーヘッドが大きく、より多くのメモリを必要とする。このエンコーディングの変更が、メモリ使用量が大幅に増加する主な理由であると判明した。Valkeyの開発コミュニティでは、この挙動はすでに認識されており、小さいハッシュでもTTLを設定した場合にlistpackを維持できるようにする改善が議論されているが、Valkey 9.1.2の時点ではまだ実装されていない状況だ。

では、この新しいフィールドTTL機能はどのような場合に使うべきなのか。筆者の実験結果は、「ハッシュがすでに複数のフィールドを持っており、listpackではなくhashtableエンコーディングで保存されているようなケース」でこそ、この機能が真価を発揮することを示している。具体的には、フィールド数が多いためにValkeyが自動的にhashtableエンコーディングを選択しているようなハッシュに対して、その中の一部または全てのフィールドにTTLを設定する場合、1フィールドあたりの追加メモリコストはわずか16〜29バイト程度に抑えられる。これは、すでにhashtableエンコーディングによるメモリオーバーヘッドを支払っている状態であれば、フィールドTTL機能の追加コストは非常に小さいことを意味する。したがって、この機能は、単一の有効期限付き値をラップするためではなく、複数のフィールドを持つ既存のハッシュの一部フィールドに柔軟に有効期限を設定したい場合に利用すべきだと言える。

その他の検証結果も重要である。まず、フィールドTTLが設定されていても、通常のハッシュの読み取り操作(HGET)のパフォーマンスにはほとんど影響がないことが確認された。TTLを追跡するための内部構造が、読み取り速度を低下させることはなかった。また、コマンドの使い勝手についても検証された。例えば、ハッシュ型ではないキーに対してHEXPIREコマンドを使おうとするとエラーになること、無効な有効期限を指定できないこと、NX(存在しない場合のみ設定)とXX(存在する場​​合のみ設定)のようなオプションを同時に使えないことなどが示された。一方で、存在しないフィールドやハッシュに対してHEXPIREを呼び出すとエラーではなく「-2」を返し、TTLが無限のフィールドに対してGT(指定時間より大きい場合のみ更新)オプションでHEXPIREを呼び出すと何も起こらないという挙動は、従来のTTLコマンドの慣習と一致していた。

並行処理の観点から見ると、複数のクライアントが同時にField TTLを設定しても、パフォーマンス上のボトルネックは発生しなかった。Valkeyは基本的にシングルスレッドでコマンドを実行するため、複数のクライアントが1つの共有ハッシュキーにアクセスしても、本質的な競合は生じにくい。このテスト結果は、期限切れフィールドを1つの大きなハッシュに集約しても、高負荷下でホットキーのボトルネックになる心配は少ないことを示唆している。

さらに、設定されたフィールドTTLが永続性を持つことも確認された。Valkeyサーバーを再起動しても、TTLはリセットされずにカウントダウンを継続し、期待通りにフィールドが期限切れになった。また、フィールドが期限切れになった際に、Valkeyの統計情報に含まれるexpired_fieldsというカウンターが正しく更新されることも確認された。これは、本番環境でこの機能を利用する際に、フィールドの有効期限切れ状況を監視するための重要な指標となる。

結論として、Valkeyの新しいハッシュフィールドTTL機能は強力だが、そのメモリ効率は利用パターンに大きく依存する。システムエンジニアを目指す初心者は、この機能を使う前に、まず自分のアプリケーションがどのようなデータ構造を必要としているか、そして既存のハッシュがどれくらいのフィールド数を持っているかをよく検討すべきである。単一の有効期限付きデータを保存するだけであれば、従来の文字列キーとEXPIREコマンドを使う方がメモリ効率ははるかに良い。すでに複数のフィールドを持つハッシュがあり、その中で一部のフィールドに有効期限を付けたいという明確なユースケースがある場合にのみ、この新しいフィールドTTL機能の利用を検討することが推奨される。常に、OBJECT ENCODINGコマンドを使って、実際のメモリ使用量やエンコーディングを確認する習慣を持つことが重要だ。

関連コンテンツ

関連IT用語

関連ITニュース