ElastiCacheにおいてMemcachedとRedisはどちらを選ぶべきなのか？自分なりに調べてみた

本記事は、[サムザップ Advent Calendar 2019 #1](https://qiita.com/advent-calendar/2019/sumzap1) の12/4の記事です。

スマホゲームの企画・運営事業を行っている[サムザップ](https://www.sumzap.co.jp/)で、エンジニアマネージャーをしています北島です。
私の担当しているゲームでは、DBのクエリーキャッシュとして [ElastiCache for Memcached](https://aws.amazon.com/jp/elasticache/memcached/) を使っています。
ですが、最近は「Memcachedのphp libraryは古いし、今はRedisだよね！」といったような話を聞くような気がします
また、実際に新しいゲームタイトルではRedisを採用している所が多いような気もします。

結局のところどっちが良いの？と疑問に思ったので、自分なりに調べてまとめてみました。

#MemcachedとRedisの比較

[AWSの公式ドキュメント](https://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/mem-ug/SelectEngine.html)に分かりやすく比較がまとまっています。

<table style="table-layout: fixed;">
<tr>
  <th></th>
  <th>Memcached</th>
  <th>Redis (クラスターモードが無効)</th>
  <th>Redis (クラスターモードが有効)</th>
</tr>
<tr>
  <td>エンジンバージョン</td>
  <td>1.4.x</td>
  <td>2.8.x 以降</td>
  <td>3.2.x 以降</td>
</tr>
<tr>
  <td rowspan=2>データ型</td>
  <td rowspan=2>シンプル ‡</td>
  <td>2.8.x - 混在 *</td>
  <td rowspan=2>3.2.x 以降 - 複雑</td>
</tr>
<tr>
  <td>複雑</td>
</tr>
<tr>
  <td>データのパーティション化</td>
  <td>あり</td>
  <td>いいえ</td>
  <td>あり</td>
</tr>
<tr>
  <td>クラスターが変更可能</td>
  <td>あり</td>
  <td>あり</td>
  <td>3.2.10 以降 - 限定</td>
</tr>
<tr>
  <td>オンラインリシャーディング</td>
  <td>なし</td>
  <td>なし</td>
  <td>3.2.10 以降</td>
</tr>
<tr>
  <td>暗号化</td>
  <td>なし</td>
  <td>3.2.6、4.0.10 以降</td>
  <td>3.2.6、4.0.10 以降</td>
</tr>
<tr>
  <td colspan="4">コンプライアンス認定</td>
</tr>
<tr>
  <td>コンプライアンス認定<br>FedRAMP<br>HIPAA<br>PCI DSS</td>
  <td><br>なし<br>いいえ<br>いいえ</td>
  <td><br>3.2.6、4.0.10 以降<br>3.2.6、4.0.10 以降<br>3.2.6、4.0.10 以降</td>
  <td><br>3.2.6、4.0.10 以降<br>3.2.6、4.0.10 以降<br>3.2.6、4.0.10 以降</td>
</tr>
<tr>
  <td>マルチスレッド</td>
  <td>あり</td>
  <td>いいえ</td>
  <td>なし</td>
</tr>
<tr>
  <td>ノードタイプのアップグレード</td>
  <td>なし</td>
  <td>はい</td>
  <td>なし</td>
</tr>
<tr>
  <td>エンジンのアップグレード</td>
  <td>はい</td>
  <td>はい</td>
  <td>あり</td>
</tr>
<tr>
  <td>高可用性 (レプリケーション)</td>
  <td>なし</td>
  <td>はい</td>
  <td>あり</td>
</tr>
<tr>
  <td>自動フェイルオーバー</td>
  <td>なし</td>
  <td>オプション</td>
  <td>必須</td>
</tr>
<tr>
  <td>パブリック/サブ機能</td>
  <td>なし</td>
  <td>はい</td>
  <td>あり</td>
</tr>
<tr>
  <td>ソートされたセット</td>
  <td>なし</td>
  <td>はい</td>
  <td>あり</td>
</tr>
<tr>
  <td>バックアップと復元</td>
  <td>なし</td>
  <td>はい</td>
  <td>あり</td>
</tr>
<tr>
  <td rowspan=2>地理空間インデックス作成</td>
  <td rowspan=2>なし</td>
  <td>2.8.x - いいえ</td>
  <td rowspan=2>あり</td>
</tr>
<tr>
  <td>3.2.x 以降 - あり</td>
</tr>
<tr>
  <td colspan="4">注:</td>
</tr>
<tr>
  <td colspan="4">‡文字列、オブジェクト (データベースなど)</td>
</tr>
<tr>
  <td colspan="4">*文字列セット、並べ替えられたセット、リスト、ハッシュ、ビットマップ、Hyperloglog</td>
</tr>
<tr>
  <td colspan="4">‡文字列、セット、ソートされたセット、リスト、ハッシュ、ビットマップ、hyperloglog、地理空間インデックス</td>
</tr>
</table>

#自分なりの考えのまとめ

自分なりの考えを以下にまとめます。
あくまでも私個人の意見として見てください。

- パフォーマンス・費用面は大差はない
    - Memcachedの方が速いというイメージがあるが、最近は単純なget/setであれば大差はないらしい
    - 費用面もキャッシュ的な使い方であれば大差はなさそう
- 可用性ではRedis
    - Memcachedの場合、ある程度大きいコア・スレッド数のノードを用意することになる
    - そして、そのノードを追加したり削除したりすることで負荷分散をする
    - これらのノードの組み合わせをクラスターとして管理する
    - Redisの場合、クラスターモードの有効/無効、シャード有効/無効など、様々な構成ができる
    - よって、Redisの方が可用性では優れていそう
    - とはいえ、クエリーキャッシュなどの単純な構成で良い用途であればMemcachedでも良さそう
- 機能性ではRedis
    - Memcachedは単純なデータ型(string)しかない
    - RedisはListやHash、Sorted Setなど様々なデータ型がある
    - また、正規表現でキーの曖昧検索ができるのも便利
    - さらに、Redisはクラスター毎にスナップショットを取ることもできる
- 単一ノードの性能ではMemcached
    - Memcachedはマルチスレッドなので、CPUのコア数を上げれば上げるほど性能は上がる
    - Redisはシングルスレッドなので、CPUのコア数を上げてもパフォーマンスの向上はそこまで期待できない
    - とはいえ、キャッシュ的な使い方であれば、単一ノードの性能がボトルネックになることはあまりない気はする
- 運用・保守のしやすさではMemcached
    - Memcachedの最新バージョンは 1.5.16
    - Redisの最新バージョンは 5.0.5
    - RedisはMemcachedに比べ、機能が複雑な分、頻繁に更新が入っている
    - 更新することも考え、運用・保守の観点では、Memcachedの方が楽そうではある
    - 個人的なイメージだが、更新が少ないことや用途が違うこから、Memcachedの方が問題が起きにくいイメージもある

#最後に

今回は、ElastiCacheにおけるMemcachedとRedisの比較をまとめました。
あくまでも私の考えですが、使用用途が決まっていて単純なものであればMemcached。
複雑もしくは複雑になる恐れがる場合は、Redisといった感じでしょうか。

今回の件とは関係がありませんが、MySQLのエンジンに[MEMORY ストレージエンジン](https://dev.mysql.com/doc/refman/5.6/ja/memory-storage-engine.html)というのもありますね。
DBがMySQLであるならば、そのクエリーキャッシュでこの選択肢もありなのかも？と思ったりもします。

明日は、@hiroyuuki さんの記事です。

#参考

[Memcached と Redis の比較](https://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/mem-ug/SelectEngine.html)
[ElastiCacheはMemcachedとRedisのどっちを選ぶ？](https://dev.classmethod.jp/cloud/aws/which-choice-redis-memcached/)