TwilioのRedisによる決済サービスの障害、2つの原因
Twilio というサービスで決済サービスの障害があったらしいが、恐しいことにこのサービス、 決済情報をRedisで管理していたらしい、というのをRedis作者、antirez氏のblogで知った。
この件に関しては、Twilio自体も 調査報告 を出している。簡単にまとめるとこういう感じだ:
- TwilioではRedisを single-master, multi-slave なレプリケーション環境で使用している
- ネットワーク障害で一時的に master-slave 間の接続が切れたことにより、master-slave間のデータの再同期が発生
- この再同期がすべてのslaveに対して同時に発生したため、masterの負荷が高くなり、結果決済サービスの障害が発生
- この負荷を解決するためmasterを再起動するが、この際にRedisの設定ミスにより、あやまったバックアップファイルをロードしてしまい、結果決済データの損失が発生
レプリケーション再同期でmasterの負荷が上がった?
Twilioはそうレポートしているが、antirez氏は「メモリが足りないというような状況でなければ、通常、Redisはmaster-slave間でのデータ再同期で負荷があがることはない」と主張している。 AOF Rewritingしているときにはかなりメモリに余裕がないとswapしてしまうということが知られているし、再起動したあと負荷があがらなかった(再同期が原因ならmaster再起動時にも同じように高負荷になるはず)ことからも、Twilioのmasterサーバになにかが起きていたと考えられる。
antirez氏も書いているが、Twilioはその原因を調べる必要があるだろう。
またこの再同期、現在は必ずすべてのデータセットの再同期が必要になるため、データ量が多いと転送量がとてもすごいことになってしまうという問題もあるが、 これは次期バージョンである2.8で partial resynchronization という機能が導入され解消される、とのことだ。
Redisの設定ミス
Twilioのレポートではmaster再起動時に存在しない append only ファイルを読みこもうとした、とあるがちょっとこれは考えにくい。 そのような状況が起こるとすると、
- snapshotベースで運用しているRedisを可用性の高いappend onlyログに移行しようと考える
- redis.confにその設定を書く
- 設定は書いたものの、動作中のRedisに対してその設定をCONFIG SETコマンドで反映していない
- その状態で再起動したため存在しないaofファイルを読み込もうとしてデータが空に…
という、append onlyしたつもりがそうなっていなかった、という、かなりいい加減な状態で運用していたことになる。 しかし、レポートでもデータが空になった、とあるからほんとにこうだったのかもしれない…。
個人的にやっちゃいそうだと感じたのは、この逆の、動いてるRedisに設定は反映したが、redis.confに書くのを忘れる、というもので、その場合は以下のようになる。
- snapshotベースで運用しているRedisを可用性の高いappend onlyログに移行しようと考える
- 動いているRedisにその設定をCONFIG SETコマンドで反映
- append onlyファイルができはじめたのを確認する
- やれやれと安心してredis.confにも同様の設定をするのを忘れる
- この状態でRedis再起動すると、redis.confには設定がないので古い(可能性のある)snapshotファイルをロードしてしまう
気をつけよう。
次期バージョンであるRedis 2.8ではこの問題を少しでも解決しようと、 CONFIG REWRITE というコマンドで、redis.confの書き換えを行えるらしい、 が、結局それを忘れたら同じことなのでこの問題の解決にはなるかは微妙なところだ。 メモリ上にしか反映されていない設定があるかどうかをなんらかの方法でチェックすることができれば監視するなどできると思うのだが…。
Redisの可用性
「ウゲェ! 決済データをRedisで管理するなんてWTF!」みたいな意見もあるかもしれないが、append only ログを使った場合の Redis のデータ可用性は実はかなり高い。 しかしやはり、こなれたデータベースとちがって安定して運用するノウハウがまだまだ足りないためにこういう事故がおこってしまう。
このような(ありがたい)先人の事例を他人事だと思わず、肝に命じ、手元の環境を見直し続けていく必要があると感じた。