MemcachedとRedisについてなんとなくの比較しかしてこなかったので改めて整理

Reference

基本情報の比較
特徴 | Memcached | Redis |
---|---|---|
開発年 | 2003年 | 2009年 |
データ構造 | 単純なキーと値(文字列のみ) | 多様なデータ構造(文字列、リスト、ハッシュ、セット、ソート済みセットなど) |
永続化 | なし(完全揮発性) | オプションで永続化可能(スナップショットまたはAOF) |
マルチスレッド対応 | はい(v1.4以降) | いいえ(シングルスレッド。ただしI/Oはマルチスレッド化可能) |
レプリケーション | なし(外部で対応) | あり(マスター/レプリカ構成が可能) |
クラスタリング | 外部ツールで対応(例:mcrouter) | Redis Clusterを公式サポート |
トランザクション | なし | あり(MULTI/EXEC) |
Luaスクリプト | なし | あり(組み込みでサポート) |
pub/sub機能 | なし | あり |

パフォーマンス比較
項目 | Memcached | Redis |
---|---|---|
スループット | 非常に高速(シンプルな処理向き) | 高速(複雑な処理も可能) |
レイテンシ | 低い | 低い(ただし機能によって増減) |
スケーラビリティ | 良い(キーの分散による) | 良い(Redis Clusterなどで対応) |

利用ケースにおける選択の目安
要件 | 推奨 |
---|---|
単純なキャッシュ(キー/値) | Memcachedが適している |
高機能なデータ構造を使いたい | Redisが適している |
永続化が必要 | Redis |
高度なクエリ、ランキング、統計など | Redis |
メモリ効率重視(非常に単純な用途) | Memcached |

ざっと要点まとめると、
基本Redisのほうができることが多くて、特にストレージへの永続化をしないといけないとか、レプリケーション目的でクラスタ組まないといけないとかならほぼ確Redis使うのが良い。
一方で、Redisはマルチスレッド対応していない(シングルスレッドで動く)ので、単純なGET/SET以外のコマンドを実行するのに、1クライアントの処理で長時間全体の処理がブロックされてしまう可能性があるので、単純なKVSではない使い方をする場合、発行するコマンドによってはパフォーマンスを出しづらい場面もあるため、この場合はMemcachedに軍配が上がる。

memo:シングルスレッドで動作するとは?
クライアントから受けたリクエストの処理を1つのスレッドで処理するということ。
🔍 具体的には
- 1つのクライアントのコマンドを順番に処理する。※つまり並列実行しない
- そのため、CPUコアが複数あってもRedisは基本的には1コアしか使わない。
- 例:1000個のクライアントから同時アクセスされても、内部では1つづつ順番に処理される。
※Redisで並列処理させないといけないとかになったら、複数インスタンスを立てる or クラスタ構成にするのが一般的らしいがこのあたりは調べきれてない

- 揮発性メモリのMemcachedの場合、再起動した際にキャッシュが全て消失してしまうため、このタイミングで一斉にDBや外部API等のoriginサーバへのアクセスが集中してしまうことも視野に入れる必要がある。
- そもそもキャッシュしたいデータとは複雑なデータ(もしくは整形しにくいデータ)であることが前提と考えれるため、負荷のかかりやすいslow-queryになるものが多い。

Thredering herd problem 問題について
以下、キャッシュを利用する際の大まかな通信の流れ
- クライアントによるリクエスト
- バックエンドでリクエストを解析し、キャッシュサーバに問い合わせ
- キャッシュサーバにデータが存在していないため、DBに問い合わせ
- DBから取得したデータをキャッシュサーバに設定
- クライアントにレスポンス返却
だいたい上記のような構成になるが、
前述したとおり、キャッシュに乗せたいデータはつまりは負荷のかかりやすいデータであることが多いため、とくに初回のリクエストなどで、APIエンドポイントは異なれど、それぞれのAPIのロジック内で扱うデータをキャッシュ上のデータを参照するような構成にしている場合は、キャッシュサーバ再起動後の初回リクエスト時に↑の3の処理が多数走ってしまい、結果高負荷な状態に陥ってしまう。
キャッシュサーバを再起動するって運用しててあんまり遭遇したことがないけど、もし定期的に再起動かけないといけないってなった場合はMemcached使いどころむずいなといったところで、そこまで大規模な環境でない場合はRedis使っておくのが無難なのではないかと。

キャッシュサーバを再起動するって運用しててあんまり遭遇したことがないけど、もし定期的に再起動かけないといけないってなった場合はMemcached使いどころむずいなといったところで、そこまで大規模な環境でない場合はRedis使っておくのが無難なのではないかと。
回避策は結構あるなと思い、例えば再起動かける前に別のデータストアにその情報保持しておいて、再起動後にbatch処理か何かで再度設定してあげれば良いねと。と言いつつ、この運用すら冗長だなとか、のちに考えること多そうだなという思いが強い場合は結局のところRedisが無難という結論は変わらないかも。