MySQL では 「InnoDB Memcached」プラグインを使うことで、Memcached プロトコルを使ってテーブルデータに直接アクセスすることができるようになります。
参考:MySQL :: MySQL 5.7 Reference Manual :: 14.20 InnoDB memcached Plugin
今回はキャッシュストアとしてよく使われる Redis と Memcached 、そしてMySQLの InnoDB Memcached プラグインのベンチマークをとって比較してみたいと思います。
ベンチマーク環境
AWS の m4.2xlarge インスタンスを使用しました。
スペック
項目 | 値 |
---|---|
vCPU | 8 core |
MEM | 32GB |
DISK | 16GB |
バージョン
項目 | バージョン |
---|---|
MySQL | 5.7.20 |
Redis | 4.0.2 |
Memcached | 1.5.3 |
ベンチマークツールは Redis と Memcached プロトコルが使える memtier-benchmark を使用しました。
公式サイト : https://github.com/RedisLabs/memtier_benchmark
AWSなのでネットワークのスループットは十分に出ると思いますが、KVSでは比較的ネットワークがボトルネックになることが多いため、今回はベンチマークツールも同一マシン上で動かすことにしました。
Memcached
Memcached はメモリ上にしかデータを持たないため、ディスクへのアクセスがほとんどありません。そのため、高速ではあるものの、データが永続化されないため、インスタンスが停止するとデータが消えてしまいます。
1 |
$ memcached -t 8 |
-t はスレッド数です。今回のCPUのコア数に合わせて 8 とします。
Redis
Redis は2つの方法でデータをディスクに保存して永続化します。
- 指定したタイミングでデータのスナップショットをディスクに保存 (RDB)
- 更新記録をディスクに追記して保存(AOF)
RDBはMySQLのバックアップファイルのようなイメージで、取得したタイミングのデータが記録されます。
AOFはMySQLのバイナリログのようなイメージで、更新処理の記録が追記されているため、Point-in-time recovery も可能です。
1 2 3 |
save 900 1 save 300 10 save 60 10000 |
RDB、AOF共にディスクに書き出すタイミングを指定できますが、RDBはデフォルトのまま、AOFは更新を常に同期させる(appendfsync always)の2つのパターンでベンチマークを計測しました。
1 2 |
appendonly yes appendfsync always |
MySQLの InnoDB Memcached プラグイン
データはInnoDBのテーブルに格納されるため、データの永続化は基本的にはMySQLの設定に準拠します。
(例えば、innodb_flush_log_at_trx_commit はデフォルト 1 なのでコミットのたびにディスクにフラッシュされ、クラッシュしてもコミット済みのデータが消失することはありません)
今回のベンチマークでは、以下の2通りの設定で行いました。
データの安全性重視
1 2 3 4 |
[mysqld] innodb_buffer_pool_size = 20GB innodb_flush_method = O_DIRECT innodb_flush_neighbors = 0 |
速度重視
1 2 3 4 5 6 |
[mysqld] innodb_buffer_pool_size = 20GB innodb_flush_method = O_DIRECT innodb_flush_neighbors = 0 innodb_doublewrite = 0 innodb_flush_log_at_trx_commit = 2 |
Memcached プラグインの設定でも高速化することは可能ですが、弊社の検証環境ではこれらの設定を変更すると安定性が極端に低くなったため、デフォルトのままにしています。
参考
- MySQL :: MySQL 5.7 Reference Manual :: 14.20.5.3 Tuning InnoDB memcached Plugin Performance
- https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_daemon_memcached_option
ベンチマーク方法
memtier-benchmark をインストールして以下の設定でベンチマークを行いました。
項目 | 値 |
---|---|
スレッド数 | 8 |
クライアント数 | 15 (スレッド単位なので合計120) |
テスト時間 | 30秒 |
Redisの場合
1 |
$ memtier_benchmark -t 8 -c 15 --test-time=30 |
Memcached と MySQLのMemcachedプラグインの場合
1 |
$ memtier_benchmark -p 11211 -P memcache_text -t 8 -c 15 --test-time=30 |
テスト結果
Memcached
1 2 3 4 5 6 7 8 |
ALL STATS ======================================================================== Type Ops/sec Hits/sec Misses/sec Latency KB/sec ------------------------------------------------------------------------ Sets 28099.01 --- --- 0.37800 1918.03 Gets 280969.68 118.90 280850.78 0.37300 7110.82 Waits 0.00 --- --- 0.00000 --- Totals 309068.69 118.90 280850.78 0.37300 9028.85 |
Redis (RDB設定)
1 2 3 4 5 6 7 8 |
ALL STATS ======================================================================== Type Ops/sec Hits/sec Misses/sec Latency KB/sec ------------------------------------------------------------------------ Sets 11805.49 --- --- 0.92400 909.66 Gets 118032.86 24.00 118008.86 0.92200 4022.39 Waits 0.00 --- --- 0.00000 --- Totals 129838.35 24.00 118008.86 0.92200 4932.05 |
Redis (AOF設定)
1 2 3 4 5 6 7 8 |
ALL STATS ======================================================================== Type Ops/sec Hits/sec Misses/sec Latency KB/sec ------------------------------------------------------------------------ Sets 5418.64 --- --- 2.23600 417.55 Gets 54165.53 12.41 54153.12 2.06600 1845.84 Waits 0.00 --- --- 0.00000 --- Totals 59584.18 12.41 54153.12 2.08100 2263.39 |
MySQL (データ安全設定)
1 2 3 4 5 6 7 8 |
ALL STATS ======================================================================== Type Ops/sec Hits/sec Misses/sec Latency KB/sec ------------------------------------------------------------------------ Sets 1687.43 --- --- 8.68300 115.19 Gets 16853.49 23.93 16829.56 6.24800 427.44 Waits 0.00 --- --- 0.00000 --- Totals 18540.92 23.93 16829.56 6.47000 542.63 |
MySQL (速度重視設定)
1 2 3 4 5 6 7 8 |
ALL STATS ======================================================================== Type Ops/sec Hits/sec Misses/sec Latency KB/sec ------------------------------------------------------------------------ Sets 18994.62 --- --- 0.58100 1296.61 Gets 189927.61 145.87 189781.74 0.55100 4810.58 Waits 0.00 --- --- 0.00000 --- Totals 208922.23 145.87 189781.74 0.55400 6107.19 |
項目 | Sets | Gets |
---|---|---|
Memcached | 28099.01 | 280969.68 |
Redis (RDB) | 11805.49 | 118032.86 |
Redis (AOF) | 5418.64 | 54165.53 |
MySQL (安全) | 1687.43 | 16853.49 |
MySQL (速度) | 18994.62 | 189927.61 |
まとめ
やはりディスクアクセスが無い分、Memcached が最も高速でした。
MySQL も速度重視の設定にすればそれなりのパフォーマンスを発揮しましたが、innodb_* の設定はインスタンス全体で共通のため、通常のMySQLとしての使い方とMemcachedプラグインを併用する場合は注意が必要になります。
次回はPHPを使ったSQLとMemcachedプロトコルのベンチマーク比較です。