0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Redisってキャッシュなの? Memcachedと比べながら役割を整理してみた

0
Posted at

はじめに

Redisは「キャッシュで使うもの」としてよく名前が出ます。でもセッションやランキングの実装例にもRedisが登場します。
調べてみると、Redisを理解するには「キャッシュ」と「Redis」を同じものとして考えない方が分かりやすいと気づきました。そこでMemcachedと比べながら、何が同じで何が違うのかを整理してみます。

TL;DR

  • キャッシュは役割で、Redis / Memcachedはその役割を担える具体的なストア
  • Redisはストア側に豊富な操作とデータ型を持つため、キャッシュ以外の用途にも広げやすい
  • 「Redisの方が高機能だから」ではなく、必要な操作・データ型・運用要件から選ぶ

1. Redis = キャッシュではなかった

Redisを調べるとき、最初に分けた方が分かりやすかったのが、キャッシュという役割データを置く具体的なストアです。ここを同じものとして考えると、「Redisはキャッシュなのに、なぜセッションやランキングにも使うの?」という疑問が出てきます。

キャッシュは、同じ結果を再利用して高い処理を繰り返さないための仕組みです。たとえばDBから取得した商品情報を一時的に保存しておき、次のリクエストではDBまで行かずに返す。これはRedisを使わなくてもできます。アプリケーション自身のメモリへ置くこともできますし、HTTPの仕組みとしてブラウザやCDNでレスポンスを再利用することもあります。

image.png

RedisやMemcachedは、こうしたキャッシュの保存先として使えるソフトウェアです。どちらも主なデータをRAM上で扱うため、In-memory Store(主なデータをメモリ上で扱うストア) と呼ばれます。RAMはSSDなどの永続ストレージより高速に読み書きできるので、短い待ち時間でデータを取り出しやすいのが特徴です。

さらに、アプリケーションのプロセス内部へデータを置く場合と違い、RedisやMemcachedは独立したサーバーとして動かせます。複数のアプリケーションインスタンスから同じストアへアクセスできるので、共有ストアとして使えるわけです。

ここまで整理すると、Redisは「キャッシュという概念そのもの」ではなく、キャッシュとしても使えるインメモリストアだと考える方が自然でした。では、同じようにキャッシュで使われるMemcachedは何が違うのでしょうか。

2. Memcachedを見ると、キャッシュ用ストアの形が分かりやすい

Redisは機能が多いので、いきなりRedisから入ると「何がキャッシュに必要な機能で、何がRedis固有の機能なのか」が見えにくくなります。そこでMemcachedを見ると、キャッシュ用のストアに何があればよいのかがかなり単純に見えました。

たとえば商品ID 100 の商品情報を保存するとします。

Key:   product:100
Value: {"name":"Keyboard","price":12000}

このように、キーを指定して値を保存・取得する仕組みを Key-Value Store(キー・バリューストア) と呼びます。Memcachedはこの形が中心で、アプリケーション側からキーを指定して値をSETし、必要になったらGETします。

Memcachedは、値の中身を細かく理解して操作することを主目的にしていません。JSONでも文字列でもシリアライズしたオブジェクトでも、基本的には「このキーに対応する値」として扱います。このような、中身の構造をストア側があまり解釈しない値を opaque value と表現することがあります。

キャッシュとして使うなら、値がずっと残り続ける必要もありません。TTLを設定して期限切れになれば使わなくなりますし、メモリが足りなくなれば一部のエントリが追い出されることもあります。前者が Expiration、後者が Eviction です。どちらの場合も、キャッシュとして使っているなら次のキャッシュミスで元データから作り直せます。

複数台へ増やすときも、「Memcachedサーバー同士が1つの巨大なサーバーとして同期する」と考えると少し違います。基本的に各Memcachedサーバーは独立していて、典型的にはクライアント側、またはProxyがキーを見て接続先のバックエンドを振り分けます。

image.png

このシンプルさを見ると、Memcachedは「Redisより機能が少ない」というより、消えても作り直せる値を高速に置く用途へかなり集中していると捉える方が分かりやすいです。

ではRedisは、この基本形に何を足しているのでしょうか。

3. Redisはストア側に「操作」と「データ型」を持っている

