ElasticsearchとSSDのTRIMの関係

*2018年7月9日 : このブログは、本番環境で大幅な速度低下を防ぐためにいつディスクのTRIMをしないようにするかという項目が追加されました *

「TRIM」を有効にしていますか?

ElasticではElasticsearchのパフォーマンスのベンチマークを定期的に行っており、その結果を 公開しています。これまでにパフォーマンスの低下に一定のパターンがあることが判明しました:

recurring-elasticsearch-slowness

上図を見ると、2016/9/26のピークパフォーマンスが2016/10/3まで徐々に低下し、その後また2016/10/10に上昇に転じるまで、パフォーマンスは低下を続けていることがわかります。このようなパターンにお気づきだったでしょうか?

| 日付 | 曜日 | | ---- | --------------- | | 2016/09/26 | Monday | | 2016/10/03 | Monday | | 2016/10/10 | Monday |

月の満ち欠けが原因とは思えないわけで、どうしてこのようなパフォーマンス低下が起きるのかを探るために OS で毎週実行されるジョブを調べてみることにしました。ベンチマークはベアメタルサーバーで2 台の SSD ドライブをソフトウェア RAID-0 構成にし、Ubuntu 16.04 をインストールして行っています。以下は、Ubuntu Server 16.04 LTS ベースの仮想マシンでの cron.weekly の内容です。fstrim ジョブに注目してください。

vagrant@ubuntu1604vbox:/etc/cron.weekly$ ls
fstrim  man-db

ところでTRIMって何?

Wikipedia の記事によれば:

trim コマンド(ATA コマンドセットでは TRIM、SCSI コマンドセットでは UNMAP)は、データのブロックが未使用とみなされ、内部的に削除可能であることを OS がソリッドステートドライブ (SSD) に通知できるようにします。

SSD ドライブはフラッシュ (NAND) メモリセルで構成されています。従来の磁気ディスクとの次の 3 つの大きな違いが SSD ドライブのパフォーマンスに影響します:

  1. メモリセルは 1 回の操作では上書きできません。つまり、まず既存のデータを削除してからでないと、新しいデータに置き換えることはできません。
  2. メモリセルがサポートできるプログラム/削除サイクルが限られています。
  3. メモリセルはページとブロックで構成されているため、SSD ドライブは、ブロック丸ごとでないと削除できない!

このような制限により、製造元が苦肉の策として実装したのが ガベージコレクション です。ガベージコレクションでは、データが含まれるページと削除対象のページの両方がデータが含まれるページが、空きブロックにコピーされた後で削除されます。したがって、内部的に、SSD ドライブが生成する IO は、OS によって明示的に生成される書き込み操作より多くなります。この現象は ライトアンプリフィケーションと呼ばれます。

OS がファイル削除のリクエストを受け取っても、ファイルシステムはメタデータを更新するだけで、実際のデータが入っているディスクアドレスは削除されません。これにより、GC実行中に SSD ドライブではさらに多くのライトアンプリフィケーションが発生してしまいます。この問題を解決するために、OS は TRIM コマンドを発行して OS にデータが消去されたことを知らせることができます。これには 2 つのメリットがあります:

  • GC 実行中に不要なデータ(すでに OS によって削除されたデータ)の動きを阻止できる
  • 空き領域が増えるため、GCの効率が上がる

つまり、どういうこと?

ファイルシステムが削除されたファイルに関する情報を SSD ドライブに通知できれば、SSD ドライブの処理は速くなります。fstrim crontab プロセスが Ubuntu で実行するのはまさにこれです。

そんなに違いが出ますか?

ええ!まったく違います。2016/10/17 以降に fstrim ccronjob を毎日実行するようにスケジュールに移した後、グラフが安定したのがわかります:

elasticsearch-performance-after-trim

以下は、TRIM を実行しないで 10 回連続で異なる(PMC)ベンチマークを実行した結果ですが、TRIM 実行なしの場合にどれほどの影響が出るかがよくわかります。ファイルシステムではベンチマーク開始前に 1 回だけ TRIM を実行しています。

ten-rally-benchmark-iterations-notrim

TRIMを実行「しない」理由はありますか??

ベンチマークを実行する前にディスクのTRIMを実行することは(一例として)理にかなっていますが、本番環境ではそれを実行したくない理由があるかもしれません。

ディスクでTRIMが実行されるまでの時間によっては、TRIMの実行中にディスクの性能が大幅に低下し、TRIMの完了するまでに長時間かかることがあります。

  • Elastic Cloud Enterprise(ECE)のインストールでは、システム全体に影響があるため、長時間のTRIM実行中にコントロールプレーンが不安定になることがあります。そのため、ECEディスクに対して手動でTRIMを実行することは避けてください。
  • そのほかの本番環境の事例では、トラフィックが少ない時間帯にのみ実行されるスケジュールにすることを推奨します。また、頻繁に実行される場合は定期的なTRIM実行を完全に無効にすることを推奨します。

注意

CentOS-7 では、fstrim.service と関連する systemd タイマーがデフォルトで無効になるため、このサービスを有効にする必要があります。また、おそらくデフォルトのタイマースケジュールも上書きする必要があります。LVM を使用していてサイズ変更操作を頻繁に行う場合は、/etc/lvm/lvm.confissue_discards を 1 に設定する必要があります。dm-crypt Linux 暗号化レイヤーを使用する場合も、特殊な処理が必要になります。lvm/dm-crypt で TRIM を設定する手順については ArchLinux wiki ページを参照してください。

クラウドインスタンスで SSD ディスクへの直接アクセスが許可されている場合、TRIM の問題はクラウドインスタンスにも影響します。一部の Amazon Instancesの Instance Store-Backed Linux AMIがこれに該当します。

まとめ

Elasticsearch は IO インテンシブアプリケーションです。 SSD ストレージで実行している場合は、TRIM が有効になっているかどうかを確認し、負荷に応じて TRIM ジョブの実行頻度を調整する必要があります。 驚くほどパフォーマンスが向上しますよ!