Redis latency spikes and the 99th percentile

Salvatore Sanfilippo

Redisのレイテンシスパイクと99パーセンタイル

Redisについて書かれたStripeのブログ記事で興味深いのは、テスト中に取得したレイテンシのグラフを掲載していることです。Redisでディスクに永続化するには、fork()システムコールを呼び出す必要があります。通常、物理サーバーや大半のハイパーバイザーでは、大きなプロセスであってもforkは高速です。しかしXenはforkが遅いため、特定のEC2インスタンスタイプ(および他の仮想サーバープロバイダー)では、親プロセスがディスクへの永続化のためにforkするたびに、深刻なレイテンシスパイクが発生する可能性があります。この点については、Stripeのグラフが非常にわかりやすく示しています。

想像できるとおり、fork中にレイテンシテストを実行すると、親プロセスがforkする瞬間に処理中だったすべてのリクエストが、最大で1秒遅延します(上のグラフを例にした場合で、プロセスサイズやEC2インスタンスについてはわかりません)。その結果、高いレイテンシのサンプルがいくつも生じ、99パーセンタイルの結果に影響します。

この挙動を改善するために、インスタンスタイプや設定、構成などを変更するのはよい考えです。場合によっては、たった1つのリクエストでもレイテンシが高すぎることが許容できません。しかし、30分ごと(適切な書き換えトリガーでAOFを使う場合は、それ以上の間隔で)発生する1秒のレイテンシスパイクと、リクエスト全体に均等に分散するレイテンシスパイクとでは、何が大きく違うのかは、どうやら明白ではないようです。

スパイクが均等に分散している場合、ページを生成するためにRedisサーバーへ何度もリクエストを送る必要があると、ページビューでレイテンシのペナルティを受ける可能性が非常に高くなります。これはサービス品質に大きな影響を与え得ます。詳しくは、次のリンクを確認してください。http://latencytipoftheday.blogspot.it/2014/06/latencytipoftheday-most-page-loads.html

しかし、30分に1回、1秒のレイテンシが発生する場合は、まったく別の話です。まず、レイテンシが良好なパーセンタイル値は、リクエスト数が増えるほど改善します。リクエスト数が多いほど、この1秒のレイテンシがサンプル内で過大に代表される可能性が低くなるためです(1分に1リクエストしかなく、そのうち1つが高レイテンシに当たった場合は、毎秒100リクエストの場合よりも99.99パーセンタイルに大きく影響します)。

次に、大半のページビューは影響を受けません。1秒の遅延を目にするのは、fork呼び出しの瞬間に重なったリクエストを行ったユーザーだけです。それ以外のリクエストが、平均レイテンシより大幅に悪いレイテンシのリクエストに当たる確率は、極めて低いでしょう。また、forkの時刻に重なったページビューが、たとえ100個のリクエストで構成されていたとしても、1秒を超えて遅延することはありません。fork()呼び出しが終了すると、リクエストはすぐに完了するからです。

ここでの結論は、個々のリクエストごとに厳しいレイテンシ要件があるなら、時々リクエストが1秒遅延する構成は明らかに大きな問題だということです。しかし、目標が優れたサービス品質を提供することである場合、レイテンシスパイクの分布は結果に大きな影響を及ぼします。Xen上でforkが原因となって発生するRedisのレイテンシスパイクは、時間軸上では孤立した点です。そのため、ページビューが多数のRedisリクエストで構成されていても、影響を受けるページビューの割合は、レイテンシスパイクの総時間が占める割合に比例します。この場合は1,800秒に1秒なので、影響を受けるページビューはわずか0.05%です。

レイテンシの特性を1つの指標だけで捉えるのは困難です。パーセンタイル曲線全体とスパイクの分布を見れば、より正確な状況を把握できます。一般に、経験則は調査を始めるよい手がかりですし、平均レイテンシが乏しい指標であるというのも、概ね正しいでしょう。しかし、経験則を絶対的な真理へと祭り上げることにも弊害があります。私たちが物事を単純化しすぎたいと思っていても、複雑なものの多くは複雑なままであり、綿密な調査が必要なのです。

その一方で、EC2インスタンスにおけるforkの遅延は、現在最も普及している実行環境の1つでRedisを使うユーザーにとって、最悪の体験の1つです。そこで私は現在、定期的にEC2上でRedisのテストを始めています。近いうちに、Redisの公式ドキュメントにEC2固有の最適化に関するページを追加し、永続化を無効にしたマスターとスレーブのレプリカを、より安全に運用する方法も提供する予定です。

今すぐEC2上で永続化を無効にしたRedisマスターが必要なら、最も簡単に導入できる「クイックフィックス」は、Redisインスタンスの自動再起動を無効にし、フェイルオーバーにSentinelを使うことです。こうすれば、クラッシュしたマスターが自動的に利用可能な状態へ戻ることはなく、Sentinelによってフェイルオーバーされます。システム管理者は、フェイルオーバーが成功し、新しいアクティブなマスターが存在することを確認したうえで、マスターを手動で再起動できます。

追記:EC2、Xen、forkにかかる時間について興味深い情報が含まれている、Hacker Newsのスレッドを確認してください。https://news.ycombinator.com/item?id=8532851。また、すべてのEC2インスタンスが同じというわけではありません。ベアメタルシステムと同等の優れたfork時間を提供するタイプもあります。https://redislabs.com/blog/testing-fork-time-on-awsxen-infrastructure#.VFJQ-JPF8yF

原文は Salvatore Sanfilippo により に公開されました。

この記事は「gpt-5.6-luna」を使用して翻訳されました。