【入門編】 LRUアルゴリズムの実装 – Redis

こんにちは!Redisの世界へようこそ。
今回は、Redisの心臓部とも言える「メモリ管理と最適化」、その中でも特に重要な「LRU(Least Recently Used)アルゴリズム」について、徹底的に解き明かしていきます。

「LRUなんて、教科書通りの用語で難しそう……」なんて身構える必要は全くありません。
実はこれ、私たちの日常生活にめちゃくちゃ近い場所で行われている、とってもシンプルで賢い「お片付けの知恵」なんです。

ここをしっかりとクリアすれば、Redisのメモリ管理の仕組みはバッチリマスターできますよ!それでは、優しく、そして深く、その本質の世界へご案内します。

—

1. なぜRedisには「お片付け」が必要なのか?

まず前提として、Redisはデータの読み書きをものすごく高速に行うために、パソコンの「メモリ(RAM)」という特等席にデータを置いています。

しかし、この特等席の広さは無限ではありません。いつかは満杯になります。
メモリがパンクしかけたとき、Redisはこう考えます。

「新しいデータを置くスペースを作るために、古くて使われていないデータを何か一つ捨てなきゃいけない……どれを捨てよう?」

この「どれを捨てるか」を決めるルールのひとつが、今回主役のLRUアルゴリズムです。

—

2. 日常で例えるLRU:「本棚の整理」

LRUは、「最も長い間使われていない(Least Recently Used)ものから処分する」というルールです。

あなたの部屋にある小さな本棚を想像してください。この本棚には、最大で5冊しか本が入りません。
そこに新しい本が届きました。でも、すでに本棚はパンパンです。さて、どうしますか?

  • 直近で何度も読んでいるお気に入りの本は、すぐ取り出せるように残しておきたいですよね。
  • 逆に、「最後に開いたのはいつだっけ……?」というホコリをかぶった難しい本は、一旦本棚から出して、ダンボール箱にしまいそうです。

この「最後に使ってからの経過時間が一番長いものを追い出す」という仕組みこそが、LRUの本質です。直感的で、理にかなっていますよね。

—

3. 本物のLRUは「贅沢病」?Redisの選択

「なるほど、じゃあ一番古いやつを完璧に探して捨てればいいんだね!」と思ったそこのあなた。さすが鋭い視点ですが、ここに大きな罠があります。

コンピュータの世界で「完全な(真の)LRU」をやろうとすると、ものすごい手間のコストがかかります。
すべてのデータに「最後にアクセスされた正確な日時」を記録し、誰かがアクセスするたびに並び替えを行い、一番古いものを正確に特定する……。

これを数百万件という膨大なデータを持つRedisでやるとどうなるか?
「片付けの計算」に夢中になりすぎて、肝心の「データの読み書き(本来の仕事)」が遅くなってしまうのです。本末転倒ですよね。

そこでRedisの生みの親たちはこう決断しました。
「完璧な一番古いデータじゃなくて、だいたい一番古そうなやつをサクッと選んで捨てよう!」

これが、Redis独自の「近似(きんじ)LRUアルゴリズム」の正体です。

—

4. 近似LRUの仕組みと、神設定 `maxmemory-samples`

Redisは、メモリがいっぱいになって何かを捨てなきゃいけない時、次のようなスマートなサボり方(効率化)をします。

1. メモリ上のデータから、テキトウにいくつか(例えば5個とか)のデータをつまみ食いして選びます。
2. そのつまみ食いしたデータの中で、「一番最後に使われてから時間が経っているもの」を1つだけ選びます。
3. それを容赦なく削除します!

ここで重要になってくるのが、Redisの設定ファイルにある `maxmemory-samples` という項目です。
これは、先ほど言った「一度につまみ食いする数」を指定する設定です。

サンプル数のマジックを知ろう

  • `maxmemory-samples 3` の場合:

3個だけデータを覗いて、その中で一番古そうなものを捨てます。
メリット: 計算が一瞬で終わるので、スピードが最速!
デメリット: もしかしたら、もっと古いデータが別の場所にあるかもしれない(精度はそこそこ)。

  • `maxmemory-samples 10` の場合:

10個のデータを覗いて、その中で一番古そうなものを捨てます。
メリット: たくさん覗く分、「本当により古いデータ」を見つけやすくなり、精度が上がる。
デメリット: ちょっぴりCPUのパワーを使う(とはいえ、人間には体感できないレベルですが)。

公式のベンチマークや実務の現場では、`5` から `10` あたりに設定されることが多く、これが「スピード」と「精度」の絶妙な黄金バランスと言われています。

—

5. 設定してみよう(Redisの設定)

実際にRedisの設定ファイル(`redis.conf`)やコマンドラインで、この挙動をコントロールしてみましょう。

Redisが使用できる最大メモリを 100メガバイト に制限する
maxmemory 100mb

メモリがいっぱいになった時のポリシーを「近似LRUを使った削除」に指定する
maxmemory-policy volatile-lru

捨てる候補を選ぶときの「つまみ食いする数」を 5 に指定する
maxmemory-samples 5

※ `volatile-lru` は、「有効期限(TTL)が設定されているデータの中から、LRUのルールで古いものを探して消す」という実務でよく使われる安全なポリシーです。

—

6. チーフアーキテクトからの実践的なアドバイス

実務でRedisを運用する際、このLRUの仕組みを知っているだけで、障害を防ぐ大きな武器になります。

1. 「完璧を求めない美学」を理解する
RedisのLRUは「厳密な古い順」ではありません。「だいたい古い順」です。この割り切りがあるからこそ、ミリ秒単位の超高速応答が維持できています。厳密な順序が必要な複雑なログ管理などは、他のデータベース(RDBなど)に任せましょう。

2. メモリに余裕を持たせたサイジングを
`maxmemory-samples` をどれだけチューニングしても、そもそも物理メモリがカツカツすぎると、Redisはひっきりなしにデータの削除と追加を繰り返すことになり(キャッシュミス・ストーム)、パフォーマンスが落ちます。常に最大メモリに対して20〜30%の余裕を持たせる設計がプロの技です。

—

まとめ

いかがでしたでしょうか?

  • Redisはメモリを守るために古いデータを捨てる必要がある。
  • しかし完璧な順番を調べると遅くなるので、「近似LRU」という賢い手抜きをしている。
  • その精度の舵取りをするのが `maxmemory-samples` である。

この仕組みが頭に入っていれば、Redisのメモリ管理はもう怖くありません。
日々の開発やインフラ運用で、ぜひこの「知的なサボり方」の美学を活かしてみてくださいね!

コメント

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