Memcachedでもキーから値を取得できますし、数値のincrement / decrement のような操作もあります。なので「MemcachedはGET / SETしかできず、Redisだけがサーバー側で操作できる」という比較ではありません。

Redisで大きく違うのは、ストア自身がデータ型の意味を理解し、それに応じた操作を多く持っていることでした。

image.png

一番分かりやすいのはStringです。普通の文字列やシリアライズ済みデータを保存するだけなら、Memcachedに近い使い方もできます。一方、数値を保存したStringならRedis側で増減できます。アプリケーションが「現在値をGET → 1足す → SET」と分けず、ストア側の操作として扱えるわけです。

Hashは、1つのキーの中にFieldとValueを持てます。たとえば商品情報を、

product:100
  name  -> Keyboard
  price -> 12000
  stock -> 8

のように持てます。商品全体をアプリケーションでデコードして書き戻さなくても、pricestock といったField単位で扱えるのが違いです。

Setは重複しない集合です。「このユーザーがOnlineか」のような所属しているかどうかを扱いやすくなります。Sorted Setになると各要素にスコアを持てるので、スコア順のランキングをストア側で扱えます。

Listは順序を持つデータ型です。先頭や末尾へ追加・取得する操作があるため、順番を持つデータを扱う場面にも使えます。

ここで面白かったのは、Redisの用途が広い理由を「データ型が多いから」だけでは説明しきれないことです。共有ストアであること、ストア側で操作を実行できること、データ型自体が豊富なことが組み合わさって、使い方が広がっています。

4. セッション・カウンター・ランキングでは、使っている性質が違う

Redisがキャッシュ以外にも使われる理由は、用途ごとに「Redisの何が役立っているのか」を分けると理解しやすくなりました。セッション、カウンター、ランキングは同じRedisを使っていても、効いている性質が少しずつ違います。

用途 主に効いている性質
セッション 複数アプリケーションから読める共有ストア session:abc123 → user_id=42
カウンター ストア側の数値操作 ページビューやRate Limit用のカウント
ランキング Sorted Set user_id + score を順位順に扱う

セッションでは、複数のアプリケーションインスタンスから同じセッション状態を読めることが効きます。ただし、これはRedisだけができるわけではありません。Memcachedも共有ストアなので、セッションの保存先として使う構成は作れます。

カウンターでは、アプリケーションが値を読み出して計算し直すのではなく、ストア側で数値を増減できることが役立ちます。これもincrement / decrement 系の操作自体はMemcachedにもあるので、「カウンターがあるからRedis」という単純な話ではありません。

ランキングはRedisのデータ型とのつながりがかなり明確です。Sorted Setは「要素 + スコア」という形を持ち、スコア順で取得できるので、Leaderboard(順位表)のような用途と相性がよいです。

5. Redisを運用するときの4つの問題は別々だった

キャッシュとして使うだけなら、Redisのデータが消えても元データから作り直せます。でも、セッションのようにRedis自体が状態の保存先になると、消えたときの意味が変わります。ユーザーがログアウトするなど、サービスの状態そのものへ影響することもあります。

そこで「Redisを強くする機能」とひとまとめにせず、まず困りごとを4つに分けると整理しやすかったです。再起動後に戻したい、同じデータのコピーを持ちたい、障害時に別ノードへ切り替えたい、1台の容量を超えたい。この4つは、それぞれ別の問題です。

image.png

再起動後にもデータを戻したい — Persistence

Redisの主なデータはメモリ上にあります。ではプロセスやマシンが再起動したとき、その状態を戻したい場合はどうするのか。そこで出てくるのが Persistence です。これはメモリ上の状態をディスクへ記録し、再起動後に復元できるようにする考え方です。

Redisには代表的にRDBとAOFがあります。RDBはある時点の状態をまとめて保存するスナップショット方式、AOFは書き込み操作を記録していく方式です。細かい設定はかなり多いですが、ここでは「メモリ上のデータをどう復元するか」という問題への答えだと分かれば十分でした。

キャッシュとして使い、消えたらDBから作り直せるなら、Persistenceを使わない構成もあります。PersistenceがあるからRedisが自動的に正しい元データの保存先になるわけでもありません。

