【入門編】 OOM発生時の挙動と対策 – Redis

やあ、こんにちは!Redisの世界へようこそ。
日々開発を頑張っている皆さんに、今日はRedisを運用する上で絶対に知っておきたい「メモリがパンクした時の話」をお伝えしますね。

「Redisが急にエラーを吐いて動きません!」
「アプリケーションの書き込みが全部失敗しています!」

現場でこんな悲鳴が聞こえてきた時、裏で起きているのが今回解説するOOM(Out of Memory:メモリ不足)という現象です。

一見怖そうに思えますが、仕組みと対策さえ知っていれば何も恐れることはありません。日常の出来事に例えながら、一緒に紐解いていきましょう。ここをクリアすれば、Redisの基本はバッチリマスターできますよ!

—

1. Redisの「お片付け限界」と `maxmemory` の仕組み

まずは、Redisがどうやってメモリを管理しているのか、日常の「冷蔵庫」に例えて考えてみましょう。

Redisは、データをすべて「メモリ(RAM)」という超高速な場所で管理しています。これは例えるなら、「食材をパッと取り出せる小さめの最新式冷蔵庫」です。

しかし、冷蔵庫には入れられる限界の量がありますよね。この限界値をRedisの設定では `maxmemory`(最大メモリ量)と呼びます。

メモリが一杯(100%)になった時に何が起きる?

冷蔵庫がパンパンの状態で、あなたが「新しいケーキ」を買ってきたとします。この時、Redisには大きく分けて2つの行動パターンがあります。

1. 古い食材を捨てて、新しいケーキを入れる(お片付け:エビクションポリシー)
2. 「もう入らないよ!」と断る(書き込み拒否:OOMエラー)

Redisの設定で「勝手に食材を捨てないでね(`noeviction`)」という安全設定にしている場合や、捨てるべき古いデータが残っていない場合、Redisは悲鳴を上げます。

(error) OOM command not allowed when used memory > ‘maxmemory’.

これがOOMエラーの正体です。
Redisは「これ以上新しいデータを書き込むコマンド(SETやHSETなど)は受け付けない!」と一線を引くのです。

ポイント:読み込みはできる!

面白いのは、「データの参照(GETなど)」は拒否されないという点です。
「冷蔵庫に新しいものは入れられないけれど、今中にあるものを取り出して食べる(読む)ことはできる」わけですね。本質を押さえたとても賢い設計だと思いませんか?

—

2. アプリケーション側でのエラーハンドリング

では、Redisから「もう無理です!」とOOMエラーが返ってきた時、私たちが作っているアプリケーション(Webサイトやスマホアプリの裏側)はどう振る舞うべきでしょうか?

何も対策をしていないと、Redisのエラーがそのまま画面に表示されてユーザーが困惑してしまったり、アプリ全体がガラガラと崩れて停止してしまったりします。

優しさと強さを備えたコードを書こう

大切なのは、「Redisが使えないなら、本家のデータベース(MySQLやPostgreSQLなど)を見に行く」というバックアッププラン(フォールバック)を用意しておくことです。

Redisはいわば「素早さが自慢のサブの棚」であり、本家のデータベースは「少し遅いけれど大容量の巨大な倉庫」です。棚が一杯なら、少し遠くても倉庫へ取りに行けば良いのです。

具体的な処理の流れを、Pythonのシンプルなコードで見てみましょう。

import redis

Redisへの接続設定
r = redis.Redis(host=’localhost’, port=6379, db=0)

def get_user_profile(user_id):
“””
ユーザーのプロフィール情報を取得する関数
“””
cache_key = f”user:{user_id}”

# 1. まずは高速なRedis(冷蔵庫)を見に行く
try:
cached_data = r.get(cache_key)
if cached_data:
print(“Redisから超高速でデータを取得しました!”)
return cached_data
except Exception as e:
# Redis接続エラーなどのハンドリング
print(f”Redisアクセス時に問題が発生しました: {e}”)

# 2. Redisに無ければ本家のデータベース(巨大倉庫)から取得
print(“データベースから取得します…”)
user_data = fetch_from_main_database(user_id)

