Caching data sebaiknya dipertimbangkan untuk data yang sering dibaca tetapi jarang ditulis, terutama pada tabel yang sering diakses dalam 5 query teratas RDB, dengan jumlah query update yang sedikit.
Data yang sensitif terhadap perubahan membutuhkan perhatian khusus saat menerapkan caching, dan caching lokal memang menawarkan kecepatan yang lebih tinggi, tetapi perlu diperhatikan manajemen instansnya.
Saya telah menerapkan caching lokal untuk data terkait pembayaran dengan pengaturan TTL 5 detik untuk meningkatkan performa, dan akan melakukan pengujian performa lebih lanjut untuk memvalidasi efektivitasnya.
Halo? Saya Jayon.
Hari ini, saya ingin menjelaskan kriteria pengaturan cache. Posting ini saya tulis berdasarkan pengalaman saya dalam pekerjaan, jadi harap anggap saja sebagai referensi ya ㅎㅎ
Apa itu Cache?
Cache adalah menyimpan hasil yang akan diminta nanti terlebih dahulu, lalu memberikan layanan dengan cepat. Dengan kata lain, menyimpan hasil terlebih dahulu dan ketika ada permintaan nanti, alih-alih merujuk ke DB atau API, permintaan tersebut diproses dengan mengakses cache. Latar belakang munculnya cache ini adalah Hukum Pareto.
Hukum Pareto menyatakan bahwa 80% hasil disebabkan oleh 20% penyebab. Silakan lihat gambar di bawah ini untuk referensi!
Artinya, cache tidak perlu menyimpan semua hasil, tetapi hanya 20% yang paling sering digunakan saat memberikan layanan, sehingga dapat meningkatkan efisiensi secara keseluruhan.
Data apa yang harus di-cache?
Sesuai dengan Hukum Pareto, kita tidak boleh sembarangan dalam melakukan caching data, dan hanya data yang benar-benar dibutuhkan saja yang harus di-cache. Lalu, data seperti apa yang harus di-cache?
Data yang sering dibaca tetapi jarang ditulis
Secara teoritis, banyak yang mengatakan bahwa “data yang sering dibaca tetapi jarang ditulis harus di-cache”, tetapi kriteria “sering dibaca” dan “jarang ditulis” cukup samar.
Maka dari itu, saya menyelidiki data yang akan di-cache dengan langkah-langkah berikut.
Memeriksa 5 besar riwayat pemanggilan query RDB melalui APM seperti Data Dog.
Dari situ, cari query yang bersifat select dan periksa dari tabel mana query tersebut mengambil data.
Periksa berapa kali query update untuk tabel tersebut dipanggil.
Melalui proses di atas, kita bisa melihat apakah query select banyak dipanggil tetapi query update jarang dipanggil. Dalam tabel yang saya periksa di pekerjaan saya, query select dipanggil 1,74 juta kali dalam sehari, sedangkan query update paling banyak dipanggil 500 kali. Kalau ini, siapapun bisa bilang kalau ini cocok untuk di-cache ya ㅎㅎ
Data yang sensitif terhadap pembaruan
Data yang sensitif terhadap pembaruan berarti perbedaan waktu antara RDB dan cache harus sesingkat mungkin. Misalnya, informasi terkait pembayaran sangat sensitif terhadap pembaruan, sehingga meskipun memenuhi syarat cache di atas, penerapannya perlu dipertimbangkan.
Saya harus melakukan caching pada tabel terkait pembayaran yang memenuhi kedua karakteristik di atas. Oleh karena itu, saya tidak menerapkan cache pada semua logika yang menggunakan tabel terkait pembayaran tersebut, dan memutuskan untuk menerapkan caching secara parsial pada logika yang relatif aman di mana pembayaran tidak benar-benar terjadi.
Local Caching vs Global Caching
Sekarang, kita sudah menentukan data apa yang akan di-cache dan ruang lingkup caching-nya. Lalu, kita harus memikirkan “di mana” data cache tersebut akan disimpan. Umumnya, data cache dapat disimpan di memori lokal atau di server terpisah seperti Redis.
Local Caching
Local caching adalah cara menyimpan data cache di memori server aplikasi, dan umumnya Guava cache atau Caffeine cache banyak digunakan.
Kelebihan
Karena cache diambil dari memori dalam server yang sama saat menjalankan logika aplikasi, kecepatannya cepat.
Mudah diimplementasikan.
Kekurangan
Jika ada banyak instance, akan muncul beberapa masalah.
Global Caching
Global caching adalah metode yang menggunakan server terpisah untuk menyimpan data cache, seperti Redis.
Kelebihan
Karena cache dibagikan antar instance, jika cache diubah di satu instance, semua instance dapat memperoleh nilai cache yang sama.
Saat instance baru muncul, instance tersebut dapat melihat penyimpanan cache yang sudah ada, sehingga tidak perlu memasukkan cache lagi.
Kekurangan
Karena harus melalui lalu lintas jaringan, kecepatannya lebih lambat dibandingkan local caching.
Karena harus menggunakan server cache terpisah, biaya pengelolaan infrastruktur akan muncul.
Mana yang saya pilih?
Saat ini, server aplikasi perusahaan saya menggunakan struktur dengan banyak instance, tetapi saya memilih local cache.
Ada 3 alasan utama.
Data yang akan di-cache yang disimpan di RDB berjumlah sekitar 40.000, dan jika semuanya dimasukkan ke memori, ukurannya kurang dari 4MB.
Performa pencarian data terkait pembayaran harus baik.
Redis memang sudah ada, tetapi menyimpan cache baru di Redis akan menimbulkan biaya infrastruktur.
Bagaimana cara memperbarui cache?
Jika ada beberapa server aplikasi dan local caching diterapkan di sana, nilai cache yang disimpan di setiap server aplikasi bisa berbeda. Misalnya, nilai data cache yang disimpan di server A adalah “1”, tetapi nilai data cache di server B berubah menjadi “2” karena server B telah melakukan perubahan. Dalam kondisi ini, jika pengguna mengirimkan permintaan ke load balancer, pengguna akan menerima nilai yang berbeda dari server A dan server B.
Oleh karena itu, cache di setiap instance harus dihapus secara otomatis agar data dapat diambil dari RDB, dan TTL biasanya digunakan untuk itu.
Berapa lama TTL yang harus diatur?
TTL adalah singkatan dari Time To Live, yang merupakan pengaturan untuk menghapus cache setelah jangka waktu tertentu. Misalnya, jika TTL diatur menjadi 5 detik, data cache akan dihapus secara otomatis setelah 5 detik. Setelah itu, jika terjadi cache miss, data akan diambil dari RDB dan disimpan.
Lalu, berapa lama TTL yang harus diatur?
Read/write terjadi di satu server cache
Jika read/write terjadi di satu server cache seperti Redis atau di satu server aplikasi yang menerapkan local caching, nilai TTL dapat dinaikkan hingga satuan jam atau lebih. Toh, saat write, cache yang sudah ada akan diubah, dan server yang mengambil data dari cache tersebut selalu akan melihat data terbaru.
Dalam kasus ini, TTL dapat dihilangkan dan server cache dapat dikonfigurasi untuk secara otomatis menghapus sebagian cache sedikit demi sedikit menggunakan algoritma LRU saat server cache penuh.
Read/write terjadi di beberapa server cache
Jika read/write terjadi di beberapa server cache seperti server global cache atau beberapa server aplikasi yang menerapkan local caching, sebaiknya nilai TTL dibuat dalam hitungan detik hingga menit. Hal ini karena ada kemungkinan membaca data lama dari server cache yang belum merefleksikan data yang telah diubah.
Nilai TTL dalam hal ini ditentukan dalam berbagai konteks, semakin penting pembaruan dan semakin besar kemungkinan nilai berubah, TTL harus dibuat lebih pendek. Sebaliknya, semakin tidak penting pembaruan dan semakin kecil kemungkinan nilai berubah, TTL dapat dibuat lebih lama.
Bagaimana saya mengatur TTL?
Data yang akan saya cache adalah data terkait pembayaran, dan meskipun caching tidak diterapkan pada logika yang benar-benar melakukan pembayaran, pembaruan tetap penting karena sifat pembayaran. Namun, kemungkinan pembaruan rendah, jadi saya menetapkan TTL sekitar 5 detik untuk berjaga-jaga.
Kesimpulan
Secara ringkas, metode caching yang saya pilih adalah sebagai berikut.
Data terkait pembayaran
Sering dibaca, tetapi jarang diubah.
Caching diterapkan pada logika yang tidak benar-benar melakukan pembayaran, tetapi masih ada pencarian.
Local caching diterapkan dan TTL diatur menjadi 5 detik.
Ke depannya, saya akan melakukan pengujian performa pada metode caching yang telah diterapkan. Saya masih mempertimbangkan bagaimana cara melakukan pengujian performa secara spesifik, jadi saya akan menuliskannya di postingan selanjutnya!