同じデータのコピーを別ノードにも持ちたい — Replication

1台のRedisにしかデータがなければ、そのノードに障害が起きたとき困ります。そこで、書き込みを受けるPrimary(主系)のデータを別のノードにも複製しておくのが Replication です。複製先のノードをReplica(複製先)と呼びます。

Replicationがあると、同じデータのコピーを別ノードへ持てます。読み込みをReplicaへ分散する設計や、障害対応の材料にもなります。ただし、Primaryへの書き込みがReplicaへ反映されるまで少し遅れることがあるので、PrimaryとReplicaが常に完全に同じ瞬間を持つとは限りません。

そして、Replicaがあるだけでは「Primaryが壊れたら自動で切り替わる」とは限りません。

壊れたPrimaryから切り替えたい — Failover

Primaryが使えなくなったとき、Replicaなど別のノードへ役割を切り替えることを Failover と呼びます。Replicationは「コピーを持つ仕組み」、Failoverは「障害時に役割を切り替える仕組み」です。

RedisではSentinelやRedis ClusterなどがFailoverを含む構成に関わります。この記事ではそれぞれのアルゴリズムまでは扱いません。初学者としては、Replication = コピー、Failover = 切り替えと分けるだけでもかなり整理できました。

1台に入りきらないデータを分けたい — Sharding

Replicationは同じデータのコピーを増やします。それに対して Sharding は、データそのものを複数ノードへ分割する考え方です。

たとえばキーの一部をノードA、別のキーをノードBへ置けば、1台のメモリ容量を超えるデータを扱いやすくなります。スループットを複数ノードへ分散したい場合にも関係します。

Redis Clusterは単なる「Sharding機能」ではありません。Redis ClusterはデータのShardingに加えて、ReplicationやFailoverも組み合わせるRedisの分散構成です。ここでは「Sharding = Redis Clusterではない」と分けて理解するところまでに留めます。

6. RedisとMemcached、結局どう選ぶ?

Persistence / Replication / Failover / Shardingを分けてみると、「重要なデータをRedisへ置くなら全部必要」という話でもないと分かります。消えても作り直せるキャッシュでも可用性や容量のために分散が必要なことはありますし、逆に重要なデータだからといって4つすべてが必要とは限りません。

ここまで見てくると、Redisの方ができることは多く見えます。でも、「できることが多い = 常に良い選択」ではありません。運用機能も要件次第だったのと同じように、Redis / Memcachedの選択も、ストア側に何を求めているのかへ戻して考える方が分かりやすかったです。

たとえば、保存したいものが単純なキャッシュで、

  • キーから値を高速に取り出せればよい
  • 消えても元データから作り直せる
  • 複雑なデータ型をストア側で扱う必要がない

という要件なら、Memcachedのシンプルさがそのまま価値になります。

一方で、Hash / Set / Sorted Setのようなデータ型をストア側で扱いたい、ランキングや集合操作をストア側へ寄せたい、Redis自身のPersistenceやClusterの機能が要件に合う、といった理由があるならRedisが候補になります。

image.png

ここで容量や可用性は、製品選択とは分けて考えたいところです。Memcachedでも複数のバックエンドへ分散する構成は取れますし、「複数台にしたいからRedis」とは限りません。

Redisの機能が増えるほど、設定や障害時の振る舞い、どこまでデータを守るかといった判断も増えます。調べる前は「Redisの方が高機能ならRedisでよいのでは」と考えやすかったのですが、比較してみると、使わない機能を持たないシンプルさも設計上の性質だと分かりました。

おわりに

RedisとMemcachedを比べてみると、Redisを「キャッシュの高機能版」とだけ捉えるのは少し違うと分かりました。

キャッシュは役割で、Redis / Memcachedはその役割を担えるストアです。Memcachedはシンプルなキャッシュ用ストアとして理解しやすく、Redisはストア側の操作やデータ型を広げることでセッション・カウンター・ランキングなどにも使いやすくなります。

最終的には「Redisの方が機能が多いか」ではなく、何を保存し、ストア側にどんな操作を求め、どんな運用要件を持つのかから選ぶ方が整理しやすかったです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?