# 3. 取得したデータを次回のためにRedisへ書き込もうとする
try:
# データをRedisに保存(ここがOOMで失敗する可能性がある!)
r.set(cache_key, user_data, ex=3600) # 1時間有効
except redis.exceptions.ResponseError as err:
# ★ここが重要!OOMエラー(書き込み拒否)を優しく受け止める
if “OOM” in str(err):
print(“【警告】Redisのメモリが一杯です!キャッシュ保存をスキップして処理を続行します。”)
# 書き込めなくてもアプリを止めず、そのままユーザーデータを返してあげる
else:
# その他のエラーの場合
raise err

return user_data

def fetch_from_main_database(user_id):
# 本家のデータベースから値を取ってくる疑似関数
return f”{{‘id’: {user_id}, ‘name’: ‘Alice’}}”

ここがプロのポイント!

Redisへの書き込み(`r.set`)がOOMで失敗しても、「キャッシュに保存できなかっただけ」と割り切って、アプリのエラーにせず処理を続行させている点です。
ユーザーから見れば「少し表示が遅くなったかな?」くらいで済み、サービスは止まりません。これが倒れないシステムを作る秘訣です。

—

3. 事故を未然に防ぐ!監視アラートの設計指針

そもそも、RedisがパンクしてOOMエラーを出す前に気づきたいですよね。
そのために設定するのが「監視アラート」です。

日常で例えるなら、「お部屋のスマートゴミ箱が8割埋まったらスマホに通知が来る仕組み」を作るようなものです。

どのタイミングでアラートを鳴らすべきか、おすすめの「3段階アラート指針」を紹介しますね。

[ メモリ使用量 ]
100% ———————— 💥 OOM発生(書き込み停止!)
90% ———————— 🚨 危険(Critical):今すぐ対応が必要!
80% ———————— ⚠️ 警告(Warning):原因調査をスタート
70% ———————— ℹ️ 注意(Info):そろそろお掃除の時期
0% ———————— 🌱 正常

監視すべき2大指標

監視ツール(DatadogやPrometheus、AWS CloudWatchなど)を使う際は、Redisの `INFO memory` コマンドで取れる以下の2つの数字をチェックします。

1. `used_memory`(現在使っているメモリ量)

  • 今、Redisの中にどれくらいデータが詰まっているか。

2. `maxmemory`(上限メモリ量)

  • 設定した限界値。

アラート設定のゴールデンルール

  • 警告(Warning):メモリ使用率 70%〜80% に達した時
  • 対応内容: 急激にデータが増えていないか調査します。不要なデータが残り続けていないか(有効期限 `TTL` のつけ忘れなど)を確認する時間的余裕があります。
  • 危険(Critical):メモリ使用率 90% に達した時
  • 対応内容: 担当エンジニアのスマホを鳴らします。メモリの増設(スケールアップ)や、手動での古いデータの削除(`FLUSHALL` は危険なので慎重に!)を即座に検討します。

「パンクする直前(99%)」でアラートを設定すると、エンジニアが気付いて対応する前に100%に達してOOM事故になってしまいます。余裕を持った80%でのアラートが、あなたとチームを救いますよ。

—

まとめ

今回の学びを振り返ってみましょう。

1. `maxmemory` に達すると?

  • Redisは無理な書き込みを断り、`OOM command not allowed` エラーを出して自分自身を守る。(でも読み込みはできる!)

2. アプリ側の対策は?

  • 「Redisへの保存に失敗しても、本家DBのデータを使ってアプリを止めない」優しさと粘り強さを持つ。

3. 運用・監視のコツは?

  • メモリ使用量80%の段階でアラートを飛ばし、パンクする前に余裕を持って対処する。

インフラとアプリケーションの両面から「限界が来たときの挙動」を理解しておくと、トラブルが起きても冷静に対処できるようになります。

ここまでの流れを理解できれば、Redisのメモリ管理の基本はバッチリマスターですよ!自信を持って、安全で高速なWebアプリケーションを作っていってくださいね。応援しています!

コメント

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