Maqola · 2026-08-16 · ~3 daqiqa o‘qiladi · o'rta
Negative caching tuzog'i: xatolikni ham keshlab qo'ymang
Mundarija
Kecha shu saytning o'zida qiziq bug bo'ldi: bosh sahifadagi "open-source loyihalar" soni GitHub'dan jonli olinadi, lekin production'da u eskirgan zaxira qiymatni ko'rsatib turaverdi. Lokalda esa hammasi to'g'ri. Sabab — men bilib turib qazib qo'ygan chuqurga o'zim tushdim: xatolikni ham muvaffaqiyat bilan bir xil muddatga keshlagan edim.
Kod qanday edi#
def repo_count() -> int:
cached = cache.get(CACHE_KEY)
if cached is not None:
return cached
value = fetch_from_github() # xato bo'lsa None
if value is None:
value = FALLBACK # zaxira qiymat
cache.set(CACHE_KEY, value, 60 * 60 * 12) # 12 soat!
return value
Bir qarashda mantiqiy: qiymat topilmasa zaxirani olamiz, keshga yozamiz, 12 soat
tinch yashaymiz. Muammo shundaki, cache.set ikkala holatda ham 12 soatga yozadi.
Nima bo'ldi#
Server qayta ishga tushganda birinchi so'rov GitHub API'ga 3 soniyalik timeout
bilan ketdi. O'sha paytda tarmoq bir soniya sekinroq edi — so'rov o'tmadi,
None qaytdi, zaxira qiymat keshga tushdi. Tamom: keyingi 12 soat davomida
hech kim GitHub'ga qayta so'rov yubormaydi, chunki kesh "to'la". Bitta omadsiz
soniya — kun bo'yi eskirgan raqam.
Bu holatning nomi bor: negative caching — salbiy natijani (xato, bo'sh javob, 404) keshlab qo'yish. O'z-o'zidan yomon narsa emas, DNS ham shunday qiladi. Xato — salbiy natijani ijobiy natija muddatiga keshlash.
To'g'ri yechim#
Ikkala holatga alohida muddat:
TTL = 60 * 60 * 12 # muvaffaqiyat: 12 soat
FAILURE_TTL = 60 * 15 # xatolik: 15 daqiqadan keyin qayta urinamiz
value = fetch_from_github()
if value is None:
cache.set(CACHE_KEY, FALLBACK, FAILURE_TTL)
return FALLBACK
cache.set(CACHE_KEY, value, TTL)
return value
Endi omadsiz so'rov ko'pi bilan 15 daqiqa yashaydi — foydalanuvchi zaxira qiymatni qisqa vaqt ko'radi, tizim esa o'zini o'zi tuzatadi.
Qoidalar#
- Muvaffaqiyat va xatolik — har doim alohida TTL. Xatolik uchun qisqa (soniyalar–daqiqalar), muvaffaqiyat uchun uzun.
- Timeout'ni juda qattiq qilmang. 3 soniya tashqi API uchun kam — bitta sekin javob butun keshni zaharlaydi.
- Zaxira qiymat — vaqtinchalik yamoq, holat emas. U keshda uzoq yashasa, foydalanuvchi uchun "haqiqat"ga aylanadi.
- Bunday bug'ni topish qiyin: kod ishlayapti, xato loglari yo'q, faqat raqam "qotib" qolgan. Shuning uchun keshga yozayotgan har bir joyda o'zingizdan so'rang: "bu yerga xato qiymat tushsa, qachon tuzaladi?"
Kichik bug, katta saboq — endi bu savol mening har bir code review ro'yxatimda.