こんにちは!Redisの奥深い世界へようこそ。
今日は、現場のエンジニアなら誰もが一度はヒヤリとするテーマ、「OSのスワップ発生時の挙動」についてお話しします。
「Redisは超高速なインメモリデータベースだ!」と聞いて使い始めたものの、ある日突然、アプリから「タイムアウトです!」と悲鳴が聞こえてくる……。その裏で何が起きているのか。
今回は、専門用語をできるだけ使わず、私たちの日常の感覚に置き換えながら、そのメカニズムと対策を優しく、かつ本質的に解説していきますね。ここをクリアすれば、あなたもRedisのメモリ管理の急所をバッチリマスターできますよ!
—
1. 例え話:超高速な「作業机」と、絶望的に遅い「遠くの倉庫」
まず、Redisがなぜあんなにも速いのか、その秘密を「机の上の作業」に例えてみましょう。
- メモリ(RAM):あなたの目の前にある広くてめちゃくちゃモノが取り出しやすい作業机です。
- ディスク(SSD/HDD):オフィスの一番奥、あるいは別の階にある巨大な段ボール倉庫です。
Redisは、すべてのデータ(顧客情報やセッションなど)を「目の前の作業机(メモリ)」の上だけに広げて仕事をすることで、一瞬のレスポンスを実現しています。
では、「スワップ(Swap)」とは何か?
もし、机の上のスペースがいっぱいになっているのに、次から次へと新しい仕事(データ)が舞い込んできたらどうなるでしょう?
机の上がパンクしてしまいますよね。そこでOS(オペレーティングシステム)という「おせっかいな管理人」がこう言います。
> 「おや、しばらく使っていない書類があるな。よし、スペースを作るために、あの書類を『遠くの倉庫(ディスク)』の片隅に一時的に片付けて(退避させて)おこう」
この、「メモリがいっぱいになったから、使っていないデータを一時的にハードディスクの領域(スワップ領域)に追い出す現象」を、OSのスワップと呼びます。
—
2. なぜRedisがスワップされると「地獄のレイテンシ悪化」が起きるのか?
「使っていないデータを片付けてくれたなら、机がすっきりして良いことじゃないの?」と思った方、鋭いですね。一般的なアプリならそれで問題ありません。
しかし、Redisにとってはこれが「死活問題」になります。その理由は2つあります。
① Redisは「すべてが机の上にある前提」で作られている
Redisは、データをすべてメモリ(作業机)に置くことで、マイクロ秒単位の超高速な応答を叩き出しています。
もし、あるユーザーから「さっきのデータを出して!」と言われたとき、そのデータが「遠くの倉庫(スワップ領域)」に追いやられていたらどうなるでしょうか?
1. 「ええっと、あのデータは倉庫のどこだっけ……?」と探しに行く。
2. ディスクからデータを引っ張り出して、机の上のスペースを空けて、古いものをまた倉庫に押し出す(ページイン/ページアウト)。
3. この一連の作業の間、Redisは完全に硬直(フリーズ)します。
② Redisの「シングルスレッド」という性格
Redisの頭脳は、基本的に「1つの作業員(シングルスレッド)」で動いています。
つまり、この作業員は同時に複数のことを処理できません。たった1つのデータがスワップアウトされていたがために、そのデータの取り出しに数ミリ秒〜数百ミリ秒(コンピュータの世界では永遠のような時間です)ブロックされてしまうと、後ろに並んでいる数千件のリクエストの処理がすべてストップしてしまいます。
結果として、アプリケーション全体が固まったような状態になり、ユーザーに「エラー」や「激しい遅延」として跳ね返ってくるのです。これが、スワップ発生時のレイテンシ悪化のメカニズムです。
—
3. 魔の設定「vm.swappiness」の正体
LinuxというOSには、この「いつ、どれくらいのタイミングでスワップさせるか」の度合いを決める設定があります。それが `vm.swappiness` です。
- 設定値の範囲:`0` 〜 `100`
- デフォルト値:多くのLinuxディストリビューションでは `60` など、わりと積極的にスワップさせようとする値になっています。
日常の例えで言うと…
- `swappiness = 60`(おせっかいな管理人)
「机の上がまだ少し空いてるけど、念のため古い書類はすぐ倉庫に片付けちゃおうっと!」と、少しでもメモリに余裕がなくなると、すぐにデータをディスクに追い出そうとします。Redisにとっては大迷惑です。
- `swappiness = 0` または `1`(頑固な職人)
「机の上が完全にパンクして、もうこれ以上モノが置けない!という限界が来るまで、絶対に倉庫には行かない!」と、極限までメモリにしがみつきます。
Redisを使うサーバーでどう設定すべきか?
Redisの公式ドキュメントでも強く推奨されていますが、Redisを動かす本番サーバーでは、この `vm.swappiness` を `0` または `1` に極限まで下げておくのが鉄則です。
OSが勝手に「良かれと思って」Redisのデータをスワップ領域に追い出すのを防ぐためですね。
—
4. 現場のシニアが教える、本当の解決策
`vm.swappiness` を下げるのは大切な第一歩ですが、それだけでは根本的な解決になりません。メモリが足りなければ、いずれ本当にパンクしてしまいます。
現場のエンジニアとして、以下の3つを必ずセットで実践してください。
1. メモリの最大値(`maxmemory`)を正しく設定する
Redisの設定ファイル(`redis.conf`)で、OSの物理メモリの限界値よりも少し少なめに最大使用量を指定しておきます。
# 例: メモリの上限を 4GB に制限する
maxmemory 4gb
2. あふれた時のポリシー(`maxmemory-policy`)を決めておく
万が一メモリがいっぱいになったとき、どうするか?をあらかじめ決めておきます。
- `noeviction`(デフォルト):これ以上入らないよ!とエラーを返す(スワップするよりマシですが、アプリはエラーになります)
- `allkeys-lru`:最近使っていない古いデータから自動的に削除(お掃除)していく
多くのキャッシュ用途では、LRU系のポリシーを設定しておくことで、メモリ溢れによるスワップを防ぐことができます。
3. モニタリングを怠らない
「INFO memory」コマンドなどで、メモリの使用率やスワップが発生していないかを常に監視しましょう。
—
まとめ
いかがでしたでしょうか?
- Redisにとってスワップは「死(フリーズ)」を意味する。
- OSのおせっかい(`vm.swappiness`)を抑え込み、メモリの限界値できちんとコントロールする。
この2つを意識するだけで、あなたのシステムの安定性は劇的に向上します。
「なぜ動くのか」「どこがボトルネックになるのか」の本質が見えてくると、Redisを触るのがますます楽しくなりますよ。
それでは、快適なRedisライフを!次回の技術解説もお楽しみに。
コメント