Bali, Indonesia
Insights

Anatomi Stalling Linux Dirty Page Writeback Saat Lonjakan Flush Redo Log Payment Gateway

Invalid Date
0:00
Pernahkah Anda menyaksikan payment gateway yang biasanya memproses transaksi dalam 30 milidetik tiba-tiba melesat ke 8.000 milidetik, tepat saat kampanye flash sale tanggal kembar dimulai? Di layer aplikasi, metrik CPU dan memori database terlihat normal—utilisasi CPU bahkan sering kali anjlok drastis di bawah 25%. Namun, antrean koneksi di connection pool meledak, transaksi perbankan timeout berjamaah, dan log PostgreSQL atau MySQL dipenuhi barisan worker thread yang tersangkut dalam status D (uninterruptible sleep). Fenomena ini berakar dari dilema fundamental yang dieksplorasi dalam riset Yue Qi mengenai konsistensi data dan skalabilitas pada sistem pembayaran berkonkurensi tinggi (Data Consistency and Scalability in High-Concurrency Payment Systems). Riset Qi menggarisbawahi bahwa pemaksaan konsistensi transaksi absolut secara terpusat menciptakan titik jenuh write I/O yang parah. Dalam ranah Linux kernel, titik jenuh ini bermutasi menjadi petaka spesifik: mekanisme writeback throttling pada Page Cache yang mengunci worker thread database saat volume dirty pages melampaui batas kewajaran.
Secara default, Linux memperlakukan memori utama sebagai penyangga asinkron (buffered cache) untuk mempercepat operasi penulisan disk. Ketika database memodifikasi data page, halaman memori tersebut ditandai sebagai dirty. Di balik layar, kernel mendelegasikan proses penulisan ke disk kepada thread kworker melalui mekanisme flusher background ketika dirty memory melampaui ambang batas vm.dirty_background_ratio (biasanya 10%). Masalah fatal muncul ketika server database dilengkapi RAM raksasa—misalnya 256 GB atau 512 GB—namun tetap menggunakan konfigurasi sysctl default berbasis persentase. Jika vm.dirty_ratio bernilai 20%, artinya kernel mengizinkan hingga 50–100 GB dirty pages menumpuk di RAM sebelum intervensi agresif dijalankan. Ketika lonjakan transaksi pembayaran memaksa ribuan mutasi saldo dan insert ledger per detik, laju produksi dirty pages melesat jauh melampaui kemampuan sustained write controller storage NVMe. Begitu ambang vm.dirty_ratio terlewati, kernel mengeksekusi fungsi balance_dirty_pages() di dalam loop penulisan I/O. Pada titik ini, kernel tidak lagi menyerahkan writeback ke thread background. Sebaliknya, kernel memanggil throttle_vm_writeout() yang secara paksa membajak thread aplikasi database yang memanggil write(). Worker thread tersebut dipaksa berhenti memproses kueri SQL dan diubah menjadi flusher darurat yang menulis dirty pages secara sinkron ke disk. Hasilnya adalah I/O pause brutal yang melumpuhkan thread pool database secara serempak.
BASH
# Periksa metrik penumpukan dirty pages saat ini
cat /proc/vmstat | grep -E 'nr_dirty|nr_writeback|nr_dirtied|nr_written'
Pada transaksi finansial, konsistensi data bersifat non-negotiable: setiap perubahan saldo harus dijamin persisten ke disk sebelum status sukses dikembalikan ke user. Database mengamankan ini melalui Write-Ahead Logging (WAL pada PostgreSQL atau Redo Log pada InnoDB). Setiap kali transaksi melakukan commit, database memanggil fdatasync() atau fsync() pada file log transaksi tersebut. Bencana performa meletus ketika Redo Log dan data directory (tempat dirty data pages disimpan) berbagi partisi atau physical disk pool yang sama. Ketika mekanisme balance_dirty_pages() terpicu, antrean I/O block device seketika dibanjiri oleh jutaan blok data acak dari checkpoint dan dirty table writeback. Di tengah saturasi antrean request queue (nr_requests), thread database yang sedang berusaha memanggil fsync() untuk sebaris commit log kecil (hanya 4 KB) tertahan di belakang antrean dirty pages raksasa tersebut. Kondisi ini memicu apa yang dikenal sebagai lock convoy. Mutex internal database—seperti WALWriteLock di PostgreSQL atau log_sys mutex di MySQL InnoDB—tertahan selama ratusan milidetik oleh thread yang menunggu I/O. Akibatnya, seluruh worker thread lain yang hendak melakukan commit terantuk pada mutex yang sama. Latensi commit melonjak eksponensial, dan timeout merambat ke layer payment adapter di depan.
Langkah kuratif pertama adalah mencabut konfigurasi berbasis persentase yang berbahaya pada mesin dengan kapasitas memori besar, lalu menggantinya dengan batasan berbasis byte absolut. Tujuannya adalah membuat kernel memicu background flushing lebih awal dan sering dalam porsi kecil (trickle flush), bukan menimbun puluhan gigabyte dirty memory yang memicu badai I/O massal.
BASH
# Terapkan batas byte ketat agar buffer flusher tidak menumpuk
sysctl -w vm.dirty_background_bytes=268435456   # 256 MB
sysctl -w vm.dirty_bytes=1073741824              # 1 GB
sysctl -w vm.dirty_writeback_centisecs=100       # Flush cycle per 1 detik
Dengan mematok vm.dirty_background_bytes pada 256 MB, thread background kworker akan terus-menerus menyapu dirty page ke disk secara konstan tanpa membiarkan beban terakumulasi. Jika terjadi lonjakan I/O abnormal, vm.dirty_bytes pada 1 GB memastikan pembatasan terjadi sebelum sistem terkunci oleh antrean ratusan gigabyte. Disk controller NVMe modern dapat mencerna 1 GB penulisan dalam hitungan ratusan milidetik, menjaga latensi tetap terkendali.
Menyetel kernel saja tidak menyelesaikan akar masalah jika arsitektur storage masih menyatukan write-path sequential redo log dengan random write table pages. Solusi paling deterministik pada level infrastruktur adalah mengisolasi Redo Log/WAL ke disk NVMe terdedikasi dan memaksanya beroperasi via Direct I/O (O_DIRECT atau O_DSYNC). Direct I/O melewati Linux Page Cache seutuhnya. Penulisan WAL langsung dikirim dari memory buffer database ke controller NVMe melalui antrean submission queue hardware, terbebas dari campur tangan Page Cache dan kebal terhadap balance_dirty_pages(). Untuk disk data tables, gunakan scheduler I/O none (atau mq-deadline) pada subsistem block multi-queue (blk-mq) Linux guna memangkas overhead locking software kernel. Kembali ke tesis riset Yue Qi: keandalan payment gateway berskala besar pada akhirnya tidak bisa diselesaikan hanya dengan tuning parameter disk semata. Perlu ada segmentasi konsistensi di tingkat software. Mutasi saldo inti yang memerlukan jaminan mutlak harus dipisahkan dari pencatatan riwayat audit dan notifikasi transaksi yang toleran terhadap eventual consistency via outbox pattern. Tanpa segmentasi arsitektural ini, kapasitas write controller disk terbaik di dunia pun pada akhirnya akan menyerah ketika volume dirty pages melampaui batas fisika storage Anda.