- rqlite adalah database relasional terdistribusi open source yang ringan, ditulis dalam Go, dan dikembangkan berdasarkan SQLite dan Raft
- Pengembangannya dimulai sejak 2014, dengan memprioritaskan keandalan dan kualitas, dan bahkan setelah lebih dari 10 tahun pengembangan serta deployment, hanya kurang dari 10 kasus panic yang dilaporkan di lingkungan produksi
- Pengujian sistem terdistribusi memerlukan pertimbangan cermat di berbagai lapisan, dan mengikuti filosofi menjaga kualitas di dalam kesederhanaan
Piramida pengujian: pendekatan yang efektif
- Pengujian rqlite mengikuti "piramida pengujian"
- Piramida pengujian: struktur yang berlandaskan unit test, mencakup integration test dan end-to-end test (E2E) seminimal mungkin
- Memberikan test suite yang efisien, mudah di-debug, dan berorientasi pada tujuan
Unit test: inti kualitas
- Unit test menguji komponen secara independen, serta memberikan keseimbangan antara kecepatan dan akurasi
- Berdasarkan SQLite dan arsitektur "shared nothing", sebagian besar fungsi dapat dicakup dengan unit test
- Dari seluruh kode rqlite (sekitar 75.000 baris), unit test terdiri dari sekitar 27.000 baris
- Pengujian selesai dalam beberapa menit, sehingga pengujian yang sering selama pengembangan dimungkinkan
Pengujian tingkat sistem: verifikasi konsensus
- Pengujian tingkat sistem memverifikasi interaksi antara modul konsensus Raft dan SQLite
- Item pengujian utama:
- Replikasi pernyataan SQLite antar node
- Operasi baca pada berbagai tingkat konsistensi
- Verifikasi pemulihan kegagalan cluster dan pemilihan leader
- Dengan sekitar 7000 baris kode uji, interaksi dalam konfigurasi single-node dan multi-node dicakup secara menyeluruh
End-to-end test: lapisan seminimal mungkin
- End-to-end test berperan sebagai smoke test untuk memeriksa startup sistem, clustering, dan perilaku dasar
- Ditulis dalam Python dan memverifikasi fungsi utama dengan menjalankan cluster rqlite yang sebenarnya
- Contoh: verifikasi backup ke AWS S3
- Dengan sekitar 5000 baris kode uji, pendekatan yang terbatas digunakan untuk meminimalkan biaya debugging
Pengujian performa: menguji batas
- Pengujian performa mengevaluasi metrik berikut:
- Kecepatan INSERT maksimum
- Penanganan query secara bersamaan
- Perbandingan penggunaan memori, CPU, dan disk
- Mencakup pengujian database SQLite berukuran lebih dari 2GB untuk menganalisis manajemen memori dan bottleneck penulisan disk
- Menemukan masalah performa dan memastikan stabilitas melalui optimisasi
Pelajaran yang didapat
- Mulai menguji sejak awal
- Unit test adalah cara paling efektif untuk membangun kepercayaan terhadap sistem
- Penulisan unit test tidak boleh ditunda selama pengembangan, karena bug bisa ditemukan lebih cepat dibanding integration test atau E2E test
- Jaga kode pengujian tetap sederhana
- Test suite bukan tempat untuk memaksakan refactoring yang kompleks atau prinsip DRY (Don't Repeat Yourself)
- Penting untuk menulis kode yang mudah dipahami, dan tambahan kode boilerplate pun harus diterima
- Verifikasi pengujian
- Saat menulis test, untuk sementara atur hasil yang diharapkan menjadi kebalikannya lalu jalankan ulang test
- Test yang ditulis dengan benar harus gagal dalam kasus ini, sehingga kesalahan pada kode pengujian dapat dicegah lebih awal
- Jangan abaikan kegagalan pengujian
- Bahkan kegagalan test yang sulit dipahami atau jarang terjadi pun memberikan informasi penting tentang software
- Kasus kegagalan yang sulit di-debug sering kali bisa menjadi kesempatan untuk menemukan cacat fatal dalam kode
- Maksimalkan determinisme
- Bangun mekanisme yang memungkinkan proses otomatis dalam sistem dijalankan secara manual
- Contoh: fitur snapshot Raft biasanya berjalan semi-otomatis, tetapi dirancang agar dapat dipicu secara eksplisit selama pengujian
- Bersikaplah disengaja (Be Deliberate)
- Integration test atau E2E test tingkat lebih tinggi hanya ditambahkan ketika kebutuhannya telah terbukti dengan jelas
- Pengujian yang berlebihan dapat menurunkan kecepatan pengembangan dan debugging
- Terapkan dan ulangi
- Dalam pengujian performa, panggilan fsync diidentifikasi sebagai bottleneck utama, dan entri log Raft dikompresi sebelum ditulis ke disk untuk mengoptimalkan penggunaan disk
- Utamakan efisiensi
- Mempertahankan test suite yang dapat dijalankan dalam beberapa menit memungkinkan pengembangan iteratif yang cepat
- Ini adalah keunggulan penting untuk menjaga dan mengaktifkan proyek open source
Kualitas diutamakan
- Mematuhi piramida pengujian, dengan setiap lapisan pengujian dirancang agar memiliki tujuan yang jelas
- Seiring meningkatnya kompleksitas sistem terdistribusi, menjaga kesederhanaan pengujian menjadi kunci
- Tujuannya adalah membangun database yang andal dan mudah dioperasikan
1 komentar
Komentar Hacker News
Pengujian pertama adalah yang paling sulit, tetapi layak untuk ditambahkan. Setelah itu, tes berikutnya menjadi lebih mudah
Komitmen terhadap proyek ini mengesankan
Test pyramid masuk akal, tetapi sering kali tidak semua level tersedia sehingga perlu cepat diperbaiki
Sepertinya ada kesalahan copy-paste di FAQ
Menantikan laporan Jepsen
Juga menikmati format videonya
Iri dengan setup pengujian performanya
Pernah menggunakan rqlite, dan proyek ini menyampaikan kesederhanaannya dengan baik
Menanyakan pendapat tentang pengujian simulasi deterministik
Penasaran apakah rqlite digunakan di lingkungan produksi
rqlite adalah proyek yang orisinal dan brilian