- Jepsen memverifikasi durabilitas dan konsistensi sistem messaging terdistribusi NATS JetStream dalam berbagai kondisi gangguan
- Hasil pengujian menunjukkan kehilangan data dan fenomena split-brain pada kerusakan file (.blk, snapshot) serta simulasi kegagalan daya
- Secara default JetStream menjalankan
fsync setiap 2 menit, sehingga pesan yang baru saja diakui bisa tetap belum tertulis ke disk
- Crash OS pada satu node saja dapat memicu kehilangan data dan ketidaksesuaian replika
- Jepsen merekomendasikan agar NATS mengubah default ke
fsync=always atau mendokumentasikan risiko kehilangan data secara eksplisit
1. Latar belakang
- NATS adalah sistem streaming populer untuk memublikasikan dan berlangganan pesan sebagai stream
- JetStream menggunakan algoritma konsensus Raft untuk mereplikasi data dan menjamin pengiriman minimal satu kali (at-least-once)
- Dalam dokumentasi, JetStream mengklaim konsistensi linearizable dan selalu tersedia, tetapi menurut teorema CAP kedua kondisi itu tidak dapat dipenuhi secara bersamaan
- Menurut dokumentasi NATS, stream 3 node dapat menoleransi hilangnya 1 server, dan stream 5 node dapat menoleransi hilangnya 2 server
- Pesan dianggap “berhasil disimpan” pada saat server mengakui permintaan
publish
- Untuk konsistensi data dibutuhkan mayoritas (quorum) node; pada klaster 5 node, minimal 3 harus berjalan agar pesan baru bisa disimpan
2. Desain pengujian
- Jepsen melakukan pengujian dengan klien JNATS 2.24.0 dan lingkungan kontainer Debian 12 LXC
- Sebagian pengujian menggunakan image Docker resmi NATS di lingkungan Antithesis
- Satu stream JetStream tunggal dikonfigurasi (replikasi 5), lalu disuntikkan gangguan seperti penghentian proses, crash, partisi jaringan, packet loss, dan kerusakan file
- Menggunakan filesystem LazyFS untuk mensimulasikan kegagalan daya yang menyebabkan hilangnya write yang belum di-
fsync
- Setiap proses memublikasikan pesan unik, lalu setelah pengujian selesai diverifikasi di semua node apakah pesan yang sudah diakui benar-benar ada
- Jika pesan hanya ada pada sebagian node, kasus itu diklasifikasikan sebagai divergence (ketidaksesuaian replikasi)
3. Hasil utama
3.1 Kehilangan seluruh data pada NATS 2.10.22 (#6888)
- Ditemukan fenomena seluruh stream JetStream hilang hanya karena crash proses sederhana
- Setelah muncul error
"No matching streams for subject", pemulihan tidak terjadi selama berjam-jam
- Penyebabnya meliputi pembalikan snapshot leader, penghapusan status Raft, dan lain-lain, lalu diperbaiki pada versi 2.10.23
3.2 Kehilangan data saat file .blk rusak (#7549)
- Jika file
.blk JetStream mengalami error satu bit atau pemotongan (truncation), dapat terjadi kehilangan ratusan ribu write yang sudah diakui
- Contoh: dari 1.367.069 kasus, 679.153 hilang
- Bahkan jika hanya sebagian node yang rusak, dapat terjadi kehilangan data skala besar dan split-brain
- Contoh: pada node
n1, n3, n5, kehilangan pesan mencapai 78%
- NATS sedang menyelidiki masalah tersebut
3.3 Penghapusan seluruh data saat file snapshot rusak (#7556)
- Jika file snapshot dalam
data/jetstream/$SYS/_js_/ rusak, node menilai stream sebagai orphaned lalu menghapus seluruh data
- Meski hanya sedikit node yang rusak, hal itu dapat membuat mayoritas klaster tidak tercapai dan stream tidak tersedia secara permanen
- Contoh: node
n3, n5 rusak → n3 terpilih sebagai leader lalu menghapus seluruh jepsen-stream
- Jepsen menyoroti risiko node yang rusak menjadi leader saat pemilihan leader
3.4 Kehilangan data karena konfigurasi default fsync (#7564)
- Secara default JetStream hanya menjalankan
fsync setiap 2 menit, sementara pesan langsung diakui
- Akibatnya, pesan yang baru saja diakui bisa masih belum tertulis ke disk
- Saat terjadi kegagalan daya atau crash kernel, pesan yang sudah diakui selama puluhan detik bisa hilang
- Contoh: dari 930.005 kasus, 131.418 hilang
- Bahkan kegagalan pada satu node yang terjadi berurutan dapat menyebabkan seluruh stream terhapus
- Perilaku ini nyaris tidak disebutkan dalam dokumentasi
- Jepsen merekomendasikan mengubah default ke
fsync=always atau menambahkan peringatan eksplisit tentang risiko kehilangan data
3.5 Split-brain akibat satu crash OS (#7567)
- Hanya dengan kegagalan daya atau crash kernel pada satu node saja, tetap dapat terjadi kehilangan data dan ketidaksesuaian replikasi
- Dalam struktur leader-follower, jika sebagian node sudah mengakui write yang baru ter-commit di memori lalu terjadi gangguan,
mayoritas node dapat kehilangan write tersebut dan melanjutkan dengan status baru
- Dalam pengujian, satu kegagalan daya memicu split-brain yang persisten
- Terlihat bahwa tiap node kehilangan rentang pesan yang sudah diakui namun berbeda-beda
- Jepsen mengutip kasus serupa pada Kafka dan menekankan bahwa risiko yang sama juga ada pada sistem berbasis Raft
4. Diskusi dan kesimpulan
- Masalah kehilangan seluruh data pada 2.10.22 telah diselesaikan di 2.10.23
- Pada 2.12.1, kehilangan data dan split-brain akibat kerusakan file dan crash OS masih tetap terjadi
- Saat file
.blk dan snapshot rusak, dapat terjadi pesan hilang pada sebagian node atau penghapusan seluruh stream
- Karena interval default
fsync panjang, ada risiko kehilangan data yang sudah diakui saat beberapa node gagal bersamaan
- Jepsen mengusulkan penggunaan
fsync=always atau pemberitahuan risiko yang jelas dalam dokumentasi
- Klaim JetStream sebagai sistem yang “selalu tersedia” mustahil menurut teorema CAP, sehingga dokumentasi perlu diperbaiki
- Jepsen menegaskan bahwa keberadaan bug bisa dibuktikan, tetapi ketiadaan masalah keamanan tidak bisa dibuktikan
4.1 Peran LazyFS
- LazyFS digunakan untuk mensimulasikan hilangnya write yang belum di-
fsync
- Saat kegagalan daya, berbagai error storage seperti kerusakan write parsial (torn write) juga dapat direproduksi
- Dalam riset terkait When Amnesia Strikes (VLDB 2024), bug serupa juga dilaporkan pada PostgreSQL, Redis, ZooKeeper, dan lainnya
4.2 Tugas ke depan
- Verifikasi kehilangan pesan pada level konsumer tunggal, urutan pesan, serta jaminan Linearizable/Serializable belum dilakukan
- Jaminan pengiriman tepat satu kali (exactly-once) juga menjadi topik riset berikutnya
- Saat menambah atau menghapus node, ditemukan kesalahan dokumentasi dan langkah health check wajib yang hilang (#7545)
- Prosedur aman untuk perubahan konfigurasi klaster masih belum jelas
Belum ada komentar.