Batasi data usang dan penggunaan memori
TTL, eviction, dan negative caching menentukan seberapa lama data lama boleh tampil dan berapa banyak memori yang dipakai.
Pertanyaan
Seberapa lama data lama boleh tampil, dan berapa memori yang dibutuhkan untuk menjaganya tetap segar?
Setelah baca ini, kamu bisa menetapkan TTL dari toleransi bisnis, memperkirakan memori cache, dan menjelaskan apa yang terjadi saat memori penuh.
Prasyarat dan contoh
Kamu sudah paham kebijakan penulisan dan race pengisian (M06.03) dan bisa menghitung ukuran data dengan satuan (M01.03).
Contoh: daftar harga untuk 2 juta SKU. Bisnis bilang, "perubahan harga harus tampil di bawah 60 detik, kecuali saat promo besar". Developer mengatur TTL 24 jam "karena datanya jarang berubah". Kalimat itu bertentangan dengan permintaan bisnis, tapi tidak ada yang menyadarinya sampai pelanggan memprotes harga lama.
Soal lain: cache dengan 6 GB tapi data yang diminta totalnya 20 GB. Entri terus tergusur sebelum dipakai lagi, dan hit ratio turun diam-diam.
Mekanisme
TTL dari toleransi. Tanyakan: berapa lama pembaca boleh melihat nilai lama tanpa kerugian? Itu batas atas TTL. Tulis sebagai kalimat: "harga boleh usang maksimal 60 detik". TTL yang tidak punya alasan bisnis hanyalah tebakan.
TTL juga menentukan beban sumber. Kalau 100.000 key aktif dengan TTL 60 detik, DB menerima paling banyak sekitar 1.667 pengisian per detik untuk menjaganya segar:
isiUlangPerDetik ≈ keyAktif / TTL = 100.000 / 60 ≈ 1.667
Menaikkan TTL ke 300 detik menurunkannya menjadi sekitar 333. Jadi ada tarik-menarik langsung antara kesegaran dan beban.
Perkiraan memori.
memori = jumlahEntri × (ukuranNilai + ukuranKey + overhead)
Overhead struktur data cache umumnya puluhan sampai ratusan byte per entri, tergantung implementasi, jadi ukur sendiri. Contoh: 2 juta entri × (1,2 KB nilai + 80 B key + 100 B overhead) ≈ 2,76 GB. Sisakan ruang untuk fragmentasi dan lonjakan: kapasitas yang kamu beli sebaiknya 1,3 sampai 1,5 kali perkiraan.
Eviction. Saat memori penuh, cache membuang entri. LRU membuang yang paling lama tidak dipakai, LFU yang paling jarang dipakai. LRU cocok untuk pola akses yang berpindah, LFU untuk beberapa key yang selalu populer. Tanpa eviction yang sesuai, cache menolak tulis atau, lebih buruk, menggusur entri panas karena satu pemindaian besar (scan) yang menyentuh jutaan key sekali.
Satu catatan: eviction bukan mekanisme kesegaran. Ia membuang berdasarkan tekanan memori, bukan berdasarkan umur kebenaran. Entri usang yang sering dibaca tidak akan pernah tergusur.
Negative caching. Menyimpan hasil "tidak ada" (404, baris kosong) dengan TTL pendek. Tanpa itu, request ke ID yang tidak ada menembus cache ke DB setiap kali. Dengan TTL 30 detik, 1.000 request per detik ke ID yang sama hanya jadi 1 query per 30 detik. Risiko: data yang baru dibuat tetap tampak "tidak ada" selama TTL. Pakai TTL lebih pendek dari TTL data positif, dan hapus entri negatif saat data dibuat.
Saat rancangan ini gagal
- TTL tanpa alasan. 24 jam di tempat yang butuh 60 detik, atau 5 detik di tempat yang bisa 15 menit sehingga DB menerima beban tambahan tanpa manfaat.
- Working set lebih besar dari memori. Eviction terus-menerus, hit ratio turun, dan CPU habis
untuk membuang dan mengisi ulang. Perhatikan metrik
evicted_keysyang naik terus. - Satu nilai besar menggusur banyak nilai kecil. Satu entri 5 MB setara 4.000 entri 1,2 KB. Batasi ukuran nilai yang boleh di-cache.
- Negative caching menyembunyikan data baru. Pengguna mendaftar, lalu profilnya "tidak ditemukan" selama 5 menit karena entri negatif lama.
- Cache penuh oleh key yang tidak pernah dipakai lagi. Kombinasi key tanpa batas (M06.02) memenuhi memori dengan entri satu kali pakai.
- TTL kedaluwarsa serentak. Semua key yang diisi bersamaan habis bersamaan. Masalah ini dibahas di M06.05.
Contoh tandingan: tim menaikkan memori cache dari 6 ke 12 GB untuk memperbaiki hit ratio. Hit ratio tidak berubah karena penyebab sebenarnya adalah TTL 20 detik pada data yang toleransi bisnisnya 10 menit. Memori bukan masalahnya.
Latihan
Katalog punya 1,5 juta entri aktif. Nilai rata-rata 2 KB, key 100 byte, overhead 120 byte per entri. Bisnis menoleransi data usang maksimal 2 menit. Sekitar 30% entri dibaca dalam 2 menit.
- Perkirakan memori yang dibutuhkan dan kapasitas yang dibeli.
- Pilih TTL dan hitung pengisian ulang per detik jika semua entri aktif harus tetap segar.
- Sebut satu risiko negative caching di sini.
Lihat pembahasan
Memori: 1.500.000 × (2.048 + 100 + 120) byte ≈ 3,4 GB. Dengan faktor 1,4 untuk fragmentasi dan lonjakan, beli sekitar 4,8 GB.
TTL: 120 detik, sama dengan toleransi. Hanya 30% entri yang dibaca per jendela, jadi key aktif sekitar 450.000, dan pengisian ulang sekitar 450.000 / 120 = 3.750 per detik di batas atas. Kalau DB tidak sanggup, itu sinyal untuk melonggarkan toleransi, bukan untuk memperbanyak cache.
Risiko negative caching: produk yang baru ditambahkan tetap tidak ditemukan selama TTL entri negatif. Pakai TTL negatif 15 detik dan hapus entri negatif saat produk dibuat.
Terkait
- Sebelumnya: M06.03 Pilih kebijakan penulisan.
- Lanjut ke M06.05 Tangani stampede dan hot key.
- M01.03 Hitung kebutuhan server untuk cara menulis perkiraan dengan satuan.
Catatan
- Asumsi: overhead per entri adalah perkiraan, dan akses terdistribusi tidak merata.
- Yang tidak dibahas: kompresi nilai, persistensi cache ke disk, dan klaster cache.
- Perbedaan LRU dan LFU di sini disederhanakan. Implementasi nyata sering memakai pendekatan aproksimasi.
- Terakhir ditinjau: 26 Oktober 2026.