たまにはPowerShell 以外の記事を。
某記事でもRedis (REmote DIctionary Server)が memcached に代わり得る利点がBookSleeveを交えて丁寧に説明されました。
そして、Redisの運用が一定の目途を見せていることから、その初期設定に欠かせないチューニングについて記事にしてみようと思います。 全部明かすわけではありませんが、なかなかRedisに関する記事は少ないので、少し参考になれば幸いです。
経験上、高負荷環境ではRedisはチューニングで大幅に安定性が変わります。 インストール? 沢山記事ありますし、簡単なのでここでは省きます。 どうしても!な場合は希望していただければ記事にしますが。
Redis Quick Start
対象バージョン
2.6系とします。 2.4系でも大方一緒ですが、2.6系に特有な部分があるので、注意です。
対象OS
Redis は Linux ベースでの運用を主眼に置かれています。 Win32/64は直接サポートではありませんのでご注意を。一応、Microsoft Open Tech group が実験版の開発とメンテを行っているようですが。
Download
今回のチューニングは Linux、特にAWS EC2インスタンスです。
負荷と環境
ざっくりと注意点を並べておきます。
Call
20000 call /sec ~ が常時かかっている状況に平然と耐えれる程度ということで。 当然ベンチでは 40000 call /sec 超えますが平均しておきましょう。
Connection
5000 conn/every も耐えますが、その辺は実際のRedis 負荷になるのが call なので一定の目安にしかなりません。
CPU
CPU に関しては、 RedisはSingle Threadで動作することもあり、動作中はそれほど CPUを喰いません。 とはいえ結構カツカツまで利用すると 1 core 80%とかも目指せます。
このあたりは、繰り返しますが、Call に依存する部分が大きいのは当然といえば当然ですが、BookSleeveを活用した PipeLining は当然必須です。
High System CPU Usage Redis latency problems troubleshooting
AOF での Disk I/O、 RDB のDir 指定ミス、 RDB での bgsaveに伴う BackGround Threadへのrdb処理時 などにCPUが膨らみますが、その辺は日本語では記事がないですね。 もったいないです。 (でもここでは書きません(( )
Persistence
Persistence = 永続化ですが、今回は Apend Only File ではなく RDB を採用した場合とします。 RDB と AOF に関しては、 Persistence の程度は勿論の事、Letency にも大きくかかわるため、良く考慮してください。
Redis Persistence Redis latency problems troubleshooting
Virtual Environment
Virtual Memory ではありません、 仮想環境です。 Virtual Memory は、サルバトーレ御大も失敗と認め 2.4で廃止と明言していますので、くれぐれも使われないように (
Virtual Memory
Redisですが、 仮想環境 (Amazon EC2もそうですね) 、で 物理環境の同一性能 マシンに比較して性能を落とすことが公式に認められています。
Redis latency problems troubleshooting
Fork time in different systems Modern hardware is pretty fast to copy the page table, but Xen is not. The problem with Xen is not virtualization-specific, but Xen-specific. For instance using VMware or Virutal Box does not result into slow fork time. The following is a table that compares fork time for different Redis instance size. Data is obtained performing a BGSAVE and looking at the latest_fork_usec filed in the INFO command output.
- Linux beefy VM on VMware 6.0GB RSS forked in 77 milliseconds (12.8 milliseconds per GB).
- Linux running on physical machine (Unknown HW) 6.1GB RSS forked in 80 milliseconds (13.1 milliseconds per GB)
- Linux running on physical machine (Xeon @ 2.27Ghz) 6.9GB RSS forked into 62 millisecodns (9 milliseconds per GB).
- Linux VM on 6sync (KVM) 360 MB RSS forked in 8.2 milliseconds (23.3 millisecond per GB).
- Linux VM on EC2 (Xen) 6.1GB RSS forked in 1460 milliseconds (239.3 milliseconds per GB).
- Linux VM on Linode (Xen) 0.9GBRSS forked into 382 millisecodns (424 milliseconds per GB).
Redisの構築
某謎社の場合、インストールとベース設定は【EC2のSnapshot運用】 、個別のチューニングが 【capistranoを利用したチューニング適用】でほぼ自動化しています。
例えn台あったとしても、 実行時と実行後の設定周り確認も含めて、新規インスタンスを起動から運用にいれるまでは 30分 もあれば終わります。 (大半が EC2のSnapshot起動なのですが)
それだけ Redisは 安定しており、チューニングも一定の効果をキッチリ出せる極めて優れた品質と言えると思います。
PV か HVM インスタンスの選択
Amazon Linux といえば、Xen ですね。2013年までは PVが主流でしたが、2014年以降は HVMが主流です。
HVMでないと、r3インスタンスも使えず、またネットワーク周りの高速化、CPUの IvyBridge系利用もできずシングルスレッド処理も伸びません。
間違いなく HVMインスタンスを使わない理由はないので、ぜひ PVは捨ててください。
Linux Tuning
ようやく主題となるチューニングです。 まず Linux Tuningから見てみましょう。
IPv6周り
当然というかなんというか、 IPv6 を使わず IPv4 でそろえた方が安定性が高いのは事実です。 残念ですしこれが最善ともおもいませんが、 LAN内部においてはまだまだ IPv4 が安定して利用できるのは事実です。
resolv.conf
IPv4なら当然この要素は外せません。 EC2の場合は、実は少しトリックが要りますが省きます。
options single-request-reopen
他のIPv6関連もげもげは、まぁ大丈夫ですよね。
ただ、2014年9月以降のHVM インスタンスでは resolve.conf をいじらずとも v4通信のみがredisで動いているので余り気にしなくても大丈夫です。
sysctl周り
負荷具合にもよりますが、この辺は大事です。
/etc/sysctl.conf
に記述することで、再起動後も適用されています。 嫌なら sysctlとか/proc書き換えでどうぞ。
port_range
linux のデフォルトポートレンジでは足りないほどの高負荷環境。 それならば設定は必要ですね。 最大域にするならこうです。 むしろそこまで高負荷環境ではこの程度は焼け石に水ですが、まぁ後述の設定が出来るなら此処はあまり問題になりません。
net.ipv4.ip_local_port_range = 1024 65000
somaxconn
memcached でもbacklog と並んで重要なパラメータですが、Redisでも当然重要です。 状況によるかと思いますが、例えば1024にするなら以下です。
net.core.somaxconn = 1024
tcp_fin_timeoutと tcp_tw_recycle
tcp_tw_recycleですが、 NAT環境でパケットのtimeoutがほげほげでsyn_packetがという問題を良く理解した上で設定を施すか考慮、検証しなくてはいけません。
繰り返しますが、気安くやるとネットワークが意図せず不通/パケットロストになるなど「痛い目にあう可能性がある」ので気を付けてください。
また、tcp_fin_timeout設定は tcp_tw_recycleを有効にした上でないとデフォルト値の60secから変わりませんのでご注意ください。(あるいは linux sourceで cいじってbuildでもいいですけど)
※ もしこの設定が適用できる場合、 port_rangeに関しては不要になる可能性が高いです。 例えば、tcp_fin_timeout を 30秒にするなら以下です。
net.ipv4.tcp_fin_timeout = 30
例えば、tcp_tw_recycle を 有効にするなら以下です。
net.ipv4.tcp_tw_recycle = 1
FileDescriptor周り
Redisに限らず ネットワークのやり取りが多い場合は当然必要です。 limits.conf や pam.dのチューニングは必ず行いましょう。
その他 Kernel チューニング
最も大きく関わる足回りを中心に紹介しました。 その他は環境に応じて、各自の設定があるかと思います。
Redis Config
デフォルトでは、 /etc/redis/redis.conf です。 redis.conf のチューニングに関しては、それほど複雑でもありません。 また、AOFではなく RDBのパターンなので、 latencyにも気を使う必要が小さく簡単です。
daemonize
daemon化すると redis のログは出力されません。 ご自由にどうぞ。
daemonize yes
pidfile
敢えて理由がない限りは変更の必要はないですね。 ご自由にどうぞ。
pidfile /var/run/redis.pid
port
デフォルトは TCP 6379です。 iptableにSELinux など各自の事情に応じてどうぞ。
port 6379
bind
バインドするnetworkインターフェースです。 特に理由がなければremarkしても問題ありません。 ご自由にどうぞ。
# bind 127.0.0.1
unixsocket
unix domain socket 利用する場合です。 Appと同一サーバーにするなどでしか使いませんが、さて。 TCP/IPを利用するなら リマークです。 ご自由にどうぞ。
# unixsocket /tmp/redis.sock # unixsocketperm 755
timeout
クライアントから n 秒間の通信がない場合のタイムアウトです。 0でtimeout無しです。 port使用状況 や connectionの張り方に応じてどうぞ。
timeout 600
TCP keepalive
もし 0出ない場合、クライアントとの無通信時に TCP ACKs を送るのに SO_KEEPALIVE を利用します。 ダメになった peerの検出や、ネットワーク維持の明示に役立ちます。 推奨値は 60 (秒)です。
tcp-keepalive 60
loglevel
logの程度です。 出力はdaemon次第ですので悪しからず。 debug、verbose、notice、warningとありますが、本番では noticeが推奨です。
loglevel notice
logfile
logfileの出力先です。 daemonにしてると 設定値がどうあれ、/dev/null に破棄されますのでご注意を。
logfile /var/log/redis/redis.log
syslog-enabled
syslogを有効にするかです。 お好きにどうぞ。 勿論リマークも可です。
# syslog-enabled no
syslog-facility
syslogを実行する際のアレです。 USERか、LOCAL0-LOCAL7である必要あります。
# syslog-facility local0
database
利用するdatabaseの数です。 デフォルトは DB 0を利用し、0 ~ databses-1 まで利用可能です。
databases 16
Snapshot
RDBに関することだけにしますね。
save
RDBを取る頻度です。 save n x とは、n秒にx 回の変更に付き bgsave を行うという考えです。 saveしない (In-Memoryとしての利用) 場合、 save "" となります。
save 900 1 save 300 10 save 60 100000
stop-writes-on-bgsave-error
Redis は、 RDBが有効 & 前回の bgsave が失敗した場合、書き込みを受け付けなくなります。 こうすることで、 redis-infoなどでpersistence が失われている異常事態が分かるようにしています。
通常は無効にしないと思いますが、モニタの都合なので Disk 異常でも働かせたい場合に無効にします。
stop-writes-on-bgsave-error yes
rdbcompression
RDBは メモリのダンプですが、保存するときに 圧縮するかどうかです。 圧縮すると CPUは喰うものの、容量が大幅に圧縮できます。
rdbcompression yes
rdbchecksum
CRC64でのRDBのchecksum検査をお熟します。 破損の検知は永続性で最重要なので、行わない理由はないかと。 ただし、RDBのsaveとloadで10%のパフォーマンス低下が起こります。
rdbchecksum yes
dbfilename
RDBファイル名です。
dbfilename dump.rdb
dir
RDBを保存する、パスです。 先のdbfilename とセットになって、保存フルパスが定まります。
このパスを間違えると、 RDBのbgsaveに失敗し、Redis のCPU が常に高い状況が起こりえます。 Redis で CPUが常に100%なのはまずありません。異常事態なので必ず存在するパスである事、権限などRDBが生成できている事などを確認しましょう。
dir /var/lib/redis/
REPLICATION
Slaveは今回省きます。
SECURITY
Securityは今回省きます。
LIMITS
2.6.12あたりで FileDescriptor周りが変わりました。
maxclients
最大接続クライアントです。 デフォルトでは 10000となります。 ここは file descriptor に上限が左右されます。(File Descriptor -32) 上限に達すると、'max number of clients reached' とエラーを返します。 無効にする場合は、 #maxclients とリマークします。
maxclients 10000
maxmemory
Redisが利用する最大メモリ(bytes)です。 そのままですね。 無効にするとシステムの最大まで利用を試みます。 無効にする場合は、 # maxmemory とリマークします。
# maxmemory <bytes>
MAXMEMORY POLICY
基本的には変更に必要がないです。 maxmemoryに到達した時にredisがどのようにmemory を開放するかの処理です。
# maxmemory-policy volatile-lru
APPEND ONLY MODE
AOFは今回省きます。 基本的には無効にするように設定しておきます。
appendonly no appendfsync no no-appendfsync-on-rewrite no
LUA SCRIPTING
LUA SCRIPTINGを利用する場合に使用します。 最大実行時間の設定のみで、デフォルトでも十分実用値です。
lua-time-limit 5000
SLOW LOG
処理に時間がかかったのモノを SLOW LOGに残す際の閾値です。 latencyの計測には欠かせません。
slowlog-log-slower-than 10000 slowlog-max-len 128
ADVANCED CONFIG
基本的には初期値のままでとサルバトーレ御大も行っていますが、まぁしたい人はどうぞ。 ここでは省きます。
まとめ
いかがでしたでしょうか。
Linux / Redis 両面での推奨設定値を挙げるという事はしませんでしたが、日本語での説明も含めて目安となれば幸いです。
Redisはチューニングされていない linux & Redis でもある程度快適に動きます。 が、本気でチューニングした時との安定性は格段に上昇し、速度もキッチリ出ます。
EC2 の 同一 VPC / 同一 Zone 内部であれば ほぼ 遅延はなく、実質 network latency のみとなる (つまり 0.0x ms の処理) が実現できます。
是非、memcached などから Redis にメリットを感じる (C# なら特に!) 状況の場合は、採用されるといいかと思います。