RedisとMemcachedについての補足
原文は Salvatore Sanfilippo により に公開されました。 このブログを購読する
僕のことを知っている人なら、僕が競合製品を否定的に捉えるタイプではないことをご存じでしょう。むしろユーザーに選択肢があることを素晴らしいと思っています。だから、Redisを他の技術と比較するようなことはめったにしません。
ただ、正しい解決策を選ぶためには、ユーザーが正確な情報を得る必要があるのも事実です。
今回この記事を書くきっかけになったのは、Mike Perham氏が公開したブログ記事を読んだことです。Mike氏といえば、バックエンドにRedisを使っている人気ライブラリSidekiqの作者として知られています。ですから、Mike氏が「反Redis派」だとはまったく思っていません。それでも、http://www.mikeperham.com/2015/09/24/storing-data-with-redis/で読める彼の記事の中で、彼はキャッシュ用途については「(Redisではなく)おそらくMemcachedを使うべきだ」と述べています。つまりMike氏は純粋に、Redisはキャッシュには向いていないと信じているわけで、その主張を次のように論じています:
- Memcachedはキャッシュのために設計されている。
- ディスクI/Oをまったく行わない。
- マルチスレッドで、マルチコアを活かして10万件以上のリクエストを処理できる。
これらの指摘について順に触れ、その後、上記の文面では捉えきれていないものの、私の考えでは多くのキャッシュ用途やユースケースにとってより重要ないくつかの点について述べたいと思います。
Memcachedはキャッシュのために設計されている:これは議論にすらならないので飛ばします。私なら「Redisはキャッシュのために設計されている」と言えますから。この点に関しては両者に違いはありません。次の点に移りましょう。
ディスクI/Oをまったく行わない:Redisでも、望むならディスクI/Oを完全に無効にでき、純粋にインメモリで動作させることができます。ただし、本当に必要なら、再起動するときだけデータベースを永続化することもできます。例えば“SHUTDOWN SAVE”のようにです。結局のところ、Redisの永続化は、まったく使わない場合でさえ付加価値なのです。
マルチスレッドである:これは事実ですし、私自身の目標にもRedisのI/Oをスレッド化すること(Memcachedのように、基本的にデータへのアクセス自体はスレッド化されていない形で)が入っています。しかしRedisは、とりわけパイプラインを使えば、1スレッドあたり驚くほど多くのリクエストを処理できます(パイプラインを集中的に使えば1秒あたり50万件というのがよくある数字です。パイプラインなしでも10万ops/秒ほどです)。各Redisインスタンスが同じ役割を担い、マスターとして動作し、ディスク操作は無効化され、シャーディングは“Memcachedのシャーディングモデル”のようにクライアント側に委ねられるという、素のキャッシュのシナリオでは、システムごとに複数のRedisプロセスを立ち上げてもそれほど悪くありません。そうすればシェアードナッシングなマルチスレッド構成になるので、重要になるのは1スレッドあたりどれだけの操作を捌けるかです。私が最後に確認した限りでは、Redisはスレッドあたりの速度で少なくともMemcachedと同等でした。実装は時とともに変わるので、今日どちらが優位かは入れ替わっているかもしれませんが、どちらも使えるリソースを最大限に活用しようとするため、性能は近いはずです。Memcachedのマルチスレッドは、使いやすく管理しやすいという点では依然として利点ですが、決定的な要素ではないと考えています。
まだ続きがあります。Mike氏は1秒あたりの操作回数について語っていますが、操作の*質*には触れていません。RedisやMemcachedのようなシステムでは、コマンドのディスパッチやI/Oのコストが、実際にインメモリのデータ構造に触れるコストを圧倒的に上回ります。つまりRedisでは、単純なGETやSETを実行するのも、ZRANKのような複雑な操作を実行するのも、コストはほぼ同じなのです。しかし複雑な操作で達成できることは、アプリケーションの観点から見ればはるかに大きな仕事になります。5つのキャッシュされた値をいちいち取得する代わりに、小さなLuaスクリプトを送るだけで済むかもしれません。つまり、両システムの実際の「スケーラビリティ」には多くの側面があり、何を達成できるかということもその一つなのです。
Mike氏が懸念する点の中で、私が正当だと思うのはマルチスレッドだけです。しかもそれは、RedisをMemcachedの置き換えという特殊なケースで考えた場合、複数プロセスを実行するか、あるいは単に1プロセスだけを実行することで対処できます。Memcached的な操作で1スレッドを飽和させるのは、きわめて難しいからです。
本当の違い
では、両システムの*本当の*違いについて話すことにしましょう。
メモリ効率
メモリ効率でいえば、かつてはMemcachedの方がRedisより優れていました。単純な文字列から文字列への辞書を表現するために設計されたシステムでは、メモリをより効率的に使うのは簡単だからです。この差は劇的なものではなく、もう5年ほど確認していませんが、かつては目に見える差がありました。
ただ、長時間動作するプロセスのメモリ効率を考えると、話は少し違ってきます。次のセクションを読んでみてください。
そもそもメモリ効率を本当に評価するには、Redisで小さな集約値が特別なエンコーディングによって非常にメモリ効率が高くなっていることも考慮に入れるべきです。例えば小さな整数の集合は、内部的には8ビット、16ビット、32ビット、あるいは64ビット整数の配列として表現され、順序付けされているため二分探索が使えて、存在確認を対数時間で行えます。
同じことは、JSONに頼る代わりにハッシュを使ってオブジェクトを表現する場合にも当てはまります。つまり、本当のメモリ効率は、手元のユースケースと合わせて評価しなければなりません。
RedisのLRUとSlabアロケータ
Memcachedはメモリ利用率という観点では完璧ではありません。キャッシュする値のサイズが時間とともに大きく変わるアプリケーションでは、深刻な断片化に陥り、唯一の解決策が再起動ということになりがちです。Redisはこの点でずっと決定論的です。
さらに、RedisのLRUは最近大幅に改善され、現在では真のLRUに非常に近い近似になっています。詳しくはこちらをご覧ください:http://redis.io/topics/lru-cache。私の理解が正しければ、MemcachedのLRUは依然としてSlabアロケータに基づいて期限切れを処理するため、ときに真のLRUとはかけ離れた挙動になることがありますが、この点については専門家の意見を聞きたいところです。RedisのLRUを試したい方は、最近のバージョンのRedisで利用できるredis-cliのLRUテストモードで試すことができます。
スマートなキャッシング
Redisをキャッシュに使うのに、Memcachedと同じように使おうとするなら、本当に大きなものを見逃しています。私の意見では、これがMike氏の記事で最大の誤りです。Redisに乗り換える人がますます増えているのは、キャッシュしたデータをより有用な形で表現できることに気づいたからです。何かの最新N件を保持したいですか?上限付きリストを使ってください。キャッシュされた人気度インデックスが欲しいですか?ソート済みセットを使ってください、といった具合です。
永続化とレプリケーション
もしそれらが必要なら、非常に重要な資産になります。例えばこのモデルを使えば、大量の読み込みをスケールさせるのはとても簡単です。再起動時の永続化や、時間をかけてキャッシュのスナップショットを取れることなども同様です。もちろん、どちらの機能もまったく関係ないという使い方があるのも当然です。ここで言いたいのは、「純粋なキャッシュ」のユースケースの中にも、永続化とレプリケーションが重要になるものがあるということです。
可観測性
Redisは非常に、非常に可観測性に優れています。大量の内部メトリクスについて詳細なレポートがあり、SCANでデータセットを走査したり、オブジェクトの期限切れを観察したり、LRUアルゴリズムをチューニングしたりできます。クライアントに名前を付けてCLIENT LISTで確認したり、アプリケーションのデバッグに“MONITOR”を使ったり、その他多くの高度なことができます。これは利点だと考えています。
Luaスクリプティング
Luaスクリプティングは、多くのキャッシュのユースケースで非常に役立つと私は考えています。例えばキャッシュされたJSON blobがある場合、Luaコマンドを使えば全体を転送する代わりに単一のフィールドだけを抽出してクライアントに返すことができます(概念的には、Redisのハッシュを直接使ってオブジェクトを表現すれば同じことができます)。
結論
Memcachedは素晴らしいソフトウェアです。私はソースコードを何度も読みましたし、それは私たちの業界における革命でした。Redisと比べてどちらが自分にとってより良い選択か、検討してみるべきです。ただ、物事はありのままに評価されるべきであり、正直なところ、Mike氏のレポートや、長年にわたって目にしてきた非常に似たレポートを読んで少しいら立ちを感じたので、自分の見解を示すことにしました。事実として誤っている点があれば、教えてください。そうすれば“EDIT”セクションを追記する形で記事を更新します。
記事をランダムに読む
コメント
ログインしてコメントする