Topik temu duga representatif

Bagaimanakah Anda Mencegah Cache Stampede Apabila Hot Key Tamat Tempoh?

BackendSukar
Pasukan Editorial Offer.ccDiterbitkan Dikemas kini

Soalan

Satu kunci konfigurasi produk yang hangat (hot key) menerima 50,000 bacaan sesaat. Pangkalan data sumber selamat sehingga 200 pertanyaan sesaat, dan membina semula cache mengambil masa 800 ms pada p95. Data yang dicache adalah segar (fresh) selama 10 minit, dan perniagaan bertolak ansur dengan paling banyak 30 saat kelapukan (staleness). Reka laluan bacaan dan penyegaran merentas 100 tika (instance) aplikasi stateless tanpa membebankan sumber asal secara berlebihan apabila kunci tamat tempoh.

Gesaan dan skop

Satu kunci konfigurasi produk yang hangat (hot key) menerima 50,000 bacaan sesaat. Pangkalan data sumber selamat sehingga 200 pertanyaan sesaat, dan membina semula cache mengambil masa 800 ms pada p95. Data yang dicache adalah segar (fresh) selama 10 minit, dan perniagaan bertolak ansur dengan paling banyak 30 saat kelapukan (staleness). Perkhidmatan ini berjalan pada 100 tika (instance) aplikasi stateless yang berkongsi cache jauh (remote cache) dan pangkalan data sumber yang sama.

Reka laluan bacaan dan penyegaran yang lengkap. Rangkumi soft expiry, hard expiry, muatan sejuk pertama (cold load), crash pada refresher, gangguan perkhidmatan cache (cache outage), dan perubahan data sumber semasa penyegaran. Terangkan cara anda membuktikan bahawa reka bentuk tersebut tidak sekadar memindahkan beban serentak ke pangkalan data. Nilai daya pemprosesan (throughput), kependaman (latency), dan penamatan tempoh adalah input temu duga, bukan tuntutan prestasi mengenai sesuatu produk.

Ini adalah soalan kebolehpercayaan bahagian belakang (backend reliability). Set soalan temu duga SRE 2026 awam semasa secara jelas membentangkan senario cache stampede yang disebabkan oleh kunci kritikal yang tamat tempoh di bawah 100,000 permintaan sesaat; versi ini mengubah senario tersebut menjadi kekangan kejuruteraan yang boleh diukur. Ia berbeza daripada melaksanakan dasar penyingkiran LRU dalam proses kerana masalah terasnya ialah keserentakan merentas tika dan semantik kegagalan.

Perkara yang dinilai oleh penemu duga

Pertama, calon harus mengukur peristiwa penamatan tempoh secara kuantitatif. Jika setiap ketibaan memintas cache semasa pembinaan semula 800 ms, kira-kira 50,000 × 0.8 = 40,000 permintaan mungkin cuba mencapai sumber asal. Itu jauh melebihi kadar selamat 200 pertanyaan sesaat. Menambah cache tidak menyelesaikan beban yang diselaraskan apabila entri cache hilang.

Kedua, jawapan yang kukuh memisahkan tiga lapisan perlindungan. Local request coalescing hanya mengekang satu proses; jika setiap satu daripada 100 tika memilih refresher, sistem masih boleh mengeluarkan 100 pembinaan semula serentak. Distributed lease biasanya mengurangkan penyegaran merentas tika kepada satu, tetapi penamatan tempoh pajakan (lease expiry), jeda proses, dan sekatan pemisahan (partition) masih boleh mewujudkan penyegaran yang bertindih. Oleh itu, origin concurrency bulkhead atau had kadar (rate limit) mesti kekal sebagai pertahanan terakhir yang bebas.

Ketiga, semantik penamatan tempoh mestilah jelas. Data segar kembali serta-merta. Selepas soft expiry, data boleh dikembalikan dalam tetingkap lapuk 30 saat sementara penyegaran dicuba di latar belakang. Selepas hard expiry, sistem tidak boleh menyajikan data lapuk selama-lamanya: permintaan yang tidak memiliki hak penyegaran mesti menunggu untuk tempoh yang terhad, merosot taraf (degrade), atau gagal dan bukannya semua mencapai sumber asal.

