こんにちは! Redisのメモリ管理、そしてインメモリデータベースとしての極限のパフォーマンスを支える深淵へようこそ。今日は、Redisが誇る隠れた名機能、「Ziplist(ジップリスト)」と、その境界線を決める設定値についてお話ししよう。
「Redisは速い」というのは、君もすでに知っているはずだ。しかし、データをただ詰め込むだけでは、すぐにメモリがパンクしてしまう。数百万、数千万という膨大なキーを扱う現場では、「いかにメモリを節約しつつ、スピードを落とさないか」がエンジニアの腕の見せ所になる。
今回は、その極意である `hash-max-ziplist-entries` や `hash-max-ziplist-value` といった設定値を、初心者にもスッと腑に落ちるように紐解いていくよ。ここをクリアすれば、君もRedisのメモリ構造を操るワンランク上のエンジニアだ。しっかりついてきてほしい。
—
1. Redisのデータ構造は「変身する」?!
まず、Redisの面白い特徴から話そう。
Redisの「ハッシュ(Hash)」や「リスト(List)」といったデータ型は、実は状況に応じて姿形をガラリと変える。
これを日常に例えてみよう。
君が「道具箱」を持っているとする。中身がほんの数個の小さなネジやドライバーだけなら、わざわざ大きな工具箱を使うかい?ポケットや小さなピルケースにまとめて入れたほうが、持ち運びも軽くて場所を取らないよね。
しかし、工具が100個に増え、電動ドリルや大きなハンマーが入ってきたらどうだろう。小さなピルケースでは収まらないし、取り出すのも一苦労だ。だから、頑丈で整理された大きな本格的な工具箱に持ち替えるはずだ。
Redisもこれと全く同じことをしている。
- データが小さくて少ないとき(ピルケース): メモリを極限まで圧縮して節約する、コンパクトな特別構造(これが Ziplist だ!)を使う。
- データが大きく、または多くなったとき(本格的な工具箱): 検索や追加が圧倒的に速い、本格的な辞書のような構造(ハッシュテーブルやスキップリスト)に自動で「変身(昇格)」する。
—
2. Ziplist(ジップリスト)って一体なんだ?
通常のRedisのデータは、それぞれが独立したメモリの領域を陣取っている。これだと、小さなデータがたくさんあるときに、データの管理情報(オーバーヘッド)だけでメモリが無駄食いされてしまうんだ。
そこで登場するのが Ziplist(圧縮リスト)。
これは、複数のデータを「切れ目のない一本のパンのようにつなげて」メモリ上にギュッと連続して配置する仕組みだ。
- メリット: ポインター(矢印)をあちこちに向ける必要がないため、メモリの無駄が一切ない。CPUのキャッシュ効率も爆上がりする。
- デメリット: 途中のデータを書き換えたり追加したりするときに、パン全体を少しずらしたり作り直したりする必要があるため、データが大きすぎると逆に遅くなる。
つまり、Ziplistは「小さいうちは最強だが、大きくなると息切れする」という性質を持っているんだ。
—
3. 変身のタイミングを決める「ボーダーライン」
「じゃあ、いつピルケースから本格的な工具箱に持ち替えるの?」という疑問が湧くよね。
その境界線を決めているのが、今回主役となる設定値たちだ。
Redisの設定ファイル(`redis.conf`)を覗くと、こんな項目が並んでいる。
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
怖がらなくていい。一つずつ、優しく分解して見ていこう。
① `hash-max-ziplist-entries` (エントリ数の上限)
- 意味: 「ハッシュの中に、要素がいくつまでならZiplistを使っていいか」の限界数。
- デフォルト: `512`
- 解説: 要素の数が512個以下なら、まだピルケース(Ziplist)でいようぜ、という意味だ。これを超えて513個目の要素が入ろうものなら、Redisは一瞬で本格的なハッシュテーブルへと変身する。
② `hash-max-ziplist-value` (文字数の上限)
- 意味: 「ハッシュの中にある一つの値が、何バイト(文字)までならZiplistに許容するか」の限界サイズ。
- デフォルト: `64` (バイト)
- 解説: たとえ要素数が10個と少なくても、中身の文字数が「64バイト(だいたい半角英字64文字)」を超えるような巨大な文章だったらどうだろう? 大きなデータが混ざるとZiplist全体の効率が落ちるため、このルールに引っかかった瞬間、Redisは変身を決断する。
—
4. 実務でどうチューニングすべきか?
「じゃあ、設定をめちゃくちゃ大きくして、何でもかんでもZiplistに押し込めばメモリ節約になって最強じゃん!」
……と思ったそこの君、鋭いけれど、それは危険な罠だ。
エンジニアとしての極意を授けよう。
Ziplistはメモリを節約する代わりに、CPUに少しだけ負荷をかける(データをいじるときに全体を再配置するコストがかかる)。
- メモリを極限までケチりたい場合(IoTデバイスや、参照がメインで書き換えが少ないシステム):
この値を少し大きめに設定し、Ziplistで粘る領域を広げる。
- スピードや同時書き込みの軽快さを最優先したい場合(超高速なカウンターや、ひっきりなしに更新が入るセッションストア):
値を小さめにし、早めに本格的な構造へ変身させることで、CPUの負担を逃がす。
基本的には、デフォルト値(Entries: 512, Value: 64)は世界中の天才たちが絶妙なバランスで導き出した黄金比なので、特別な理由がない限り、むやみにいじる必要はない。ただ、扱うデータが「やたらと文字数の長いハッシュばかり」だとか「要素数が数千個あるのにメモリが常にカツカツ」という現場に出くわしたとき、この設定を思い出すだけで、ボトルネックを華麗に解決できるようになるはずだ。
—
まとめ
ここをクリアすれば、Redisの基本はバッチリマスターできたと言っていい!
1. Redisはデータの規模や大きさによって内部構造を自動で変身させる。
2. Ziplistはメモリを極限まで圧縮するコンパクトな構造だが、大きくなりすぎると逆に苦手になる。
3. `hash-max-ziplist-entries` と `hash-max-ziplist-value` は、その「変身のタイミング」を決める重要な舵取り役である。
メモリとスピードのトレードオフをコントロールできるようになると、インフラを触るのが何倍にも楽しくなる。日々の開発で「お、いま裏側でZiplistからハッシュテーブルに変身したな」なんて想像できるようになったら、君やり手のエキスパートの仲間入りだ。
さあ、次のRedisの深淵へ、共に出発しよう!
コメント