こんにちは!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の出番だな」と自信を持って選択できるようになります。
アーキテクトとして、あなたがこうした引き出しを一つずつ増やしていく姿を、心から応援しています。
それでは、また次回の深い技術の海でお会いしましょう!
コメント