【入門編】 Intset最適化 – Redis

こんにちは!Redisの奥深い世界へようこそ。
今日は、Redisがメモリを極限まで節約するために使っている、ちょっと職人芸的な仕組み「Intset(イントセット)」についてお話ししますね。

「データベースやキャッシュって、なんだか難しそう……」と思うかもしれませんが、心配いりません。
ここをクリアすれば、Redisのメモリ最適化の考え方がグッと身近になりますよ。一緒に楽しくマスターしていきましょう!

—

1. 日常の例え:お財布の中の「小銭入れ」

突然ですが、あなたがお買い物に行くときを想像してください。
お札(1万円札や千円札)を入れる大きなお財布とは別に、コイン(100円玉や500円玉)だけをジャラジャラと効率よく、かつコンパクトに収納する「小さな小銭入れ」を持っていませんか?

大きなバッグにわざわざ仕切りをつけてコインを並べるよりも、専用の小さな革ケースにきれいに並べて入れたほうが、かさばらないし取り出しやすいですよね。

Redisの世界でも同じことが起きています。
Redisはメモリをとても大切にするデータベースですが、「中身がすべて整数(数字)だけの小さなセット(集合)」に出会ったとき、専用のコンパクトな収納ケースを使います。それがIntsetです。

—

2. Intsetとは何か?(普通のSetとの違い)

Redisの基本的なデータ構造である「Set(セット)」は、重複のないデータをたくさん保存するのに非常に便利です。
しかし、通常のSetは、文字でも数字でも、どんな複雑なデータでも柔軟に保存できるように作られているため、実は裏側で少しだけ「大げさな仕組み(ハッシュテーブルなど)」を使っています。

もし、保存したいデータが 「1, 5, 100, 999」 のような整数だけだったらどうでしょう?
わざわざ大げさな仕組みを使うのはもったいないですよね。

そこでRedisは、「整数しか入らないなら、メモリの無駄を極限まで削って、ビルの床板のように隙間なくデータを敷き詰めよう!」と考えました。これがIntsetの本質です。

Intsetの賢いメモリ節約術

Intsetのすごいところは、「入っている一番大きな数字に合わせて、メモリのサイズを自動で伸縮させる」点です。

  • セットの中に小さな数字(例えば `10` や `50`)しかないときは、1つの数字につき「2バイト」という最小限のメモリしか使いません。
  • 少し大きな数字(例えば `30000` など)が入ってきたら、自動的に「4バイト」のサイズにグレードアップします。
  • さらに大きな数字(20億を超えるような数字など)が入ってきたら、「8バイト」に拡大します。

このように、今入っているメンバーの顔ぶれを見て、必要な分のメモリだけをパズルのようにきれいに並べて保持するのです。

—

3. Redisの設定をのぞいてみよう:`set-max-intset-entries`

ここで、Redisの裏側をコントロールする重要な設定をご紹介します。
Redisの設定ファイル(`redis.conf`)には、次のような項目があります。

set-max-intset-entries 512

「これはいいったい何をする設定なの?」と思いますよね。
日本語に訳すと、「Intsetとしてのこぢんまりした優遇を受けられるのは、メンバーが512個までだよ」という意味です。

なぜ制限があるの?

Intsetは「メモリを節約できる」という素晴らしいメリットがある一方で、「数が多くなりすぎると、データの検索や追加に時間がかかるようになる」というトレードオフ(裏表の関係)があります。

Intsetはデータをきれいに一列に並べて保持しているため、新しい数字を追加したり探したりするときに、本を最初からめくるように順番に確認していく必要があるのです(これをエンジニアの世界で「線形探索」と言います)。

もしこれが数万個の数字だったら、順番に探すのに時間がかかってしまいますよね。

だからRedisはこう決めているのです:

  • 「メンバーが512個以下なら、Intsetを使ってメモリを徹底的に節約しよう!」
  • 「512個を超えて大きくなったら、検索スピードを落とさないために、通常の効率的な構造(ハッシュテーブルなど)に変身させよう!」

この絶妙な境界線を決めているのが、`set-max-intset-entries 512` という設定なんです。

—

4. 実際に動かしてみよう

百聞は一見にしかず。実際にRedisを動かして、データ構造の変化を見てみましょう。
(※ここではメモリの使用量を調べるコマンドを使います)

1. 小さな整数をいくつかセットに追加する
127.0.0.1:6379> SADD my_numbers 10 20 30
(integer) 3

2. 中身がどんな構造で保存されているか確認してみる
127.0.0.1:6379> OBJECT ENCODING my_numbers
“intset”

おっ、「`intset`」と表示されましたね!
Redisは今、私たちが追加した `10, 20, 30` という整数を、コンパクトなIntset構造で大切に守っています。

もしここに文字(文字列)を1つでも混ぜたり、設定した数(512個)を超えて大量のデータを詰め込んだりすると、この表示が自動的に別の高速な構造へと切り替わります。Redisは裏側で、私たちの使い方に合わせて最適な姿に姿を変えているのです。

—

先輩エンジニアからのまとめ

いかがでしたか?

  • Intsetとは、整数だけを効率よく隙間なく並べて、メモリを極限まで節約する賢い小銭入れのような仕組み。
  • `set-max-intset-entries` は、「メモリ節約(Intset)」と「スピード(通常のSet)」のバランスを取るための境界線の設定。

普段は意識することのない裏側の仕組みですが、こうしたエンジニアたちの「1バイトでもメモリを削って速くしたい!」という工夫の積み重ねのおかげで、Redisは世界中で愛される超高速なデータベースとして動いています。

ここを理解できれば、あなたのRedisに対する解像度はぐっと上がっていますよ。自信を持って次のステップに進んでくださいね!

コメント

タイトルとURLをコピーしました