Mundarija (23)
- Bu darsda
- 1. Nega bu kerak?
- 2. CacheModule va CACHE_MANAGER
- 2.1 Ulash
- 2.2 Qo'lda ishlatish
- 3. CacheInterceptor — avtomatik keshlash
- 3.1 Kanon tajribasi
- 3.2 Qatorma-qator
- 3.3 Kesh so'rov yo'lining qayerida turadi?
- 4. Biz ham sinadik — xotira ombori va ikki kutilmagan natija
- 4.1 Xotira ombori havolani saqlaydi
- 4.2 Hamma foydalanuvchiga bitta javob
- 5. Hujumchi nigohi
- 6. Kanon qarori: KeshliOmbor qoladi
- 7. Ko'p uchraydigan xatolar
- 8. Mashqlar
- 1-mashq (oson): kalit va birlik
- 2-mashq (o'rta): URL keshi modeli
- 3-mashq (qiyin): avlod kalitli kesh
- 9. Loyiha qadami: o'zgarish yo'q — va nega
- 10. Real ishda
- Xulosa
- Manbalar
NestJS keshlash: CacheModule, CacheInterceptor va Redis (Keyv)
Qisqacha:
@nestjs/cache-manager— Nest'ning kesh moduli:CacheModule.register()kesh xizmatini beradi, uni@Inject(CACHE_MANAGER)bilan olibget,set,delqilasiz. Ombor —cache-manager7 va Keyv: sukutda xotira,@keyv/redisbilan Redis.@UseInterceptors(CacheInterceptor)GET javobini avtomatik keshlaydi — kalit URL. Qulay, lekin uch tuzoq bor: yozuvdan keyin eskirgan javob (TTL tugaguncha), bitta URL — hamma foydalanuvchi uchun bitta javob, invalidatsiya esa qo'lda va kalitlarni bilishni talab qiladi. Shuning uchunvazifalar-api27-qismdagiKeshliOmborda qoladi.
Bu darsda
CacheModule.register/registerAsyncva Keyv omborlarini (xotira, Redis) ulaysiz.CACHE_MANAGERbilan qo'ldaget/set/delqilasiz va TTL birligini bilasiz.CacheInterceptor,@CacheKey,@CacheTTLqanday kalit yasashini haqiqiy chiqishda ko'rasiz.- Eskirgan javob, foydalanuvchilar aralashuvi va xotira omboridagi havola tuzog'ini o'z ko'zingiz bilan ko'rasiz.
- Kanon nega
CacheInterceptoremas, avlod kalitliKeshliOmborni tanlaganini tushuntirasiz.
Oldin bilishingiz kerak: Caching naqshlari va invalidatsiya, String, TTL va kalit nomlash, Interceptor'lar va RxJS, Repository naqshi va qatlamlar, Swagger: @nestjs/swagger.
O'tgan darsda vazifalar-api ga hujjat qo'shildi. Bu dars — tajriba darsi: Nest'ning standart kesh vositasini 27-qismda o'zimiz qurgan kesh bilan solishtiramiz.
1. Nega bu kerak?
27-qismda kesh qurgandik (Caching naqshlari va invalidatsiya): Redis'da ro'yxat javobi saqlanadi, bazaga har safar bormaymiz. Eng qiyin qismi — keshlashning o'zi emas, invalidatsiya: ma'lumot o'zgarganda eski nusxani o'z vaqtida unutish. "Kompyuter fanidagi ikki qiyin narsa" haqidagi mashhur hazil aynan shu haqda.
Nest'da kesh uchun tayyor modul bor. Savol: u bizning muammoni hal qiladimi yoki yangisini keltiradimi?
O'xshatish: do'kon peshtaxtasidagi narx yorlig'i. Har mijozga narxni omborxonadan so'rab kelish o'rniga, yorliq yopishtirasiz — tez. Lekin narx o'zgarsa, yorliqni almashtirish kerak. Agar yorliqlar "qaysi javonda turganiga" qarab yopishtirilsa, bitta mahsulot uch javonda bo'lsa — uchalasini topib almashtirish kerak. Bittasi unutilsa, mijoz eski narxni ko'radi.
2. CacheModule va CACHE_MANAGER
2.1 Ulash
CacheModule.registerAsync({
useFactory: () => ({
stores: [new KeyvRedis("redis://127.0.0.1:6383")],
ttl: 60_000,
}),
}),stores— Keyv omborlari ro'yxati.cache-manager6 dan boshlab o'z omborlari o'rniga Keyv ishlatadi:@keyv/redis,@keyv/postgresva boshqalar.storesberilmasa — xotira (jarayon ichidagiMap).ttl: 60_000— yashash vaqti millisekundda. 27-qismdagi RedisEX 60soniyada edi (String, TTL va kalit nomlash); bu yerda60deb yozsangiz — 60 ms, kesh deyarli ishlamaydi.registerAsync— sozlama config'dan kelishi uchun (@nestjs/config darsidagiforRootAsyncnaqshi).isGlobal: trueham bor.
Versiyalar — kanon tajribasidagi: @nestjs/cache-manager 12.0.1, cache-manager 7.2.9, @keyv/redis 6.1.0.
2.2 Qo'lda ishlatish
constructor(@Inject(CACHE_MANAGER) private readonly kesh: Cache) {}
await this.kesh.set("vz:1:royxat", natija, 60_000);
const bor = await this.kesh.get<RoyxatNatija>("vz:1:royxat");
await this.kesh.del("vz:1:royxat");CACHE_MANAGER — token (Custom provider'lar), Cache — cache-manager turi. Hamma metod async: ombor Redis bo'lsa, har chaqiruv — tarmoq aylanishi. Bu shakl — 27-qismdagi cache-aside naqshining o'zi, faqat klient boshqa.
3. CacheInterceptor — avtomatik keshlash
3.1 Kanon tajribasi
@Controller("v")
class C {
constructor(@Inject(CACHE_MANAGER) private readonly kesh: Cache) {}
@Get() @UseInterceptors(CacheInterceptor) @CacheTTL(60_000)
royxat() {
ombordanOqish++;
return { vazifalar };
}
@Post() yarat(@Body() b: { matn: string; tozala?: boolean }) {
vazifalar.push({ id: vazifalar.length + 1, matn: b.matn });
// CacheInterceptor kalitni o'zi qo'yadi — URL; invalidatsiya —
// qo'lda, kalitni bilish kerak
return b.tozala === true
? this.kesh.del("/v")
.then(() => ({ ok: true, tozalandi: true }))
: { ok: true };
}
}Bu kanon tajribasi kodi, telefon uchun bo'lindi. CacheInterceptor — interceptor: u handler'dan oldin keshga qaraydi. Javob bor bo'lsa — handler'ni chaqirmasdan qaytaradi. Yo'q bo'lsa — handler natijasini keshga yozadi. @CacheTTL(60_000) — shu marshrut uchun TTL. ombordanOqish — handler necha marta haqiqatan ishlaganini sanaydi. vazifalar — xotiradagi massiv, "ombor" o'rnida.
Kanon chiqishi — Redis bilan (kanon o'lchovi, IlmHamroh, 2026-10, NestJS 12.2.0). Har qatorda ikki narsaga qarang: javobdagi ro'yxat va "ombordan o'qish" soni. Son o'zgarmasa — javob keshdan kelgan:
1) GET /v → 200 {"vazifalar":[{"id":1,"matn":"Non"}]}; ombordan o'qish: 1
2) GET /v (yana) → 200 {"vazifalar":[{"id":1,"matn":"Non"}]}; ombordan o'qish: 1 (keshdan)
3) GET /v?x=1 → 200 {"vazifalar":[{"id":1,"matn":"Non"}]}; ombordan o'qish: 2 — boshqa URL = boshqa kalit
4) POST "Sut" (tozalamasdan) keyin GET /v → 200 {"vazifalar":[{"id":1,"matn":"Non"}]} — ESKIRGAN (TTL 60 s gacha)
5) POST "Olma" + kesh.del("/v") → 200 {"vazifalar":[{"id":1,"matn":"Non"},{"id":2,"matn":"Sut"},{"id":3,"matn":"Olma"}]}; lekin /v?x=1 → 200 {"vazifalar":[{"id":1,"matn":"Non"}]} — u kalit tozalanmadi
6) Redis'dagi kalitlar (keyv prefiksi bilan): ["/v","/v?x=1","vz:1:avlod"]
7) o'rtacha (bitta jarayon, ketma-ket): kesh HIT 1.17 ms, MISS (+del) 1.96 ms — "ombor" bu yerda xotiradagi massiv (0 ms): kesh yutuq bermaydi3.2 Qatorma-qator
- Birinchi GET — keshda yo'q, handler ishladi (1).
- Ikkinchi GET — keshdan; handler chaqirilmadi (hali 1).
/v?x=1— boshqa kalit, handler yana ishladi (2). Kalit — to'liq URL, query bilan.?sort=matn,?limit=10,?x=1— har biri alohida kesh yozuvi.- POST'dan keyin — "Sut" qo'shildi, lekin GET hali eski ro'yxatni berdi. Kesh yozuvdan bexabar: TTL (60 s) tugaguncha mijoz eski ma'lumot ko'radi.
del("/v")—/vtoza, yangi ro'yxat keldi. Lekin/v?x=1hali eski. Invalidatsiya uchun har URL kalitini bilish va o'chirish kerak — query kombinatsiyalari esa cheksiz.- Redis kalitlari —
"/v","/v?x=1": prefikssiz. Xuddi shu Redis'ni boshqa ilova ishlatsa va u ham/vyo'lini keshlasa — kalitlar to'qnashadi.vz:1:avlod— boshqa narsa: 27-qismdagiKeshliOmborning kaliti (o'sha Redis'da edi). - Tezlik — HIT 1.17 ms, MISS 1.96 ms. Bu tajribada "ombor" xotiradagi massiv — 0 ms. Kesh Redis'ga tarmoq aylanishini qo'shdi, ombordan esa hech narsa yutmadi. Kesh faqat ombor qimmat bo'lganda (og'ir SQL, tashqi API) foyda beradi. Bitta mashina, ketma-ket o'lchov — nisbatga qarang.
3.3 Kesh so'rov yo'lining qayerida turadi?
CacheInterceptor — interceptor, demak u so'rov yo'lida aniq joyda ishlaydi (Request lifecycle). Buni bilish ikki savolga javob beradi: "keshlangan marshrutda guard ishlaydimi?" va "pipe xatosi keshga tushadimi?"
| Tartib | Qatlam | Keshlangan GET'da nima bo'ladi |
|---|---|---|
| 1 | middleware | har safar ishlaydi |
| 2 | guard | har safar ishlaydi — ruxsat tekshiruvi kesh oldida |
| 3 | interceptor (oldin) | CacheInterceptor keshga qaraydi; bor bo'lsa — shu yerda qaytadi |
| 4 | pipe | faqat keshda yo'q bo'lsa |
| 5 | handler | faqat keshda yo'q bo'lsa |
| 6 | interceptor (keyin) | handler natijasi keshga yoziladi |
| 7 | exception filter | xato keshga tushmaydi — faqat muvaffaqiyatli javob yoziladi |
Ikkinchi qatorga e'tibor bering: guard kesh oldida turadi, shuning uchun anonim mijoz keshlangan javobni ham ololmaydi. Lekin guard faqat "o'tsinmi?" deb so'raydi — kimning javobi qaytishini u hal qilmaydi. Buni kalit hal qiladi, kalitda esa foydalanuvchi yo'q. «Hamma foydalanuvchiga bitta javob» bo'limidagi tuzoq aynan shu bo'shliqdan chiqadi.
Yana bir qoida Nest kodida yozilgan: CacheInterceptor faqat GET ni keshlaydi (allowedMethods = ['GET'], @nestjs/cache-manager 12.0.1). POST ga qo'yilsa, hech narsa keshlanmaydi va xato ham chiqmaydi — jim o'tadi. Uchinchi qoida ham kodda: keshdan o'qish xato bersa (masalan, Redis uzilgan), interceptor xatoni yutadi va handler'ni chaqiradi. Ya'ni Redis uzilsa API ishlashda davom etadi, faqat sekinroq — kesh "bor bo'lsa yaxshi" qatlam bo'lib qoladi. 27-qismdagi KeshliOmbor ham shunday qilardi.
Tekshirib ko'ring:
/v?limit=10&sort=matnva/v?sort=matn&limit=10—CacheInterceptoruchun bitta kalitmi?
Javob
Yo'q — URL satri boshqa, demak kalit ham boshqa. Ma'nosi bir xil so'rov ikki marta keshlanadi va invalidatsiyada ikkalasini ham topish kerak. 25-qismdagi kanonik so'rov izi (fingerprint) shu muammo uchun edi (Idempotency-Key) — CacheInterceptor buni qilmaydi.
4. Biz ham sinadik — xotira ombori va ikki kutilmagan natija
4.1 Xotira ombori havolani saqlaydi
Redis'siz takrorladik: o'sha controller, CacheModule.register({ ttl: 60_000 }) — stores siz, ya'ni xotira (biz ishga tushirdik: @nestjs/cache-manager 12.0.1, cache-manager 7.2.9, keyv 6.1.0). 1–3 qadamlar kanon bilan bir xil. 4–5 qadamlar esa:
4) POST "Sut", keyin GET /v → 200 {"vazifalar":[{"id":1,"matn":"Non"},{"id":2,"matn":"Sut"}]}
5) POST "Olma" + del("/v") → GET /v: 200 {"vazifalar":[{"id":1,"matn":"Non"},{"id":2,"matn":"Sut"},{"id":3,"matn":"Olma"}]}
GET /v?x=1: 200 {"vazifalar":[{"id":1,"matn":"Non"},{"id":2,"matn":"Sut"},{"id":3,"matn":"Olma"}]}Eskirgan javob yo'q — "Sut" darhol ko'rindi, /v?x=1 ham yangi. Kesh yaxshiroq ishladimi? Yo'q. Handler { vazifalar } qaytaradi — o'sha massivga havola. Xotira ombori qiymatni nusxalamay saqlaydi (Havola semantikasi). push keshdagi massivni ham o'zgartirdi — kesh "o'z-o'zidan yangilandi". Isboti: handler'ni nusxa qaytaradigan qilsak ({ vazifalar: [...vazifalar] }):
4) POST "Sut", keyin GET /v → 200 {"vazifalar":[{"id":1,"matn":"Non"}]}
5) POST "Olma" + del("/v") → GET /v: 200 {"vazifalar":[{"id":1,"matn":"Non"},{"id":2,"matn":"Sut"},{"id":3,"matn":"Olma"}]}
GET /v?x=1: 200 {"vazifalar":[{"id":1,"matn":"Non"}]}Endi natija kanon (Redis) bilan bir xil: eskirgan javob va tozalanmagan /v?x=1. Xulosa: lokalda xotira ombori bilan "ishlagan" kesh prodakshnda Redis bilan boshqacha ishlaydi. Redis qiymatni JSON qilib saqlaydi — havola uziladi. Testda xotira, prodakshnda Redis bo'lsa, test xatoni yashiradi.
4.2 Hamma foydalanuvchiga bitta javob
Ikkinchi sinov — "mening vazifalarim" marshruti. Foydalanuvchi sarlavhadan keladi (auth o'rnida, x-foydalanuvchi):
@Controller("mening")
class Mening {
@Get() @UseInterceptors(CacheInterceptor)
mening(@Headers("x-foydalanuvchi") kim: string) {
return { kim, vazifalar: `${kim} ning vazifalari` };
}
}6) Ali → 200 {"kim":"Ali","vazifalar":"Ali ning vazifalari"}
Malika → 200 {"kim":"Ali","vazifalar":"Ali ning vazifalari"}Malika Ali'ning ma'lumotini oldi. URL bir xil (/mening), kalit bir xil — kesh foydalanuvchini bilmaydi. Haqiqiy auth bilan ham shunday: cookie va Authorization sarlavhasi kalitga kirmaydi. Bu shunchaki xato emas — ma'lumot sizib chiqishi.
5. Hujumchi nigohi
«Hamma foydalanuvchiga bitta javob» bo'limidagi holat hujumchi uchun tayyor sovg'a — u hech narsa buzmaydi:
- Hujumchi biror foydalanuvchi so'rovidan keyin 60 soniya ichida o'sha URL'ni o'zi so'raydi.
- Kesh unga birovning javobini beradi: vazifalar, email, balans — nima keshlangan bo'lsa.
Teskari holat ham bor — kesh zaharlash (cache poisoning): hujumchi birinchi bo'lib so'rov yuboradi (masalan, g'alati sarlavha bilan), uning javobi keshga tushadi va hamma oladi.
Himoya:
- Shaxsiy ma'lumotli marshrutda
CacheInterceptorishlatmang — yokitrackByni qayta yozib, kalitga foydalanuvchi ID sini qo'shing (CacheInterceptordan meros olib). Biz bu variantni sinamadik. - Kesh kalitini egasi bilan quring — kanondagi
KeshliOmborkabi: kalitdavz:<egasiId>:…. - HTTP darajasida
Cache-Control: private(HTTP caching) — kanon javoblarida bor; bu brauzer va CDN uchun, server keshi uchun emas.
6. Kanon qarori: KeshliOmbor qoladi
27-qismdagi kesh boshqa joyda turadi — ombor qatlamida (Repository naqshi darsidagi o'ram):
flowchart LR
subgraph A["CacheInterceptor"]
R1["so'rov"] --> K1["kalit = URL"]
K1 --> H1["handler"]
end
subgraph B["KeshliOmbor (kanon)"]
X["VazifalarService"] --> K2["kalit = egasi + avlod + so'rov"]
K2 --> P["PgOmbori / PrismaOmbori"]
endChapda — HTTP qatlamida, URL bo'yicha. O'ngda — ombor qatlamida, egasi va avlod bo'yicha. KeshliOmbor har egasi uchun vz:<egasi>:avlod hisoblagichini saqlaydi va har o'qish kalitiga qo'shadi. Har yozuvda (yarat, yangila, ochir) — INCR: avlod oshdi, shu egasining hamma eski kalitlari birdan o'qilmay qoladi. Ularni qidirish va o'chirish shart emas — TTL o'zi tozalaydi.
CacheInterceptor |
KeshliOmbor (kanon) |
|
|---|---|---|
| Kalit | URL | egasi + avlod + so'rov |
| Yozuvdan keyin | eskirgan, TTL gacha | darhol yangi (avlod +1) |
| Invalidatsiya | har URL ni del |
bitta INCR |
| Foydalanuvchilar | aralashadi | ajratilgan |
| Kod | 2 dekorator | ~90 qatorli klass (27-qism) |
Nima yo'qotiladi: qulaylik. CacheInterceptor — ikki qator, KeshliOmbor — alohida klass, testlar, Redis ulanishini boshqarish. Lekin vazifalar-api da yozuvlar ko'p (vazifa belgilash — eng tez-tez amal) va ma'lumot shaxsiy. Bunday API uchun URL bo'yicha kesh noto'g'ri tanlov. Kanon tajribasining xulosasi ham shu (kanon o'lchovi, IlmHamroh, 2026-10).
CacheInterceptor qachon o'rinli? Ma'lumot ommaviy (hamma uchun bir xil) va kam o'zgaradi: valyuta kurslari, kurs katalogi, ob-havo. U yerda bir necha soniya eskirish muammo emas.
7. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
| Kesh deyarli ishlamaydi | ttl: 60 — millisekund |
60_000 |
| Yozuvdan keyin eski ro'yxat | URL kalit, invalidatsiya yo'q | del yoki avlod kaliti |
| Lokalda yangi, prodakshnda eski | xotira ombori havolani saqlaydi | handler nusxa qaytarsin; testda ham Redis |
| Boshqa foydalanuvchi ma'lumoti | kalitda foydalanuvchi yo'q | shaxsiy marshrutda keshlamang yoki trackBy |
| Ikki ilova kalitlari to'qnashdi | Redis kalitlari prefikssiz | Keyv namespace yoki alohida baza |
npm i cache-manager@7.2.10 — ETARGET |
versiya olib tashlangan | npm view cache-manager versions |
Oxirgi qator — kanon tajribasida uchragan haqiqiy holat: npm view cache-manager time da 7.2.10 bor edi, lekin versions ro'yxatida yo'q (nashrdan olib tashlangan) — o'rnatish yiqildi. Versiya tanlashda time emas, versions ga qarang.
8. Mashqlar
Mashqlar kurs/mashqlar/30/38-cachemodule/ da.
1-mashq (oson): kalit va birlik
To'ldiring:
CacheInterceptorkaliti — so'rovning i.ttl: 60_000— 60- Kesh xizmatini olish tokeni —
@Inject() - Kanondagi yozuvdan keyingi invalidatsiya — Redis'da bitta
Yechim
- URL — query bilan birga.
- soniya —
60_000millisekund. - CACHE_MANAGER —
@nestjs/cache-managertokeni. - INCR — avlod hisoblagichi oshadi, eski kalitlar o'qilmaydi.
2-mashq (o'rta): URL keshi modeli
Brauzerda ishlaydigan urlKeshi(handler) yozing: ol(url) — Map da bo'lsa qaytaradi, bo'lmasa handler(url) ni chaqiradi va JSON nusxasini saqlaydi (Redis kabi); del(url). Sinov: kanon tajribasining 1–5 qadamlarini takrorlang va har qadamdan keyin javobdagi vazifalar sonini va handler necha marta chaqirilganini chiqaring. Ishora: JSON.parse(JSON.stringify(x)) (JSON asoslari).
Yechim
function urlKeshi(handler) {
const kesh = new Map();
return {
ol(url) {
if (!kesh.has(url)) kesh.set(url, JSON.stringify(handler(url)));
return JSON.parse(kesh.get(url));
},
del(url) { kesh.delete(url); },
};
}
const vazifalar = [{ id: 1, matn: "Non" }];
let chaqiruv = 0;
const k = urlKeshi(() => {
chaqiruv++;
return { vazifalar };
});
const son = (url) => k.ol(url).vazifalar.length;
console.log(`1) /v: ${son("/v")}, handler: ${chaqiruv}`);
console.log(`2) /v: ${son("/v")}, handler: ${chaqiruv}`);
console.log(`3) /v?x=1: ${son("/v?x=1")}, handler: ${chaqiruv}`);
vazifalar.push({ id: 2, matn: "Sut" });
console.log(`4) /v: ${son("/v")} (eskirgan)`);
vazifalar.push({ id: 3, matn: "Olma" });
k.del("/v");
console.log(`5) /v: ${son("/v")}, /v?x=1: ${son("/v?x=1")}`);Konsolda:
1) /v: 1, handler: 1
2) /v: 1, handler: 1
3) /v?x=1: 1, handler: 2
4) /v: 1 (eskirgan)
5) /v: 3, /v?x=1: 1Model kanon (Redis) natijasini takrorladi — chunki JSON.stringify havolani uzdi. JSON.stringify ni olib tashlab, obyektning o'zini saqlab ko'ring: 4-qadamda 2 chiqadi — «Xotira ombori havolani saqlaydi» bo'limidagi holat.
3-mashq (qiyin): avlod kalitli kesh
avlodKeshi(ombor) yozing — KeshliOmbor g'oyasi. royxat(egasi, sorov) kaliti: vz:${egasi}:${avlod}:${sorov}; yarat(egasi, matn) — omborga yozadi va faqat shu egasining avlodini oshiradi. Ombor — { egasi: [matnlar] } obyekt, o'qishlar sanaladi. Sinov: Ali ikki marta o'qiydi, Malika bir marta, Ali yozadi, ikkalasi yana o'qiydi. Ishora: avlodlar uchun alohida Map, sukut 1.
Yechim
function avlodKeshi(ombor) {
const kesh = new Map();
const avlod = new Map();
let oqish = 0;
const av = (egasi) => avlod.get(egasi) ?? 1;
return {
royxat(egasi, sorov) {
const kalit = `vz:${egasi}:${av(egasi)}:${sorov}`;
if (!kesh.has(kalit)) {
oqish++;
kesh.set(kalit, JSON.stringify(ombor[egasi] ?? []));
}
return JSON.parse(kesh.get(kalit));
},
yarat(egasi, matn) {
(ombor[egasi] ??= []).push(matn);
avlod.set(egasi, av(egasi) + 1); // INCR
},
get oqish() { return oqish; },
};
}
const k = avlodKeshi({ ali: ["Non"], malika: ["Kitob"] });
k.royxat("ali", "?limit=10");
k.royxat("ali", "?limit=10");
console.log("Malika:", k.royxat("malika", "?limit=10"));
console.log("o'qish:", k.oqish);
k.yarat("ali", "Sut");
console.log("Ali:", k.royxat("ali", "?limit=10"));
console.log("Malika:", k.royxat("malika", "?limit=10"));
console.log("o'qish:", k.oqish);Konsolda:
Malika: [ 'Kitob' ]
o'qish: 2
Ali: [ 'Non', 'Sut' ]
Malika: [ 'Kitob' ]
o'qish: 3Ikki marta o'qigan Ali — bitta ombor o'qishi, Malika — o'zi alohida (jami 2). Ali yozgach, uning avlodi 2 bo'ldi: yangi ro'yxat darhol ko'rindi (3-o'qish). Malika'ning keshi tegilmadi — uning avlodi o'zgarmagan. CacheInterceptor dagi uch muammo — eskirish, aralashuv, kalitlarni qidirish — bu yerda yo'q. Kanondagi KeshliOmbor xuddi shu, faqat Redis'da (INCR, TTL bilan).
9. Loyiha qadami: o'zgarish yo'q — va nega
vazifalar-api o'zgarmaydi: kesh 27-qismdan beri KeshliOmbor da (REDIS_URL berilsa, OmborModule uni Postgres/Prisma ombori ustiga o'raydi). CacheModule kanon tajribasida sinaldi va loyihaga kirmadi — «Kanon qarori» bo'limidagi jadval sabablari bilan.
O'z loyihangizda kichik tekshiruv: REDIS_URL bilan ishga tushiring, GET /v1/vazifalar ni ikki marta so'rang, keyin PATCH bilan bitta vazifani belgilang va yana GET. Ro'yxat darhol yangi bo'lishi kerak — avlod kaliti ishladi. Redis'da (redis-cli KEYS 'vz:*') vz:1:avlod kalitini ko'rasiz.
10. Real ishda
CacheModule— Nest loyihalarida ommaviy, kam o'zgaradigan ma'lumot uchun keng ishlatiladi: sozlamalar, kataloglar, tashqi API javoblari.- Kesh tufayli ma'lumot sizishi — haqiqiy hodisalarning tanish sababi: shaxsiy sahifa umumiy kalit bilan keshlangan. Review'da "bu marshrut foydalanuvchiga bog'liqmi?" savoli majburiy.
- TTL birligi — eski maqolalarda
ttlsoniyada yozilgan misollar uchraydi; ko'chirishdan oldin o'rnatilgan versiya hujjatini tekshiring. Hozirgicache-manager7 da — millisekund. - Intervyu: "Nest'da keshni qanday qilasiz?", "
CacheInterceptorkaliti nima?", "invalidatsiyani qanday hal qilasiz?".
Xulosa
CacheModule.register/registerAsync+ Keyv omborlari (xotira yoki@keyv/redis); TTL — millisekund.@Inject(CACHE_MANAGER)— qo'ldaget/set/del(cache-aside).CacheInterceptor— GET javobi, kalit = URL; yozuvdan keyin eskiradi, invalidatsiya — har URL qo'lda.- Xotira ombori havolani saqlaydi — lokal natija Redis'dagidan farq qilishi mumkin.
- URL kaliti foydalanuvchini bilmaydi — shaxsiy ma'lumot sizadi.
- Kanon: ombor qatlamidagi
KeshliOmbor— egasi + avlod kaliti, yozuvda bittaINCR.
Keyingi dars: Rejalashtirish: @nestjs/schedule — vaqt bo'yicha ishlarni (cron, interval) Nest ichida bajaramiz.
Manbalar
- NestJS hujjati — Caching (
CacheModule,CacheInterceptor,@CacheKey,@CacheTTL, Keyv omborlari): https://docs.nestjs.com/techniques/caching cache-manager(Keyv bilan): https://github.com/jaredwray/cacheable/tree/main/packages/cache-manager- Keyv —
@keyv/redis: https://keyv.org/docs/storage-adapters/redis/ - Kanon (IlmHamroh, 2026-10-28):
CacheInterceptortajribasi Redis bilan (@nestjs/cache-manager12.0.1,cache-manager7.2.9,@keyv/redis6.1.0) — URL kaliti, eskirgan javob,del, prefikssiz kalitlar, HIT 1.17 / MISS 1.96 ms;KeshliOmbor— 27-qism. Xotira ombori bilan takror (havola va nusxa variantlari), foydalanuvchilar aralashuvi va tajriba kodining tip tekshiruvi — biz ishga tushirdik (2026-11-02).
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!