redisをAutoScaling環境で使う場合はtimeoutの設定に注意
Redisをstorageやcacheとして使う事が多くなってきたのですが、普段使っている分にはさほど問題なかったものがautoscaleなどの頻繁なインスタンスの増減がある環境でtimeoutを上手く設定していないと問題が出る場面に遭遇したのでメモしておきます。
Redisのtimeout値(コネクションは貼られているが、コマンドが送られて来ない時間)はdefaultで300秒になっています。
この値を何らかの理由で0(無効)やとても長い時間に設定している場合、正常にコネクションがcloseされないと、Redis側からはESTABLISH状態に見えたままになていることがあります。
この状態の時はnetstatで確認してもESTABLISHEDになっています。
今回この場面に遭遇したときは、インスタンスの増減が頻繁に行われている時で、Redisの接続が失敗する事が増えてきたため気づきました。
その時の様子です
Redisはmaxclientsを明示的に設定しない場合、ulimitの4,064に設定されます。
redis 127.0.0.1:6379> CONFIG GET maxclients 1) "maxclients" 2) "4064"
この値以上に増やす場合は
ulimit -Sn 100000 sysctl -w fs.file-max=100000
このように設定したあと、設定ファイルかCONFIG SET maxclientsでmaxclientsを増加させます。
files limit以上に設定しようとするとエラーがでます。
timeoutは動的に設定可能でredis-cliをつかって
redis 127.0.0.1:6379> CONFIG SET timeout 3600
の様に設定します。単位は秒です。
configファイルも同じくtimeoutの項目を書き換えておくと、次回再起動した際にも反映されます。
timeout値を適切に設定した後、先ほどのグラフで一気にコネクション数が下がっているのがわかると思います。今回は少し長すぎました。
timeoutが設定されると、無通信状態がその値を超えると、切断されるため、アプリケーション側で再接続処理を考えて置く必要がありますが、ライブラリはだいたい考慮されているかと思います。
接続数があまり変わらない環境では起こりにくいかとおもいますが、クラウドでインスタンス数などの増減が激しい場合はちょっと注意が必要です。
インスタンスやアプリケーションの実行プロセスが終了される時に、適切にcloseが呼ばれればいいのですが、いきなりシャットダウンなどが行われる環境では起こりやすくなります。
AutoScaling便利ですが、縮退される時は一気にterminateされるので、切り離されてるとはいえ正常な切断にならないことが発生するので注意が必要です。