Akhir sekali, penemu duga ingin mendengar cara reka bentuk tersebut menghalang refresher lama daripada menulis ganti nilai yang lebih baharu. Pajakan (lease) hanya menyediakan pengecualian semasa tetingkap kesahihannya; ia bukan jaminan exactly-once. Entri cache memerlukan versi atau generasi sumber, dan penulisan mesti membandingkan versi sebelum menggantikan data.

Soalan untuk penjelasan

  • Adakah data lapuk benar-benar selamat? Senario ini membenarkan selewat-lewatnya 30 saat. Baki, pengesahan (authorization), dan potongan inventori mungkin memerlukan tingkah laku yang lebih ketat.
  • Apakah yang diukur oleh had sumber asal? Anggap 200 pertanyaan sesaat sebagai had selamat seluruh pangkalan data, di samping meminta had keserentakan dan had masa tamat (timeout) bagi setiap kunci.
  • Bolehkah cold load mengembalikan nilai lalai (default)? Secara lalai tiada nilai lapuk wujud, jadi hanya satu refresher mencapai sumber asal dan pengikut menunggu untuk masa yang terhad. Nilai lalai statik ialah kemerosotan produk yang jelas jika tersedia.
  • Bagaimanakah entri dinyahsahkan? Gunakan cop masa kesegaran logik dan hard-expiry dan bukannya memadam setiap salinan secara fizikal pada saat yang sama. Peristiwa perubahan sumber boleh menyegarkan atau menyahsahkan entri lebih awal.
  • Adakah ini berbilang rantau (multi-region)? Mulakan dengan 100 tika dalam satu rantau. Pelbagai rantau memerlukan peruntukan belanjawan sumber asal; kunci merentas rantau tidak boleh diandaikan untuk menyelesaikan setiap mod kegagalan.
  • Patutkah pemanggil mengetahui bahawa data sudah lapuk? Respons dalaman dan telemetri sekurang-kurangnya harus merekodkan stale_age dan sebab kemerosotan taraf. Keperluan produk menentukan sama ada pengguna akhir melihatnya.
  • Apakah yang berlaku jika cache gagal? Tentukan belanjawan kemerosotan dan sumber asal terlebih dahulu. Ralat cache tidak boleh bermaksud bahawa setiap permintaan menyoal pangkalan data.

Jawapan 30 saat

“Saya akan mencache fresh_until, stale_until, dan versi sumber bersama-sama nilainya. Hit segar dikembalikan secara langsung. Semasa tetingkap lapuk 30 saat, kembalikan nilai lama dan pilih refresher menggunakan singleflight bagi setiap proses serta distributed lease dengan token pemilikan dan TTL. Pada cold miss atau hard miss, pengikut hanya menunggu untuk masa yang terhad dan membaca semula dengan jitter. Penulisan penyegaran membandingkan versi sumber, dan pelepasan pajakan memeriksa token. Oleh kerana penamatan tempoh pajakan masih boleh membenarkan pertindihan, pangkalan data juga memerlukan bulkhead bagi setiap kunci dan global. Saya akan mengesahkan QPS sumber asal, keserentakan, dan usia lapuk maksimum dengan ujian beban penamatan tempoh, crash refresher, lebihan pajakan, dan latihan simulasi gangguan cache.”

Pendalaman langkah demi langkah

Mulakan dengan mentakrifkan entri cache dan bukannya menyimpan nilai perniagaan semata-mata:

text
CacheEntry {
  value
  source_version
  generated_at
  fresh_until
  stale_until
}

fresh_until menamatkan tempoh kesegaran 10 minit, dan stale_until melanjutkannya tidak lebih daripada 30 saat. TTL fizikal kunci jauh mesti meliputi stale_until ditambah margin pembersihan yang kecil; jika tidak, cache akan memadamkan nilai yang masih selamat untuk disajikan semasa soft expiry. Tetingkap lapuk ialah belanjawan perniagaan dan tidak boleh dilanjutkan secara senyap-senyap selepas kegagalan penyegaran berulang.

Laluan bacaan boleh dinyatakan sebagai pseudokod:

text
entry = cache.get(key)
now = clock.now()

if entry exists and now < entry.fresh_until:
  return entry.value

if entry exists and now < entry.stale_until:
  try_refresh_async(key)
  return entry.value

return rebuild_or_wait(key, request_deadline)

Laluan soft-expiry melindungi kependaman permintaan. Permintaan pertama yang menyedari soft expiry cuba melakukan penyegaran latar belakang sementara yang lain terus menggunakan nilai lama. Singleflight bagi setiap proses menggabungkan panggilan penyegaran mengikut kunci; pelaksanaan awam Go mentakrifkan ini sebagai satu pelaksanaan dalam penerbangan bagi setiap kunci yang hasilnya dikongsi dengan pemanggil pendua. Ia tidak melangkaui sempadan proses, jadi ia tidak mencukupi dengan sendirinya merentas 100 tika.

Gunakan pajakan terikat masa untuk penyegaran merentas tika. Pesaing mencipta token rawak yang tidak boleh diguna semula dan melaksanakan:

text
SET refresh:{key} {token} NX PX {lease_ms}

Selepas memperoleh pajakan, baca semula cache sekiranya refresher lain baru sahaja selesai, dan buat pertanyaan ke sumber asal hanya jika penyegaran masih diperlukan. Lepaskan pajakan hanya jika nilainya semasa masih sama dengan token milik pemilik. DEL biasa adalah tidak selamat: refresher lama mungkin dijeda sehingga pajakannya tamat tempoh, pengganti mungkin memperoleh pajakan baharu, dan proses lama mungkin menyambung semula lalu memadamkan pajakan pengganti. Panduan kunci teragih Redis juga memerlukan nilai unik dan semakan pemilikan untuk pelepasan yang selamat.

Tetapkan lease_ms melebihi p99 penyegaran yang diukur ditambah margin rangkaian dan penjadualan, bukan secara mekanikal mengikut p95 800 ms. Pajakan yang terlalu pendek meningkatkan pertindihan; pajakan yang terlalu panjang melambatkan pengambilalihan selepas crash. Penamatan tempoh pajakan hanya membenarkan pesaing baharu mencuba; ia tidak membuktikan bahawa operasi lama telah berhenti. Oleh itu, bacaan sumber asal masih memerlukan perkhidmatan singleflight bagi setiap kunci atau bulkhead pangkalan data, dan penulisan cache mesti bertolak ansur dengan pelaksanaan yang bertindih.

Baca versi sumber monotonik dengan data, seperti versi baris atau jujukan peristiwa. Gantikan cache hanya apabila new.source_version >= cached.source_version. Jika sumber tidak mempunyai versi yang boleh dipercayai, peruntukkan generasi penyegaran dengan peningkatan atomik dalam storan penyelarasan kongsi dan bandingkannya secara atomik pada cache. Cache masih bukan punca kebenaran (source of truth); penyegaran yang tertangguh tidak boleh menulis ganti versi yang lebih baharu yang telah dipasang oleh peristiwa perubahan.

Hard expiry atau muatan pertama tidak mempunyai nilai lama yang boleh diterima. Pemilik pajakan membina semula hanya selepas memasuki bulkhead sumber asal. Pengikut membaca semula cache pada selang masa yang singkat dan mempunyai jitter dalam had masa akhir permintaan dan bukannya melakukan pengundian (polling) secara serentak. Apabila masa menunggu itu tamat, kembalikan respons terdegradasi yang jelas atau ralat. Nilai lalai statik boleh digunakan jika produk membenarkannya, tetapi ketersediaan ketara tidak boleh menghantar kesemua 50,000 permintaan ke sumber asal.

Pertahanan terakhir sumber asal harus merangkumi had keserentakan bagi setiap kunci, had keserentakan penyegaran global, dan belanjawan kadar pertanyaan. Dalam keadaan normal hanya satu pembinaan semula berjalan untuk sesuatu kunci. Semasa kegagalan pajakan, bulkhead masih memastikan jumlah kerja sumber asal berada di dalam sempadan yang selamat. Apabila kapasiti habis, penyegaran gagal dengan pantas (fail fast) atau memasuki giliran terikat; permintaan soft-expired terus menggunakan nilai yang lebih muda daripada 30 saat, manakala hard miss mengikut dasar kemerosotan yang ditetapkan.

Apabila cache tidak tersedia, aplikasi tidak boleh mengalihkan keseluruhan kadar bacaan ke pangkalan data. Near-cache baca sahaja yang berjangka hayat pendek boleh menyediakan nilai lapuk yang boleh diterima, tetapi semua bacaan sumber asal yang diperlukan tetap melalui bulkhead global. Permintaan tanpa nilai near-cache mesti merosot taraf atau gagal. Panaskan kunci hangat (warm hot keys) pada kadar terkawal semasa pemulihan dan bukannya meminta setiap tika mengisi semula sekali gus. Jitter TTL rawak membantu apabila banyak kunci berbeza tamat tempoh bersama-sama, tetapi ia tidak menyelesaikan pembinaan semula serentak bagi satu hot key.

Mod kegagalan yang berkaitan harus kekal berasingan. Cache stampede atau kerosakan hot-key ialah pembinaan semula serentak selepas hot key sedia ada menjadi tidak tersedia. Cache avalanche ialah penamatan tempoh serentak bagi banyak kunci atau gangguan perkhidmatan menyeluruh pada cache. Cache penetration ialah carian berulang bagi data yang tidak wujud. Jitter TTL terutamanya membantu menangani avalanche, manakala negative cache pendek atau penapis Bloom membantu menangani penetration; kedua-duanya tidak menggantikan request coalescing untuk senario ini.

Data yang diramalkan hangat boleh disegarkan sebelum fresh_until. Pendekatan pengesahan semula awal kebarangkalian (probabilistic early-revalidation) yang diterbitkan oleh Cloudflare meningkatkan kebarangkalian penyegaran apabila penamatan tempoh semakin hampir, mengurangkan perebutan kunci di bawah kadar permintaan yang tinggi. Pernyataan tetap seperti "segarkan 1% permintaan" adalah tidak selamat kerana tingkah lakunya berubah mengikut trafik. Tetingkap lapuk yang terikat dan penyegaran latar belakang juga sepadan dengan semantik HTTP stale-while-revalidate: kandungan lapuk dibenarkan hanya dalam selang masa yang jelas sementara pengesahan semula berlaku secara tak segerak (asynchronous).

Bagi berbilang rantau, utamakan cache serantau dan refresher serantau dengan belanjawan QPS dan keserentakan sumber asal yang diperuntukkan. Satu pajakan global tunggal menambah kependaman merentas rantau dan tingkah laku pemisahan pada laluan bacaan. Jika setiap rantau berkongsi satu sumber asal, satah kawalan boleh memperuntukkan belanjawan penyegaran atau sumber asal boleh mendedahkan perkhidmatan pembinaan semula berpusat. Dalam mana-mana kes, jumlah belanjawan serantau mesti kekal dalam 200 pertanyaan sesaat.

Perhatikan kadar fresh-hit, stale-served, dan hard-miss; usia lapuk; percubaan dan kegagalan penyegaran; pemanggil kongsi singleflight; perebutan dan penamatan tempoh pajakan; kependaman penyegaran; QPS, keserentakan, dan penolakan sumber asal; serta kependaman dan ralat cache. Berikan amaran tentang belanjawan sumber asal yang telah habis, nilai yang menghampiri stale_until, dan kegagalan penyegaran yang berterusan daripada hanya bergantung pada kadar hit cache semata-mata.

Uji batas tak varian (invariants) secara langsung. Tamatkan tempoh kunci di bawah 50,000 permintaan sesaat dan sahkan satu pembinaan semula sumber asal bagi setiap kunci dalam kes biasa. Lakukan simulasi crash pada refresher sebelum penulisannya dan sahkan bahawa data lapuk kekal tersedia dan pengganti mengambil alih selepas pajakan tamat tempoh. Jeda refresher lama melebihi tempoh pajakan dan sahkan bahawa ia tidak boleh menggantikan versi yang lebih baharu. Lumpuhkan cache dan sahkan bahawa sumber asal kekal dalam 200 pertanyaan sesaat dan bulkhead keserentakannya. Tamatkan tempoh banyak kunci bersama-sama dan sahkan keberkesanan jitter TTL serta belanjawan global.

Contoh jawapan yang kukuh

“Saya akan bermula dengan beban kes terburuk. Lima puluh ribu permintaan sesaat didarabkan dengan pembinaan semula 800 ms menghasilkan kira-kira 40,000 ketibaan semasa tetingkap penamatan tempoh, manakala pangkalan data selamat untuk 200 pertanyaan sesaat sahaja. Tiada pengikut boleh bolos terus ke sumber asal.

Saya akan mencache nilai tersebut dengan versi sumbernya, fresh_until, dan stale_until. Kembalikan ia secara langsung selama 10 minit, kemudian sajikan sehingga 30 saat tambahan sementara mencuba penyegaran. Setiap proses terlebih dahulu menggabungkan kerja tempatan dengan singleflight, kemudian pesaing menggunakan SET lock token NX PX lease untuk memilih refresher merentas tika. Pemilik menyemak semula cache sebelum menyoal pangkalan data. Pelepasan pajakan membandingkan token, dan penulisan cache membandingkan versi sumber supaya refresher lama tidak boleh memadamkan pajakan baharu atau menulis ganti data yang lebih baharu.

Pada cold load atau selepas 30 saat, tiada nilai lapuk yang boleh diterima. Satu permintaan membina semula sementara pengikut membaca semula dengan jitter sehingga had masa akhir mereka, kemudian menggunakan kemerosotan lalai yang jelas atau mengembalikan ralat. Pangkalan data juga mempunyai bulkhead bagi setiap kunci dan global kerana penamatan tempoh pajakan mungkin membenarkan refresher bertindih; kunci tidak menggantikan perlindungan kapasiti.

Saya akan menguji beban sempadan penamatan tempoh yang tepat dan menyuntik crash refresher, jeda yang lebih lama daripada pajakan, kegagalan cache, dan kemas kini sumber yang serentak. Kriteria penerimaan merangkumi QPS sumber asal tidak lebih tinggi daripada 200, satu pembinaan semula normal bagi setiap kunci, usia lapuk tidak lebih daripada 30 saat, dan tiada regresi versi daripada penulis yang tertangguh. Itu memberikan batasan yang boleh diukur kepada kependaman, kesegaran, dan keselamatan sumber asal.”

Kesilapan lazim

  • Hanya menambah jitter TTL rawak → Ini menyebarkan penamatan tempoh merentas kunci yang berbeza tetapi tidak menghentikan pembinaan semula serentak bagi satu hot key → Gabungkan kerja bagi setiap kunci dan kekalkan bulkhead sumber asal.
  • Hanya menggunakan singleflight dalam proses → Seratus tika masih boleh menghasilkan 100 refresher → Gabungkan penggabungan tempatan dengan pajakan merentas tika.
  • Membaca pangkalan data sebelum memperoleh hak penyegaran → Lonjakan keserentakan telah pun mencapai sumber asal → Pilih dahulu, semak semula cache, dan kemudian masuk ke belanjawan sumber asal.
  • Mengambil kunci SETNX tanpa TTL → Refresher yang mengalami crash boleh menyekat kemas kini selama-lamanya → Gunakan pajakan terikat dengan tingkah laku pengambilalihan.
  • Melepaskan dengan DEL biasa → Refresher lama mungkin memadamkan pajakan penggantinya → Lepaskan secara atomik hanya apabila token unik masih sepadan.
  • Menganggap pajakan sebagai pelaksanaan exactly-once → Proses yang dijeda melepasi TTL boleh bertindih dengan pengganti → Gunakan bulkhead sumber asal dan penulisan berversi untuk bertolak ansur dengan pertindihan.
  • Menyajikan data lapuk selama-lamanya selepas kegagalan → Usia data kehilangan had atasnya → Sajikan hanya sebelum stale_until, kemudian turunkan taraf atau gagal secara jelas.
  • Menghantar semua trafik ke sumber asal semasa gangguan perkhidmatan cache → 50,000 bacaan sesaat akan membebankan sumber asal yang selamat untuk 200 pertanyaan sahaja → Gunakan nilai near-cache jika dibenarkan dan salurkan setiap bacaan sumber asal melalui belanjawan kongsi.
  • Mengelirukan antara stampede, avalanche, dan penetration → Pemulihan tidak lagi sepadan dengan jenis kegagalan → Gunakan request coalescing, jitter TTL, dan negative caching untuk masalah masing-masing.
  • Hanya memantau kadar hit → Kadar hit yang tinggi boleh menyembunyikan penyegaran yang gagal dan lonjakan pendek sumber asal → Pantau juga usia lapuk, keserentakan penyegaran, pajakan, dan belanjawan sumber asal.

Susulan

Susulan 1: Bagaimana jika perniagaan tidak boleh menyajikan data lapuk langsung?

Keluarkan respons lapuk dan biarkan pengikut menunggu hanya untuk tempoh yang terhad. Sediakan kapasiti pembinaan semula yang mencukupi dan kembalikan kegagalan yang jelas tanpa mengorbankan keselamatan sumber asal.

Susulan 2: Berapa lamakah sepatutnya TTL pajakan?

Mulakan daripada p99 penyegaran yang diukur, masa tamat rangkaian, dan jeda penjadualan, kemudian tambah margin dan perhatikan kekerapan kerja bertahan lebih lama daripada pajakan. Nilai p95 800 ms tidak mencukupi dengan sendirinya.

Susulan 3: Bagaimana jika data sumber berubah semasa penyegaran?

Baca dan bawa versi sumber, kemudian kemas kini cache secara bersyarat. Versi lebih baharu yang dipasang oleh peristiwa perubahan tidak boleh digantikan oleh penyegaran yang tertangguh.

Susulan 4: Bagaimana jika seluruh kluster cache tidak tersedia?

Sajikan nilai near-cache yang boleh diterima, pastikan setiap bacaan sumber asal yang diperlukan berada di belakang bulkhead global, turunkan taraf apabila tiada salinan wujud, dan panaskan kunci pada kadar terkawal semasa pemulihan.

Susulan 5: Bagaimanakah negative caching dimuatkan?

Cache keputusan "tidak dijumpai" yang disahkan untuk TTL yang pendek bagi menghalang penetration. Ia bebas daripada penggabungan penyegaran untuk hot key sedia ada.

Susulan 6: Bilakah penyegaran awal kebarangkalian berguna?

Untuk data yang boleh dikira semula, toleran terhadap kelapukan, dan berkadar tinggi. Kebarangkalian harus bergantung pada baki kesegaran dan trafik yang diperhatikan, dengan kegagalan penyegaran dan belanjawan sumber asal masih dikuatkuasakan.

Susulan 7: Patutkah rantau berkongsi satu kunci?

Kebiasaannya tidak. Segarkan mengikut rantau dan peruntukkan belanjawan sumber asal. Penyelarasan berpusat hanya wajar apabila penyegaran tunggal global diperlukan dan kependaman serta pemisahan merentas rantau boleh diterima.

Susulan 8: Bagaimanakah anda membuktikan bahawa reka bentuk itu berfungsi?

Jalankan 50,000 permintaan sesaat merentas soft expiry dan hard expiry sambil menyuntik crash, jeda, kegagalan cache, dan perlumbaan versi. Sahkan satu penyegaran normal bagi setiap kunci, beban sumber asal dalam belanjawan, kelapukan paling banyak 30 saat, dan tiada pembalikan (rollback) versi.

Sumber awam

Soalan berkaitan