- Wafris adalah perusahaan web application firewall open source yang menyediakan klien middleware Rails
- Klien v1 memerlukan penyimpanan data Redis lokal, tetapi v2 menggunakan SQLite
- Menjelaskan latar belakang keputusan migrasi dari Redis ke SQLite, pertimbangan performa, dan perubahan arsitektur
TL;DR
- SQLite punya hal yang dikerjakan dengan baik dan hal yang tidak
- Redis punya hal yang dikerjakan dengan baik dan hal yang tidak
- RDBMS tradisional (Postgres/MySQL) punya hal yang dikerjakan dengan baik dan hal yang tidak
- Penyimpanan data ini tidak bisa saling menggantikan secara langsung, dan memaksakannya akan menimbulkan masalah
- Artikel ini menjelaskan proses pengujian dan pengambilan keputusan saat merearsitektur klien v1 berbasis Redis menjadi klien v2 berbasis SQLite
Faktor yang memaksa perubahan
- Tujuan Wafris adalah memudahkan developer melindungi situs mereka
- Karena masalah deployment Redis, v1 tidak sepenuhnya mencapai tujuan ini
- Redis dipilih karena mereka bekerja di lingkungan seperti Heroku yang memudahkan penggunaan Redis, tetapi banyak pengguna mengalami masalah deployment Redis
- Memaksa pengguna memakai DB terpisah seperti Redis bukanlah pilihan yang berpihak pada pengguna
Apa itu "kecepatan"?
- Redis "lebih cepat" daripada RDBMS tradisional, tetapi tetap perlu mengelola koneksi, memori, proses, dan lainnya
- Di lingkungan cloud, latensi jaringan bisa menjadi masalah besar
- Karena aturan Wafris harus dievaluasi pada setiap permintaan HTTP masuk, latensi jaringan dapat memperlambat aplikasi
Asumsi monolitik (Monolith-ish)
- Ada aplikasi yang benar-benar terdistribusi, tetapi sebagian besar aplikasi Rails adalah "Majestic Monoliths"
- Aplikasi yang dideploy di banyak region, dipecah menjadi server dengan fungsi tumpang tindih, atau hanya sebagian memakai Rails akan menghadapi lebih banyak masalah saat menggunakan Redis
Meninjau ulang arsitektur
- Wafris adalah web application firewall yang diinstal sebagai middleware Rails
- Jika disederhanakan menjadi dua tahap: 1) mencocokkan permintaan HTTP dengan aturan, dan 2) melaporkan hasil pemrosesan
- Operasi "baca" aturan (tahap 1) jauh lebih penting daripada "tulis" (tahap 2)
- Pembacaan harus diproses secara berurutan, tidak boleh gagal, dan memengaruhi performa yang dirasakan pengguna
- Penulisan bisa dibuat lebih lambat, dibatch, atau dijalankan secara asinkron
Saatnya SQLite
- Orang lain sudah menjelaskan dengan baik untuk penggunaan seperti apa SQLite cocok
- SQLite tidak bersaing dengan DB client/server, melainkan dengan
fopen()
- Dengan menghilangkan network round-trip, diperkirakan SQLite akan jauh lebih cepat daripada Redis
- Mereka memutuskan untuk mengevaluasi benchmark SQLite dan Redis
Benchmark SQLite dan Redis
- Benchmarking adalah seni gelap untuk menipu diri sendiri dengan angka yang tampak presisi
- Benchmarking penyimpanan data bahkan lebih rumit
- Mereka tidak mencari kecepatan absolut, melainkan membuat benchmark yang spesifik untuk data dan use case mereka
- Tweaking optimasi diabaikan. Mereka ingin Wafris langsung bekerja saat dimasukkan ke aplikasi
- Mereka menguji jalur utama aplikasi dan query terburuk, bukan benchmark teoretis
- Query terburuk adalah permintaan terhadap struktur data "lexical decimal" yang kompleks untuk memetakan rentang IP (IPv4, IPv6) ke kategori
- Lookup rentang dipra-hitung lalu ditulis ke tabel SQLite dan sorted set Redis
- Pada setiap permintaan HTTP masuk, IP permintaan harus dibandingkan dengan rentang kustom allow/block, rentang GeoIP, dan rentang reputasi IP
Protokol pengujian
- Pengujian dilakukan pada MacBook Air M2 dengan Redis yang diinstal via Homebrew dan DB SQLite lokal
- Pengujian dilakukan terhadap set data rentang yang ada (1,2 juta entri)
- Beberapa set IP dijalankan ke SQLite dan Redis dalam urutan yang sama
- Untuk setiap kelipatan, pengujian dijalankan 5 kali lalu dirata-ratakan
Hasil pengujian
- SQLite mengalahkan Redis secara telak (dalam use case khusus mereka)
- SQLite sekitar 3 kali lebih cepat daripada instance Redis lokal
- Ini adalah hasil sebelum mempertimbangkan latensi jaringan
- Bahkan jika SQLite hanya setara dengan Redis, menghilangkan waktu jaringan saja sudah memberi keuntungan
Yang tidak terlihat di grafik
- Bahkan jika performa SQLite 2 kali lebih buruk dalam benchmark, di dunia nyata bisa tetap lebih cepat karena latensi jaringan
- Sehebat apa pun server Redis, tetap ada batas bandwidth jaringan, koneksi, dan latensi antarwilayah
- SQLite memungkinkan skalabilitas horizontal yang nyaris tak terbatas "secara gratis"
- Onboarding menjadi jauh lebih baik dengan SQLite. Pengguna bahkan mungkin tidak sadar itu digunakan
- Performa Redis masih bisa diperas lebih jauh, tetapi sulit meyakinkan pengguna untuk mengubah konfigurasi Redis mereka
Hasil ini baru permulaan
- Meskipun terbukti SQLite lebih cepat daripada Redis, tetap ada trade-off nyata
- Pengujian di atas tidak mempertimbangkan penulisan
- Untuk mengelola persaingan antara baca dan tulis, diperlukan hal seperti koneksi ke DB, connection pool, transaksi, dan lainnya
- Seperti supercar listrik yang kesulitan membawa balok beton, SQLite tidak boleh digunakan untuk peran yang tidak cocok baginya
Membangun arsitektur sinkronisasi
- Di v1 (Redis), ketika pengguna memperbarui aturan di Wafris Hub, aturan di penyimpanan data Redis juga ikut diperbarui
- Dengan SQLite, cara ini tidak bisa digunakan karena tidak bisa melakukan "push" ke web server
- Di v2 (SQLite): 1) pengguna memperbarui aturan di Wafris Hub 2) klien memeriksa pembaruan aturan secara berkala 3) jika aturan diperbarui, klien mengunduh DB SQLite yang benar-benar baru
- Ini secara signifikan mengurangi tanggung jawab instalasi dan konfigurasi di sisi pengguna
- Tingkat keberhasilan instalasi klien v2 meningkat 3 kali lipat
Arsitektur terdistribusi SQLite
- Bayangkan aplikasi Rails yang dideploy di penyedia cloud dengan autoscaling aktif
- Jika permintaan naik dari 100req/s menjadi 10.000req/s, instance komputasi akan bertambah, tetapi DB tidak
- Ini sebenarnya alasan utama aplikasi Rails berhenti karena overload
- Dengan menyinkronkan DB SQLite ke tiap instance komputasi, masalah ini teratasi karena semua pemanggilan tetap lokal
Bagaimana dengan penulisan?
- Mereka membagi aplikasi menjadi jalur baca (evaluasi aturan) dan jalur tulis (pelaporan), lalu mengabaikan jalur tulis terlebih dahulu
- Jalur tulis kemudian didesain ulang menjadi 1) terhubung ke Wafris Hub secara asinkron untuk pelaporan 2) mengirim laporan secara batch 3) menghapus sepenuhnya penulisan DB dari klien
- Ini mungkin tidak cocok untuk semua orang, tetapi yang mereka pedulikan adalah pengguna yang menginginkan klien Wafris yang cepat dan mudah dideploy
Kesimpulan
- Mereka sangat puas dengan arsitektur v2 yang menggunakan SQLite
- Ini sudah membantu banyak situs bertahan dari serangan dan tetap online
- Memulai jadi jauh lebih mudah, sehingga mengurangi beban dukungan mereka dan kerepotan pengguna
- Ini dianggap sebagai kemenangan bagi internet yang lebih aman dan lebih terlindungi
7 komentar
SQLite memang cukup bagus, tetapi dalam kasus ini rasanya memang ini bukan use case yang cocok untuk Redis... begitu sih menurut saya.
Agak gimana gitu kalau benchmark-nya dilakukan di M2..
Jadi, apakah harus diukur satu per satu untuk setiap instance AWS? Ekspektasi Anda terhadap open source terlalu besar.
Apakah ini jadi masalah kalau pengujiannya dilakukan di lingkungan server yang sama?
Apakah benchmark memang harus memakai CPU tertentu...?
Bagian apa dari yang dilakukan di M2 yang bisa menjadi masalah? (Selain fakta bahwa lingkungan layanan sebenarnya bukan prosesor M2)
Itulah masalahnya. Bereksperimen di laboratorium, lalu mengklaim, ini sempurna untuk penggunaan komersial!