Google Cloud SQL for MySQLがダブルバッファーライトをやめて16KiBのアトミックなダイレクトI/Oを実現するまで
まとめ
AWSはre:Invent 2022でRDS MySQLの書き込みスループットが最大で2倍になる機能を発表しました。
x86_64アーキテクチャの場合、1ページの大きさは4KiBです。
複数ページにまたがるデータをflush中に障害が起こると、一部のページだけが書き込み成功することがあります。この状態を torn write と呼びます。
torn writeを防ぐために(torn write prevention;TWP)、MySQLにはダブルバッファーという仕組みがあり、ダーティーページをまずダブルバッファーに書き込み、その後、flushします。
flush時にtorn writeが起きたときは、ダブルバッファーからリカバリできます。
一方で、ダブルバッファーを利用するとI/Oが増えるため、書き込みスループットが伸びません。
ストレージスタックを改善し、MySQLがダブルライトバッファーを経由せずに16KiB単位でアトミックに書き込めるようにしたのが本機能です。
2018年のGoogle Cloud Nextにおいて、技術的に同等の機能を要するCloud SQL 16 KiBインスタンスの取り組みが発表されています。当時の発表から性能改善の背景を探ります。
Optimizing performance on Cloud SQL for MySQL (Cloud Next '18)
動画
概要
The doublewrite buffer is a storage area where InnoDB writes pages flushed from the buffer pool before writing the pages to their proper positions in the InnoDB data files. If there is an operating system, storage subsystem, or unexpected mysqld process exit in the middle of a page write, InnoDB can find a good copy of the page from the doublewrite buffer during crash recovery.
並列度が高い環境下で書き込みがスケールしない
512スレッドでSysbenchのOLTPワークロードを流すと、TPS(transaction/second)の性能で偏差が大きく、前半では3倍、後半では10倍程度と振れ幅が大きい。
キャパシティプランニングが難しく、TPSが大きく落ちている後半では、大量のタイムアウトが発生しており、データベースが使い物にならない。
問題はflushの遅延
MySQLは以下の流れでトランザクションを書き込む
- トランザクションをREDOログにWRITE
- データベースページにWRITE
- データベースページを非同期にデータファイルにWRITE(flush)
REDOログとflushしたデータのサイズの差(flushラグ)をプロット
※ キャプチャは動画から
REDOログが大きくなりすぎるとリカバリ時間に影響するため、REDOログには上限(グラフの赤線)があり、ベンチマークはこの上限付近でサチっている。
この状態はsync flushモードと呼ばれる。
新規WRITE処理を停止し、古いダーティーページをflushし、REDOログの空きを作ったあとで、止めていたWRITE処理を再開する。
TPSが落ちているのはこのsync flushモード。
ボトルネックであるInnoDB Double Writeを無効化したのが次のグラフ
※ キャプチャは動画から
sync flushモードに陥らなくなり、トランザクションを滞りなく処理できるようになった。
flushラグを制御
新規書き込みよりも速いペースでダーティーページをflushできればラグは発生しない。
flushレートを上げるテクニックの一つがInnoDB Double Write Bufferの無効化
InnoDB Double Writeとは?
InnoDB Double Writeは”Double Write”の名前の通り、連続して2回書き込む。1回目がダーティーページからダブルライトバッファー、2回目データファイルへの書き込み。
なんでこんなめんどくさいことをしているかというと torn write 対策のため。
ストレージのブロックサイズより大きなサイズでflushする際の障害により、一部のページのみ書き込みが成功することがある。
この状態を"torn write"と呼ぶ。
データ不整合が起きているため、REDOログをリプレイできない。
このような障害が起きたときは、ダブルライトバッファーをソースにリカバリする。
Torn Writeが起きるのはなぜか?
Torn Writeが起きる理由は2つ
- ストレージ・レイヤー:
- ブロックサイズは4KiB
- 16KiBをアトミックに書き込みできない
- ファイル・レイヤー:
- ブロックサイズが4KiB
- ストレージのブロックサイズが16KiBでも、ファイルシステムが16KiBのboundaryでallignされていないと、複数のブロックにまたがってアトミックに書き込めない
ストレージスタックend-to-endで16KiBのアトミックな書き込みに対応
I/Oを減らすためにInnoDB DoubleWriteを無効化しても問題が起きないようにするために、ストレージスタック全体で16KiBをアトミックに書き込めるようにする
※ キャプチャは動画から
スタックの下から上に順に紹介
- ディスク(Googleの場合はPersistent Disk;PD)
- ブロックサイズを16KiBにする
- フィルシステムを16KiB
- EXT4のBigAllocを使い、16KiBバウンダリーでアライン
- Container Optimized OS
- Linuxカーネルのアップストリームの変更で壊れないようにテスト追加
- virtioレイヤー
- I/O設定の調整
- InnoDB
- O_DIRECT(ダイレクトI/O)を使って書き込み
Cloud SQLが動作するCOSの改善
Cloud SQL VMはContainer-Optimized OS(COS) のイメージで動作
Chromium OSがベース。以下の理由でリリースサイクルが短い
- セキュリティフィックス
- 機能追加
Linux Kernelのtorn write対策
16KiBデータベースページがインスタンスやハードウェアの障害のためにtorn writeにならないために次の2点を保証
- データベースファイルは16KiBのチャンク(「クラスター」と呼ぶ)でレイアウト
- IOリクエストを複数に分裂させない
Ext4 BigAllocの活用
BigAllocというExt4ファイルシステムの機能を利用
この機能はもとはGoogleのGFSのような大規模なクラスターファイルシステムでの書き込みパターンを最適化するためのもの
ファイルシステムのブロックサイズはページサイズより大きくできない
x86_64アーキテクチャの場合、このページサイズは4KiB
4KiBのブロックを2のべき乗個でひとまとまりにした「クラスター」という概念を導入(16KiB = 4Kib * (2^2))
データファイルはクラスター単位でアロケートされる
ファイルシステムは書き込みを16KiBのクラスターでトラック
BigAllocを実践導入させるには?
BigAllocはKernelのメインストリームに2011年から存在するが、限定された用途でのみ用いられてきた
Cloud SQLに導入するために、2点を決めた
- オンライン・リサイジング対応
- DBはどんどん容量が増える
- Persistent Diskを拡張できること
- 広範囲な回帰テストを追加
- BigAllocが登場してから年月が経つが、あまり使われてこなかった
IOスタックをaudit
歴史的に、Linuxを含む多くのOSは効率化のために、複数の連続するセクタへのI/Oリクエストをマージして処理
マージした結果、SCSIコントローラーやSCSIディスクの制限に引っかかる場合、制限を回避するために、リクエストを分割してきた
IOスタックの各レイヤー
- ファイルシステム
- Linuxブロック
- Linux SCSIレイヤー
- Vertio SCSIドライバー
において、これまでのように、分割しないこと、仮に分割する場合は16KiBで分割するかあらゆるコードパスを後半にauditした。
ゲストカーネルをテスト
- Linuxカーネルが今後変更されてもauditしたことを保証したい
- COSカーネルのビルド・リリースサイクルに回帰テストを追加
関わったチームは多岐にわたる
Google内の
- Cloud SQL
- COS
- Persistent Disk
- GCE Virtualization
など様々なチームとの連携の上で成し遂げられた
AWS RDSの書き込み最適化について
AWS RDSの最適化書き込みについて、関連するドキュメントを確認します。
ストレージ・ファイルシステムは次のEC2のドキュメントが該当します。
Improving write performance with Amazon RDS Optimized Writes - Amazon Relational Database Service
torn write問題やdouble bufferを無効化した場合のメリットが記載されています。
With torn write prevention, data is written to storage in all-or-nothing write transactions, which eliminates the need for using the doublewrite buffer. This prevents partial, or torn, data from being written to storage in the event of operating system crashes or power loss during write transactions. The number of transactions processed per second can be increased by up to 30 percent, and write latency can be decreased by up to 50 percent, without compromising the resiliency of your workloads.
ストレージのブロックサイズとして4KiB以外の8KiBと16KiBも選択できるようになっています。
Requirementsの動作検証環境を確認すると、
- ext4 with bigalloc enabled
- O_DIRECT file access mode to bypass Linux kernel buffer cache.
などGoogle Cloud SQLと同じですね。
続いて、RDSのドキュメントを確認します。
Improving write performance with Amazon RDS Optimized Writes - Amazon Relational Database Service
次の箇所からNitroでハードウェア(ストレージ)レベルから手が入っていることがわかります。
These databases run on DB instance classes that use the AWS Nitro System. Because of the hardware configuration in these systems, the database can write 16 KiB pages directly to data files reliably and durably in one step. The AWS Nitro System makes RDS Optimized Writes possible.
なお、RDS Optimized WritesはデフォルトでAUTO
に設定されており、利用可能な環境下では、自動的に有効化されます。
具体的には、以下の要件が必要です。
- RDS MySQL 8.0.30 以降を利用
- インスタンスタイプが db.r6i または db.r5b
Fusion-IOはdublewrite bufferが無効化される
MySQLドキュメントにあるように、doublewrite bufferが Fusion-io 上にある場合、同機能は無効化され、Fusion-ioのatomic write機能が使われます。
If the doublewrite buffer is located on a Fusion-io device that supports atomic writes, the doublewrite buffer is automatically disabled and data file writes are performed using Fusion-io atomic writes instead.
参考
- Improving write performance with Amazon RDS Optimized Writes - Amazon Relational Database Service
- Torn write prevention - Amazon Elastic Compute Cloud
- MySQL :: MySQL 8.0 Reference Manual :: 15.6.4 Doublewrite Buffer
- AWS re:Invent 2022 で発表の Torn Write Prevention と Optimized Write とは - サーバーワークスエンジニアブログ
- [試して理解]Linuxのしくみ ―実験と図解で学ぶOS、仮想マシン、コンテナの基礎知識【増補改訂版】:書籍案内|技術評論社
Discussion