Cache dapat mengurangi trafik backend pada kondisi stabil, tetapi justru memperbesar kerja saat sebuah entry populer kedaluwarsa. Jika seratus request melihat key yang sama dalam keadaan kosong sebelum nilai pengganti tersimpan, jalur lookup biasa dapat mengirim seratus read yang setara ke origin. Cache tetap bekerja sesuai aturan lookup-nya; amplifikasi muncul dari concurrency selama interval kosong tersebut.
Request coalescing mengubah interval itu. Caller pertama untuk sebuah key memulai fill, sedangkan caller berikutnya dengan key yang sama bergabung ke operasi yang sedang berjalan alih-alih memulai kerja setara. Setelah operasi selesai, hasilnya dibagikan kepada caller yang menunggu dan, bila sesuai, disimpan ke cache.
Mekanisme ini mengendalikan kerja duplikat. Ia tidak memperpanjang masa berlaku data cache, tidak menentukan freshness, dan tidak membuat request origin yang gagal menjadi berhasil.
Coordination key menentukan batas berbagi
Coalescing memerlukan key yang mengidentifikasi operasi yang aman untuk dibagikan. Pada object cache sederhana, key tersebut dapat sama dengan cache key. Pada HTTP response cache, key mungkin perlu mencakup dimensi representasi seperti locale, encoding, authorization scope, atau request header tertentu.
Dua request hanya boleh berbagi fill yang sedang berjalan jika satu hasil komputasi valid untuk keduanya. Coordination key yang lebih luas daripada identitas data dapat memberikan hasil untuk varian yang keliru. Key yang terlalu sempit tetap menjaga correctness, tetapi mengurangi peluang deduplikasi.
Karena itu, request coalescing merupakan persoalan identitas data sekaligus concurrency. Aturan canonicalization yang dipakai untuk identitas cache sering menjadi titik awal yang tepat, tetapi relasi kesetaraannya harus sesuai dengan operasi yang benar-benar dibagikan.
In-flight entry berumur lebih pendek daripada nilai cache
Coalescer biasanya menyimpan map dari coordination key ke in-flight record. Record tersebut dapat memuat completion signal beserta result atau error. Masa hidupnya dimulai ketika caller pertama mengambil kepemilikan key dan berakhir setelah operasi bersama selesai serta waiter dapat mengamati hasilnya.
Secara konseptual, critical section-nya kecil:
lock inflight map
if key exists:
join existing operation
else:
create operation for key
mark current caller as owner
unlock inflight mapBackend call yang mahal tidak boleh berjalan saat global map lock masih dipegang. Jika itu terjadi, key yang tidak saling terkait ikut terserialisasi di belakang satu fill yang lambat. Koordinasi hanya melindungi kepemilikan in-flight record; eksekusi backend berlangsung di luar lock tersebut.
Setelah selesai, owner memublikasikan outcome, membangunkan waiter, lalu menghapus in-flight entry. Penghapusan harus diurutkan agar caller baru tidak bergabung ke operasi yang hasilnya sudah tidak dapat dipublikasikan. Implementasi konkret dapat memakai mutex, future, promise, channel, atau primitive single-flight yang disediakan library.
Coalescing dan caching menangani transisi state yang berbeda
Cache menjawab apakah nilai yang sudah dihasilkan masih dapat dipakai kembali. Coalescer menjawab apakah komputasi yang sedang berlangsung dapat dibagikan. Keduanya merupakan state machine yang berbeda.
Sebuah request dapat menghadapi beberapa kombinasi:
| State cache | State in-flight | Tindakan umum |
|---|---|---|
| nilai fresh | tidak ada | kembalikan nilai cache |
| kosong atau kedaluwarsa | tidak ada | mulai satu fill |
| kosong atau kedaluwarsa | fill aktif | bergabung ke fill |
| nilai stale diizinkan | refresh aktif | kembalikan nilai stale saat refresh berlanjut |
Baris terakhir memakai kebijakan yang berbeda dari blocking coalescing. Desain stale-while-revalidate dapat membuat caller tetap memakai nilai lama yang masih dapat diterima saat satu aktor melakukan refresh. Miss coalescing murni membuat caller menunggu ketika tidak ada nilai yang dapat dipakai kembali. Keduanya dapat menekan kerja origin duplikat, tetapi perilaku latency dan freshness-nya berbeda.
Kegagalan ikut dibagikan kecuali kontraknya menentukan hal lain
Jika satu-satunya fill gagal, setiap caller yang terhubung dapat menerima kegagalan yang sama. Coalescing dengan demikian mengubah korelasi kegagalan: banyak caller tidak lagi menjalankan percobaan origin independen dalam overlap window yang sama.
Sifat ini berguna ketika retry langsung hanya akan menggandakan tekanan, tetapi tetap perlu ditangani secara eksplisit. Coalescer bukan retry policy. Jika caller otomatis mengulang shared error tanpa backoff atau aturan admission lain, burst baru dapat muncul segera setelah in-flight entry yang gagal menghilang.
Negative caching juga merupakan mekanisme terpisah. Menyimpan hasil not-found atau error selama interval tertentu mengubah perilaku cache untuk request berikutnya. Coalescing sendiri hanya mempertahankan outcome cukup lama untuk mengirimkannya kepada caller yang sudah terhubung ke operasi tersebut.
Cancellation memunculkan persoalan kepemilikan
Shared work membuat cancellation lebih rumit. Jika caller pertama terputus, membatalkan operasi backend secara langsung juga dapat menggagalkan caller yang bergabung kemudian dan masih memerlukan hasilnya. Menjadikan context milik caller pertama sebagai pemilik permanen operasi bersama akan mengikat lifetime request yang sebenarnya tidak saling bergantung.
Salah satu desain memberi in-flight operation context independen dan melacak minat waiter. Desain lain mempertahankan fill setelah dimulai, dengan deadline miliknya sendiri. Implementasi yang lebih kompleks dapat membatalkan kerja backend hanya setelah seluruh waiter pergi.
Tidak ada satu aturan cancellation yang cocok untuk semua sistem. Kontrak yang tepat bergantung pada biaya melanjutkan fill, dukungan cancellation pada backend, serta apakah nilai yang selesai tetap berguna bagi cache setelah request pemicu menghilang. Hal yang penting adalah semantik cancellation menjadi milik shared operation, bukan tanpa sengaja menjadi milik caller yang kebetulan datang pertama.
Koordinasi per key membatasi dampak silang
Satu global lock untuk seluruh cache miss memang dapat mencegah fill duplikat, tetapi juga mengikat key yang tidak saling terkait. Fill lambat untuk satu key dapat menunda miss pada key lain meski backend mampu memproses keduanya secara independen.
In-flight record per key menghindari serialisasi tersebut. Struktur global hanya disentuh sebentar untuk mencari atau memasang record, sedangkan setiap key memiliki completion state sendiri. Scope koordinasi tetap sejajar dengan unit kerja yang berpotensi terduplikasi.
Jumlah in-flight record tetap memerlukan batas resource pada sistem yang menerima key berkardinalitas tinggi atau dikendalikan pihak luar. Melakukan coalescing terhadap satu juta miss dengan key berbeda hampir tidak memberi deduplikasi dan justru dapat menghabiskan memori dalam jumlah besar. Admission control, validasi key, concurrency limit, atau metadata terbatas dapat diperlukan di sekitar coalescer.
Metrik yang relevan adalah duplikasi konkuren
Cache hit ratio saja tidak menunjukkan efektivitas coalescing. Sistem dapat memiliki hit ratio tinggi tetapi tetap menghasilkan lonjakan backend tajam ketika beberapa entry populer kedaluwarsa pada waktu berdekatan.
Observasi yang berguna mencakup jumlah fill yang dimulai, jumlah caller yang bergabung ke fill aktif, jumlah waiter per key, durasi fill, shared failure, dan concurrency backend selama peristiwa expiry. Data tersebut memisahkan cache miss biasa dari miss yang tanpa coalescing akan berubah menjadi kerja duplikat.
Perbedaan ini juga relevan saat mengatur timeout. Fill yang lama dengan banyak waiter dapat menandakan origin lambat, bukan kerusakan cache. Coalescing mencegah waiter tersebut menggandakan backend request, tetapi tidak dapat mengurangi latency dari satu operasi yang menjadi dependensi mereka bersama.
Penekanan duplikasi dibatasi oleh overlap
Request coalescing hanya menggabungkan kerja yang hadir pada waktu yang sama. Setelah in-flight record selesai dan dihapus, miss berikutnya akan memulai fill baru kecuali cache sudah berisi nilai yang dapat dipakai kembali. Mekanisme ini tidak menyediakan deduplikasi persisten di antara time window yang terpisah.
Batas tersebut menjaga abstraksinya tetap sempit. Cache policy menentukan apakah hasil yang selesai masih dapat dipakai kembali. Retry policy menentukan apakah kerja yang gagal perlu dicoba lagi. Admission control membatasi banyaknya kerja yang boleh masuk ke sistem. Request coalescing menangani satu kondisi concurrency yang spesifik: beberapa caller sedang meminta hasil kosong yang sama, dan satu eksekusi dapat memenuhi semuanya.