Hedged Request Memangkas Tail Latency dengan Biaya Kapasitas
Sebuah service dapat memiliki median latency yang baik sementara sebagian kecil request memerlukan waktu jauh lebih lama. Queueing, cache dingin, runtime pause, packet loss sementara, atau operasi storage yang lambat dapat membuat satu percobaan tertinggal jauh dari jalur normal. Pada fan-out yang cukup besar, delay yang jarang itu menjadi umum pada batas request agregat.
Hedged request memulai percobaan ekuivalen kedua setelah percobaan pertama belum selesai selama jeda yang ditentukan. Caller menerima hasil berguna pertama lalu membatalkan atau mengabaikan percobaan lainnya.
waktu --->
percobaan A: |---------------------- hasil
hedge: |------ hasil
^
jeda hedge
caller mengembalikan hasil hedgeIni adalah redundansi terkontrol, bukan retry biasa setelah failure. Percobaan awal mungkin tetap sehat; percobaan itu hanya terlambat dibanding target latency service.
Jeda mengendalikan tradeoff kerja dan latency
Mengirim dua percobaan sekaligus dapat mengurangi latency, tetapi juga menggandakan tekanan request untuk setiap operasi. Jeda hedge menghindari kerja duplikat bagi request yang selesai dalam rentang latency normal.
Policy yang umum mengambil jeda dari percentile latency terbaru untuk kelas operasi yang sama. Jika hedge dimulai saat sebuah percobaan sudah tergolong sangat lambat, hanya sebagian kecil call yang menghasilkan duplikat.
jika percobaan pertama selesai sebelum hedge_delay:
kembalikan hasil pertama
mulai percobaan kedua
kembalikan hasil valid pertama
batalkan percobaan yang tersisaJeda tetap juga dapat sesuai ketika service memiliki budget latency yang stabil. Nilainya tetap perlu diukur terhadap traffic terkini karena queueing dan perilaku dependency dapat berubah.
Metric yang relevan bukan hanya penurunan percentile tinggi. Sistem juga perlu mencatat hedge rate, operasi backend tambahan, efektivitas cancellation, serta latency percobaan yang menang dan kalah.
Percobaan duplikat memerlukan semantics yang ekuivalen
Kedua percobaan harus mewakili read atau operasi logis yang sama. Hedging relatif sederhana untuk read tanpa side effect karena salah satu hasil dapat memenuhi caller ketika keduanya berada pada consistency boundary yang diterima.
Mutation memerlukan perlakuan jauh lebih ketat. Mengirim dua write dapat menggandakan charge, reservation, message, atau state transition. Mutation hanya dapat di-hedge ketika protocol sudah memiliki operation identity yang aman dan boundary deduplikasi yang sesuai untuk percobaan concurrent.
Read pun belum tentu dapat dipertukarkan antar-replica. Jika satu percobaan membaca dari leader dan percobaan lain dari replica yang tertinggal, response pertama belum tentu memenuhi consistency contract yang diminta caller. Pemilihan replica karena itu merupakan bagian dari policy hedge, bukan keputusan routing acak.
Cancellation membatasi pemborosan tetapi tidak menghapusnya
Setelah satu percobaan menang, caller sebaiknya membatalkan percobaan yang kalah ketika transport dan server mendukung cancellation yang efektif. Signal tersebut dapat melepas connection slot, menghentikan downstream work, atau mencegah operasi dalam queue mulai berjalan.
Cancellation bukan rollback. Request yang kalah mungkin sudah memakai CPU, mengirim query database, mengisi cache entry, atau menyelesaikan pekerjaan sebelum cancellation tiba.
percobaan A -> service -> query database
percobaan B -> service -> query database
|
+-- menang
batalkan AOperasi database dari A mungkin tetap berjalan jika cancellation tidak diteruskan melewati boundary tersebut. Capacity accounting karena itu harus memakai kerja yang benar-benar teramati, bukan menganggap setiap percobaan yang dibatalkan menjadi gratis.
Request deadline tetap penting. Kedua percobaan harus berada di dalam budget caller asli; hedge tidak boleh membuat lifetime baru yang bertahan lebih lama dari operasi yang dilayaninya.
Slowness yang berkorelasi mengurangi manfaat
Hedging paling berguna ketika percobaan kedua dapat menghindari kondisi yang memperlambat percobaan pertama. Mengirim kedua percobaan melalui queue, process, shard, atau network path yang sama dapat menghasilkan delay yang sama.
Keragaman replica dapat meningkatkan independensi:
caller
|---- percobaan A ---> replica 1
|
+---- hedge ----------> replica 2Keragaman tidak otomatis menguntungkan. Replica kedua mungkin memiliki data yang lebih dingin, kapasitas lebih rendah, atau consistency property berbeda. Routing lintas zone dapat menambah biaya jaringan. Policy perlu menghormati placement, affinity, cache locality, dan data ownership.
Incident yang meluas juga membuat percobaan sangat berkorelasi. Saat setiap backend mengalami saturasi, hedge tambahan dapat menambah tekanan tanpa menyediakan jalur yang lebih cepat.
Proteksi overload harus menghitung hedge
Policy hedge yang mengabaikan saturasi dapat membentuk positive feedback loop. Latency naik saat load meningkat, lebih banyak request melewati threshold hedge, traffic duplikat bertambah, lalu traffic tambahan mendorong latency lebih tinggi.
Admission path harus menghitung hedge sebagai kerja nyata. Concurrency limit, load shedding, dan budget per client dapat membatasi percobaan duplikat ketika kapasitas cadangan menghilang.
Salah satu kontrol praktis adalah hedge budget: hanya fraksi terbatas dari traffic primer yang boleh membuat duplikat concurrent dalam satu measurement window. Kontrol lain adalah menonaktifkan atau menunda hedging ketika queue depth atau utilization backend melewati threshold.
Kontrol tersebut mempertahankan asumsi utama hedging: kapasitas cadangan ditukar dengan tail latency yang lebih rendah. Saat kapasitas cadangan tidak tersedia, pertukaran itu tidak lagi memiliki karakter ekonomi yang sama.
Kelas request memerlukan policy terpisah
Satu percentile untuk seluruh traffic dapat menghasilkan jeda hedge yang buruk. Cache read cepat, read object besar, dan analytical query mahal dapat memiliki distribusi latency serta biaya resource yang sangat berbeda.
Policy dapat dipisahkan berdasarkan endpoint, jenis operasi, kelas payload, tenant tier, atau dimensi workload stabil lainnya. Partisi sebaiknya cukup kasar agar measurement tetap berguna sambil memisahkan perilaku service yang benar-benar berbeda.
Hedging untuk kerja yang sangat mahal memerlukan batas lebih ketat karena satu duplikat dapat memakai kapasitas besar. Read murah dengan replica independen dapat memakai policy yang lebih agresif.
Metric harus memisahkan kerja primer dan duplikat
Latency agregat saja dapat menyembunyikan biaya teknik ini. Telemetry sebaiknya mengidentifikasi percobaan primer, percobaan hedge, pemenang, pihak yang kalah, cancellation, dan percobaan yang tetap berjalan setelah cancellation.
Rasio yang berguna meliputi:
hedge rate = logical request yang di-hedge / logical request
hedge win rate = hedge yang menang / percobaan hedge
extra work = kerja percobaan backend / kerja logical requestHedge rate tinggi dengan hedge win rate rendah sering menunjukkan jeda terlalu agresif atau jalur duplikat sangat berkorelasi. Win rate tinggi pun dapat tetap buruk jika traffic tambahan mendorong backend menuju saturasi.
Tracing sebaiknya memakai satu logical operation identifier yang sama untuk kedua percobaan serta attempt identifier berbeda untuk setiap cabang. Hubungan keduanya tetap terlihat tanpa menggabungkan dua eksekusi fisik menjadi satu span.
Pengurangan tail bergantung pada kapasitas cadangan yang independen
Hedged request dapat mengubah percobaan lambat sesekali menjadi logical response yang lebih cepat ketika jalur eksekusi lain memiliki peluang baik untuk selesai lebih dahulu. Mekanisme ini tidak membuat backend lambat menjadi lebih cepat dan tidak menghapus biaya resource dari kerja duplikat.
Policy paling kuat ketika percobaan dapat dipertukarkan secara semantik, jalur duplikat memiliki tingkat independensi tertentu, cancellation diteruskan cukup jauh untuk menghemat kerja, dan overload control dapat menekan hedge selama saturasi. Dalam kondisi tersebut, duplikat yang tertunda dapat memperketat tail latency tanpa menjadikan eksekusi duplikat sebagai jalur default.