AWSのredisとGoogleCloudPlatformのredis、どっちが高速か戦わせてみる

# はじめに
[これ](https://qiita.com/fumihiko-hidaka/items/ef554385a32894aa9218)と[これ](https://qiita.com/fumihiko-hidaka/items/14877357939635ab059e)の続き

GCPにもフルマネージドのredisのサービス、Memorystoreがだいぶ前に発表されたので……AWSのredisとどちらが高速なんだろうという疑問が抑えきれずに。
ElasticCache VS Memorystore のどっちが早いのか白黒つけてみたいので、これは戦わせてみるしかない。
ついでに自分のローカル環境に立てたredisも戦わせてみる。

# 計測の方法

- 計測にはredis-benchmarkコマンドを使用
- redis-benchmarkコマンドを3回実行して、その平均の値を使用
- AWSとGCPでは、可能な限り性能を合わせてみる
- redisにはEC2, GCEの各インスタンスから接続する
- ローカル環境は……特に何も考えません
- 実行結果は1sあたりに実行できた処理数
- プログラムがバグってたらごめんなさい

# 計測用のプログラム

python2で書いてみました。

```benchmark.py
# -*- coding: utf-8 -*-

import subprocess
import sys
import re

args = sys.argv

retry_count = 3

redis_host = args[1]
redis_connection_str = args[2]
redis_connections = redis_connection_str.split(",")

result_dict = {}

# 実行
for set_connection in redis_connections:
    process_input = ["redis-benchmark", "-h", redis_host, "-p", "6379", "-c", set_connection, "-n", "500", "-q"]

    for try_count in range(0, retry_count):
        print("run -c {} try {}".format(set_connection, try_count))

        stdout_str = subprocess.check_output(process_input)

        each_rows = map(lambda x: re.sub(".+\r", "", x).strip(), stdout_str.split("\n"))
        filter_rows = filter(lambda x: len(x) > 0, each_rows)

        for command_row in filter_rows:
            m = re.search("(.+?): (.+?) ", command_row)

            result_key = m.group(1)
            result_value = float(m.group(2))

            if result_key not in result_dict:
                result_dict[result_key] = {}
            if set_connection not in result_dict[result_key]:
                result_dict[result_key][set_connection] = []

            result_dict[result_key][set_connection].append(result_value)

# 以降、実行結果をmarkdownに変換する文字列処理
```

# 計測開始！

:punch::punch:ファイッ！:punch::punch:

## macのlocal環境

redisをdockerコンテナで立ち上げて、チェック用のプログラムをホストからひたすら実行……
ホスト機は1世代前のMacBook Proからになります。
タッチバーとキーボードの反応が凄く悪いので、誰か直してくれないかな……:thinking:

| 同時接続数 | 1 | 10 | 25 | 50 | 100 |
| :-- | :-- | :-- | :-- | :-- | :-- |
| PING_INLINE | 2353.45 | 7969.51 | 10608.47 | 10929.51 | 7835.25 |
| PING_BULK | 2457.26 | 8510.78 | 11025.64 | 10512.6 | 10974.02 |
| SET | 2537.6 | 8268.4 | 10007.42 | 10601.73 | 8585.86 |
| GET | 2586.33 | 8697.76 | 10262.84 | 10400.13 | 8389.2 |
| INCR | 2587.77 | 8756.11 | 9828.3 | 11441.8 | 8391.34 |
| LPUSH | 2466.03 | 9024.12 | 9926.86 | 10679.27 | 9633.19 |
| RPUSH | 2257.2 | 8204.34 | 10591.13 | 10001.46 | 9817.63 |
| LPOP | 2486.2 | 7955.23 | 10054.51 | 8888.89 | 9131.58 |
| RPOP | 2668.43 | 8421.66 | 10245.51 | 11472.83 | 8703.7 |
| SADD | 2424.71 | 8680.56 | 11253.56 | 9685.85 | 8341.1 |
| SPOP | 2444.03 | 8451.55 | 9960.88 | 10357.14 | 10296.1 |
| LPUSH | 2466.03 | 9024.12 | 9926.86 | 10679.27 | 9633.19 |
| LRANGE_100 (first 100 elements) | 2164.16 | 6744.58 | 8044.58 | 8136.86 | 7559.84 |
| LRANGE_300 (first 300 elements) | 1739.92 | 4482.19 | 4727.96 | 4270.31 | 4625.08 |
| LRANGE_500 (first 450 elements) | 1516.72 | 3545.41 | 3720.64 | 3268.29 | 3397.3 |
| LRANGE_600 (first 600 elements) | 1345.15 | 2773.83 | 2866.99 | 2661.24 | 2449.77 |
| MSET (10 keys) | 2462.2 | 8429.9 | 10256.11 | 8439.71 | 8446.97 |

## AWSのElasticCache

- EC2のスペック
    - EC2ではt2.2xlargeのマシンを選択しました
    - ｖCPU8, メモリ32GB
- ElasticCacheのスペック
    - cache.r4.largeを選択
    - vCPU2, メモリ12.3GB
    - 0.273$/h
    - redisのバージョンは最新で可用性は全てオミット

| 同時接続数 | 1 | 10 | 25 | 50 | 100 |
| :-- | :-- | :-- | :-- | :-- | :-- |
| PING_INLINE | 4486.46 | 29090.91 | 39285.71 | 37500.0 | 32222.22 |
| PING_BULK | 4461.05 | 30000.0 | 39285.71 | 36111.11 | 33333.34 |
| SET | 4647.03 | 29090.91 | 37500.0 | 37500.0 | 37896.83 |
| GET | 4483.61 | 29090.91 | 39285.71 | 36111.11 | 36785.71 |
| INCR | 4225.91 | 29090.91 | 37500.0 | 37500.0 | 38571.43 |
| LPUSH | 4168.3 | 28181.82 | 37500.0 | 36111.11 | 37896.83 |
| RPUSH | 4508.41 | 30000.0 | 39285.71 | 36111.11 | 36785.71 |
| LPOP | 4524.2 | 28181.82 | 37500.0 | 36111.11 | 42857.14 |
| RPOP | 4328.31 | 28181.82 | 37500.0 | 36111.11 | 36904.76 |
| SADD | 4353.32 | 30000.0 | 39285.71 | 34722.22 | 37662.34 |
| HSET | 4266.74 | 30000.0 | 39285.71 | 36111.11 | 35876.62 |
| SPOP | 4391.09 | 30000.0 | 37500.0 | 36111.11 | 40043.29 |
| LPUSH | 4168.3 | 28181.82 | 37500.0 | 36111.11 | 37896.83 |
| LRANGE_100 (first 100 elements) | 3820.86 | 22527.47 | 25000.0 | 25384.62 | 29090.91 |
| LRANGE_300 (first 300 elements) | 2922.14 | 10114.94 | 10229.89 | 11367.53 | 12681.16 |
| LRANGE_500 (first 450 elements) | 2542.73 | 7570.6 | 8293.46 | 8354.01 | 9096.48 |
| LRANGE_600 (first 600 elements) | 2268.06 | 6464.29 | 7022.36 | 7147.44 | 5341.01 |
| MSET (10 keys) | 4225.91 | 26515.15 | 34722.22 | 39285.71 | 32222.22 |

## GCPのMemorystore

- GCEのスペック
    - vCPU8
    - CPU数8、メモリ数30GBでEC2と比べると気持ちスペック低い
- Memorystoreのスペック
    - cache.r4.largeを選択
    - CPUについては記載なし、メモリ12GB
    - ネットワークスループットは375MB/s
    - 0.384$/h
    - redisのバージョンは最新で可用性は全てオミット
    - GCPでは4系は使えず3.2が最新でした


| 同時接続数 | 1 | 10 | 25 | 50 | 100 |
| :-- | :-- | :-- | :-- | :-- | :-- |
| PING_INLINE | 6149.83 | 36111.11 | 47619.05 | 42857.14 | 41071.43 |
| PING_BULK | 7083.33 | 43452.38 | 50000.0 | 45238.1 | 42857.14 |
| SET | 6778.83 | 37896.83 | 47619.05 | 42857.14 | 42857.14 |
| GET | 5960.78 | 37896.83 | 50000.0 | 45238.1 | 41071.43 |
| INCR | 7011.29 | 41071.43 | 50000.0 | 42857.14 | 39285.71 |
| LPUSH | 6468.53 | 37500.0 | 47619.05 | 45238.1 | 41071.43 |
| RPUSH | 7169.02 | 42857.14 | 50000.0 | 42857.14 | 41071.43 |
| LPOP | 6192.35 | 41071.43 | 47619.05 | 42857.14 | 42857.14 |
| RPOP | 7505.28 | 39682.54 | 50000.0 | 45238.1 | 41071.43 |
| SADD | 6310.67 | 37500.0 | 50000.0 | 35238.1 | 39285.71 |
| SPOP | 6886.79 | 41071.43 | 47619.05 | 45238.1 | 41071.43 |
| LPUSH | 6468.53 | 37500.0 | 47619.05 | 45238.1 | 41071.43 |
| LRANGE_100 (first 100 elements) | 4898.58 | 23926.08 | 28181.82 | 25000.0 | 25116.55 |
| LRANGE_300 (first 300 elements) | 3169.63 | 11549.86 | 12681.16 | 11396.01 | 10114.94 |
| LRANGE_500 (first 450 elements) | 2487.12 | 7677.12 | 8337.62 | 8036.98 | 6999.5 |
| LRANGE_600 (first 600 elements) | 2281.7 | 6255.55 | 6433.22 | 6255.32 | 5661.72 |
| MSET (10 keys) | 6634.83 | 30202.02 | 36111.11 | 37500.0 | 33333.34 |

## 同時接続数100で比較した結果！

|  | local | AWS | GCP |
| :-- | :-- | :-- | :-- | :-- | :-- |
| PING_INLINE | 7835.25 | 32222.22 | 41071.43 |
| PING_BULK | 10974.02 | 33333.34 | 42857.14 |
| SET | 8585.86 | 37896.83 | 42857.14 |
| GET | 8389.2 | 36785.71 | 41071.43 |
| INCR | 8391.34 | 38571.43 | 39285.71 |
| LPUSH | 9633.19 | 37896.83 | 41071.43 |
| RPUSH | 9817.63 | 36785.71 | 41071.43 |
| LPOP | 9131.58 | 42857.14 | 42857.14 |
| RPOP | 8703.7 | 36904.76 | 41071.43 |
| SADD | 8341.1 | 37662.34 | 39285.71 |
| SPOP | 10296.1 | 40043.29 | 41071.43 |
| LPUSH | 9633.19 | 37896.83 | 41071.43 |
| LRANGE_100 (first 100 elements) | 7559.84 | 29090.91 | 25116.55 |
| LRANGE_300 (first 300 elements) | 4625.08 | 12681.16 | 10114.94 |
| LRANGE_500 (first 450 elements) | 3397.3 | 9096.48 | 6999.5 |
| LRANGE_600 (first 600 elements) | 2449.77 | 5341.01 | 5661.72 |
| MSET (10 keys) | 8446.97 | 32222.22 | 33333.34 |

ローカルのMacBookは……はい、まぁなんでもいいんですが。
AWSとGCPを比較してみて、結構面白い結果が出たような？

# 結果

- PING_INLINE〜LPUSHまでの操作についてはGCPの方が気持ち早い？　単純な操作だと高速？
- LRANGE_100〜600が複数個のデータの取得のはずなんですが、多くなるにつれてAWSの方が早くなってきている？
- ただ、猛烈に差があるという訳でもないので誤差かもしれない……
- AWSはredis4、GCPはredis3というバージョンの違いがあるので、ここが同じになると結果が変わってくるかもしれない
- もっと大規模データになった時、GCPの方はスループットの方が上がるっぽそうだけれども、AWSの方はどうなんだろう？
- 性能にそこまで差がないのであれば、時間あたりの費用がお安めのAWSの方がコスパがいい？
- ただ、このあたりはレプリケーションやクラスタを組んでみたら結果が変わるかもしれない。

redisで速度にそこまで差はなかった:sob:

これは引き分けではなかろうか……？
白黒をつけるのであればAWSの判定勝ちぐらい？

というかどちらも十分に早かった:airplane: