【入門編】 HyperLogLogのメモリ固定化 – Redis

こんにちは!Redisの奥深い世界へようこそ。チーフアーキテクトの私です。

今回は、数あるRedisの機能の中でも、ひときわ異彩を放つ「HyperLogLog(ハイパーログログ)」というデータ構造についてお話しします。

「名前からして難しそう…」と思いましたか?
大丈夫です。一歩ずつ、日常の例えを交えながら、本質を優しく解きほぐしていきますね。ここをクリアすれば、あなたもRedisのメモリ管理の面白さにグッと近づけますよ。

—

1. 想像してみてください:数百万人の「ユニークユーザー」を数える地獄

Webサービスを運営していると、「今日、何人の『異なる』ユーザーがサイトにアクセスしたか(いわゆるユニークユーザー数 / UU)」を知りたくなる場面が必ず来ます。

もし、あなたがこの集計を任されたらどうしますか?
素直に考えると、アクセスしてきたユーザーのIDをすべてリスト(集合)に記録し、あとから「重複を省いて数える」という方法をとるはずです。

【普通のやり方(正確な集計)】
アクセス:「Aさん」「Bさん」「Aさん」「Cさん」「Bさん」
リスト化:[“A”, “B”, “C”] (重複を消す)
人数:3人!

一見、うまくいきそうですよね。でも、考えてみてください。
もしこれが、毎日1,000万人が訪れる巨大なサービスだったらどうでしょう? 1,000万人分の文字列IDをメモリに保存し続けたら、メモリはあっという間にパンクしてしまいます。正確さを求め代償に、サーバーのCPUもメモリも悲鳴を上げる……これが「正確なカウントのジレンマ」です。

「だいたいの人数でいいから、もっと省メモリで爆速に数えられないものか……?」
そんなエンジニアの切実な願いから生まれたのが、今回主役のHyperLogLogなのです。

—

2. 日常で例えるなら:「水たまりのしぶき」からの推測

HyperLogLogがやっていることを、日常の例えで説明しましょう。

ここに、雨上がりの大きな水たまりがあるとします。たくさんの人がその上を歩いていった足跡がついています。「今日、何人の人がここを通ったのだろう?」と正確に数えるのは至難の業です。

そこで、あなたはこう考えました。
「全員の顔を覚えるのは無理だけど、みんなが泥を跳ね飛ばした『しぶき』のパターンを観察すれば、だいたいの人数が当てられるんじゃないか?」

  • 1人だけなら、しぶきは小さく、パターンも単調です。
  • 100人、1,000人と増えるにつれて、ありえないような「珍しいハプニング的なしぶき(遠くまで飛んだ泥など)」が混ざるようになります。

HyperLogLogは、まさにこれと同じことをやっています。データをそのまま保存するのではなく、データが持つ「ハッシュ値(ランダムな文字列の変換結果)」のパターンを極限まで要約し、「珍しい現象が起きたかどうか」だけを記録するのです。

—

3. なぜ「12KB」しか使わないのか?(メモリ固定化の魔法)

ここが最大のポイントです。HyperLogLogの最大の特徴は、要素が何個増えようとも、消費するメモリの量が「常に最大12KB(キロバイト)」でピタッと固定されるという点です。

100個の要素を入れようが、1,000万個入れようが、1億個入れようが、サイズは変わりません。

なぜそんな魔法のようなことができるのでしょうか?
それは、HyperLogLogが保持しているのが「個別のデータそのもの」ではなく、「観測されたデータのハッシュ値の偏りを示す、固定長のレジスタ(メモリーブロック)」だけだからです。

マンションの郵便受けを想像してください。マンションの世帯数が何人になろうとも、郵便受けの「個数」自体は建てられた時から変わりませんよね。それと同じで、Redis側であらかじめ確保された固定のマス目(12KB分)に、データの傾向をどんどん上書きしていくイメージです。

Redisで実際に動かしてみましょう。

HyperLogLogに次々とアクセスユーザー(のハッシュ等)を記録するコマンド:PFADD
127.0.0.1:6379> PFADD today:visitors “user_001” “user_002” “user_003”
(integer) 1

何人いるか概算を出すコマンド:PFCOUNT
127.0.0.1:6379> PFCOUNT today:visitors
(integer) 3

仮にここに1,000万件のデータをブッコんでも、メモリ使用量は約12KBのまま変わりません!

—

4. 知っておくべきトレードオフ:「だいたい」の代償

「じゃあ、すべてのデータをHyperLogLogに任せればいいじゃないか!」と思ったあなた、鋭いですが、世の中そんなに甘くありません。

ここでトレードオフ(代償)の話をします。
HyperLogLogは、メモリを極限まで節約する代わりに、「わずかな誤差(通常は約1%未満)」を受け入れています。

つまり、本当は「1,000,000人」アクセスがあったとしても、HyperLogLogの答えは「995,432人」だったり「1,005,120人」だったりするわけです。

どんな場面で使うべき?

  • 向いている場面:

リアルタイムなPV(ページビュー)のユニークユーザー数、SNSの「いいね!」のユニーク数、大規模なログ解析など。「およその傾向がリアルタイムにわかれば、数パーセントの誤差は全く問題ない」というシーン。

  • 向いていない場面:

ECサイトの「在庫数」や、銀行の「残高」など、1円・1個の狂いも許されないデータ管理。

—

まとめ:道具を正しく使い分ける知性

いかがだったでしょうか?
HyperLogLogは、「正確性を少し手放すことで、メモリ無限地獄から私たちを救ってくれる、最高にクールな確率的データ構造」です。

  • 要素数が増えてもメモリは常に最大12KB固定
  • 裏側ではデータのパターン(しぶき)を数えて確率的に算出している
  • 1%未満の誤差があるため、厳密なカウントが必要な場所には使わない

この本質さえ押さえておけば、実務で巨大なデータを扱う際も「ここはHyperLogLogの出番だな」と自信を持って選択できるようになります。

アーキテクトとして、あなたがこうした引き出しを一つずつ増やしていく姿を、心から応援しています。
それでは、また次回の深い技術の海でお会いしましょう!

コメント

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