こんにちは!Redisのメモリ管理、特に「バックアップを取るときにメモリが急増してヒヤッとした…」なんて経験はありませんか?
今回は、Redisがデータファイルをディスクに保存する仕組みである RDB(Redis Database) と、その裏側でこっそり行われている Copy-on-Write(コピー・オン・ライト) という技術について、徹底的に紐解いていきます。
ここをクリアすれば、Redisのメモリの動きはバッチリマスターできますよ。難しい専門用語はできるだけ排除して、日常のたとえ話を交えながら優しく解説していくので、リラックスして読んでいってくださいね。
—
1. カフェの店長と「レシピノート」のたとえ
まずは、Redisがデータをどう扱っているか、街の人気カフェを想像してみてください。
このカフェには、常連客の注文履歴や好みをすべて記憶している超優秀な店長(Redis)がいます。店長は、自分の頭の中(メインメモリ)だけで仕事をしています。頭の中なので仕事のスピードは超特急です。
しかし、夜になって店を閉めるとき、あるいは万が一の停電に備えて、今日のデータをノート(ハードディスク)に書き残しておかなきゃいけませんよね。これがRedisでいうRDBの保存(スナップショット)です。
ここで問題が発生します。
店長は日中も大忙しで接客を続けています。分厚いノートに今日のデータを全部書き写すには、何分もかかってしまいます。その間、お客さんを待たせるわけにはいきませんよね。
さあ、店長はどうするでしょうか?
—
2. 分身の術!「Copy-on-Write」の魔法
ここでRedis(店長)が使うのが、「Copy-on-Write(コピーツーライト)」という、ちょっとずる賢くてスマートな技です。日本語に訳すと「書き込み時コピー」ですね。
店長は、ノートを書き写すために自分そっくりな「アルバイト君」を影武者として呼び出します。
1. まずはコピー(正確にはコピーのフリ)
店長は、自分の頭の中にある記憶の全体像を、一瞬でアルバイト君に共有します。ただし、最初から全部の情報をノートに書き写すわけではありません。「今の記憶の地図」だけをパッと渡すイメージです。この瞬間は、メモリの消費量はほとんど増えません。
2. 裏でコツコツ書き出し
アルバイト君は、もらった地図を頼りに、裏の部屋でゆっくりノートにデータを書き写していきます。店長はというと、そんなことは気にせず、目の前のお客さんの対応(データの読み書き)を続けます。
3. 「書き換え」が起きたときだけ動く
ここが最大のポイントです。アルバイト君がノートに書き写している最中に、常連のAさんがやってきて「注文をカフェラテからカプチーノに変えて!」と言いました。店長は頭の中のデータを書き換える必要があります。
このとき、店長はこう考えます。
「おっと、アルバイト君がまだ書き写していない部分の記憶を勝手に変えちゃうと、ノートに書く内容とズレちゃうな……よし、この『変えなきゃいけない部分』だけは、新しく自分の頭の中に専用のメモ用紙を用意して、そこを書き換えよう!」
この、「実際に書き換え(Write)が起きるまで、コピー(Copy)を後回しにする」仕組みこそが、Copy-on-Writeなのです。
—
3. 【現実のRedis】書き込み負荷が高いとどうなる?
この「Copy-on-Write」の仕組み、普段はメモリを節約できて非常に優秀な機能です。
しかし、「書き込み負荷が高い環境」、つまり日中にお客さんが次々と注文を変えまくるような大忙しの状況下で `BGSAVE`(バックアップの命令)を実行すると、思わぬ罠が待っています。
アルバイト君がのんびりとノートに書き写している横で、店長が次から次へと「あ、ここも変えて!」「そこも書き換えて!」と記憶を新しくし続けたとします。
そうするとどうなるでしょうか?
- 変えなければいけない記憶のパーツがどんどん増えていき、店長の頭の中には「新しく書き換えたメモ用紙」が山積みになっていきます。
- 結果として、Redisが使っているメモリの量が、元のデータサイズの何倍にも膨れ上がってしまうのです。
これが、実務でよくある「RDB保存中にメモリが足りなくなってサーバーがクラッシュする(あるいはOSのメモリ管理機能に強制終了させられる)」という現象の正体です。
—
4. チーフアーキテクトからの実務アドバイス
この問題を防ぐために、現場のプロたちは次のような対策をとっています。ここを押さえておけば実務でも安心です。
① 空きメモリ(ヘッドルーム)を常に確保する
Redisを動かすサーバーのメモリは、今あるデータの大きさぴったりに設定してはいけません。Copy-on-Writeによる一時的な急増を見込んで、少なくともメモリの30%〜50%程度の余裕(空き容量)を残しておくのが鉄則です。
② 最大メモリ制限(maxmemory)とポリシーを設定しておく
もしメモリが限界に達しそうなとき、何もしないとサーバー全体がダウンしてしまいます。あらかじめ `maxmemory` を設定し、溢れそうなときは古いデータを自動で削除する設定(LRUなど)を組み合わせておきましょう。
③ 書き込みがピークの時間帯を避ける
アクセスが集中してデータが激しく書き換わっている最中に、無理に重いバックアップ(BGSAVE)を走らせるのは自殺行為です。アクセスが落ち着く夜間などにスケジュールをずらす配慮をしましょう。
—
まとめ
- RDB保存(BGSAVE) は、裏でバックグラウンドのプロセスを作ってデータをディスクに書き出す機能。
- その裏側では Copy-on-Write という「書き換えられた部分だけメモリを複製する」賢い仕組みが動いている。
- しかし、保存中にデータの書き換えが頻発すると、メモリ消費量が跳ね上がり、最悪の場合はクラッシュするリスクがある。
仕組みの本質さえ分かってしまえば、Redisのメモリ管理は決して怖くありません。ぜひ今日の知識を、日々の運用や設計に活かしてみてくださいね。
それでは、快適なRedisライフを!
コメント