9.9-bob: Caching strategiyalari, scalability, load balancing
9-QISM — Arxitektura va ilg'or backend · 9-mavzu
1. Kirish va motivatsiya
Endi tizimni tez va katta yukka chidamli qiladigan uchta asosiy mavzuni — caching strategiyalari (chuqur — 8.15 davomi), scalability (masshtablash), load balancing (yuk taqsimlash) — o'rganamiz. Bu — "ilovam 100 foydalanuvchiga ishlaydi, lekin 100000 ga ishlaydimi?" degan savolning javobi. System Design intervyularining (15) yuragi, va real production tizimining hayot-mamot masalasi: sayt sekin yuklansa — foydalanuvchi ketadi; server yiqilsa — biznes to'xtaydi; yuk ko'tarilsa va tizim chidamasa — falokat (Black Friday, viral bo'lish).
Uchchasi bir maqsadga xizmat qiladi — tizim ko'p so'rovni tez va ishonchli ko'tarishi: caching (takror ishni qilmaslik — tayyor natijani berish — eng katta tezlik yutug'i), scalability (yuk ko'tarilganda tizimni o'stirish — ko'proq resurs), load balancing (yukni ko'p server orasida taqsimlash). 8.15'da Redis cache'ni texnik ko'rdik; endi strategiya darajasida (qaysi cache naqshi, qachon) va butun tizim masshtabini (DB, server, CDN) ko'ramiz.
Bu bob: caching strategiyalari (cache-aside, write-through, write-behind, read-through — chuqur), cache qatlamlari (in-process/Redis/CDN), invalidation (eng qiyin), scalability (vertikal vs gorizontal), DB masshtab (replication, sharding), load balancing (algoritmlar — round-robin, ...), va bottleneck. Bu bob 8.15 (Redis), 6.15 (connection pool), 6.10 (indeks), 10 (DevOps) bilan bog'liq. Bu — katta, tez, chidamli tizim qurish bilimi (senior+).
O'xshatish: bu mavzular — restoran kengayishi. Boshda kichik kafe (1 server) — kam mijoz. Mashhur bo'ldi (yuk oshdi): caching — eng ko'p buyuriladigan taomlarni oldindan tayyorlab qo'yish (har safar noldan pishirmaslik — tez); vertikal scaling — kattaroq oshxona, kuchliroq pech (bir bino — chegarasi bor); gorizontal scaling — boshqa filiallar ochish (ko'p bino — cheksiz); load balancing — mijozlarni filiallarga taqsimlash (administrator — "bu filial band, u yoqqa boring"); DB sharding — mijozlarni hududga bo'lish (Toshkent filiali, Samarqand filiali — har biri o'z mijozlari). Bir kafedan tarmoqgacha o'sish — rejalashtirilgan masshtab.
Nega muhim?
- Tezlik — caching (sekin sayt = ketgan mijoz).
- Katta yuk — scalability (100 100000 foydalanuvchi).
- Ishonchlilik — load balancing (server yiqilsa, boshqasi).
- System Design — intervyu (15) va real production yuragi.
2. Nazariya — chuqur tushuntirish
2.1. Nega caching (eng katta tezlik yutug'i)
CACHING — tayyor natijani saqlash (takror ishni qilmaslik):
DB so'rov: 50ms │ hisoblash: 200ms │ tashqi API: 500ms
Cache (Redis): 1ms │ in-process: 0.01ms
Cache = 50-500x tez (eng oson, eng katta tezlik yutug'i)
NIMA KESHLASH (8.15: 2.12):
Tez-tez o'qiladi + kam o'zgaradi (katalog, config, profil)
Og'ir hisoblash natijasi (aggregation, hisobot)
Tashqi API javobi (kvota/sekin)
Tez o'zgaradigan (balans, real-time); maxfiy (ehtiyot — 14)Caching (eng katta tezlik yutug'i): tayyor natijani saqlash (takror ishni qilmaslik). DB (50ms) / hisoblash (200ms) / tashqi API (500ms) cache (Redis 1ms, in-process 0.01ms) — 50-500x tez. Nima keshlash (8.15: 2.12): tez-tez o'qiladi + kam o'zgaradi (katalog, config), og'ir hisoblash, tashqi API. Keshlamaslik: tez o'zgaradigan (balans), maxfiy (14). Caching — eng oson, eng samarali optimizatsiya (avval shuni sina — masshtabdan oldin).
2.2. Caching strategiyalari (4 asosiy)
┌──────────────────┬─────────────────────────────────────────┐
│ Cache-Aside │ App: cache tekshir miss DB cache'ga │
│ (lazy) │ eng keng; faqat kerakli keshlanadi │
│ │ birinchi so'rov sekin (miss); stale │
├──────────────────┼─────────────────────────────────────────┤
│ Read-Through │ Cache o'zi DB'dan yuklaydi (app emas) │
│ │ app oddiy; cache kutubxona kerak │
├──────────────────┼─────────────────────────────────────────┤
│ Write-Through │ Yozish: cache + DB BIRGA (sinxron) │
│ │ doim mos; yozish sekinroq │
├──────────────────┼─────────────────────────────────────────┤
│ Write-Behind │ Yozish: cache keyin DB (async) │
│ (write-back) │ tez yozish; cache yiqilsa — yo'qoladi│
└──────────────────┴─────────────────────────────────────────┘4 caching strategiyasi: cache-aside (lazy — app cache tekshiradi, miss DB cache'ga — eng keng, 8.15: 2.4); read-through (cache o'zi DB'dan yuklaydi — app oddiy); write-through (yozish: cache+DB birga — doim mos, lekin sekin); write-behind (yozish: cache keyin DB async — tez, lekin cache yiqilsa yo'qoladi). Eng keng — cache-aside (oddiy, moslashuvchan); write-through (izchillik muhim); write-behind (tez yozish, xavf). Tanlov: o'qish/yozish naqshiga.
Har strategiya — chuqurroq (qachon ishlatish)
Yuqoridagi to'rt strategiya + yana ikkitasi (refresh-ahead, stale-while-revalidate) — real tizimda uchraydi. Har birining o'z o'rni bor:
1) Cache-aside (lazy loading) — eng keng tarqalgan. Ilova cache'ni o'zi boshqaradi: o'qishda avval cache'ni tekshiradi, miss bo'lsa DB'dan oladi va cache'ga yozadi. Keshlanadigan narsani ilova tanlaydi (faqat so'ralgan ma'lumot keshlanadi — xotira tejaladi). Kamchilik: birinchi so'rov har doim sekin (cache miss); cache va DB alohida boshqariladi (izchillik ilova zimmasida). Deyarli barcha loyihada standart tanlov.
2) Read-through — cache DB oldida "vositachi" (proxy) sifatida turadi. Ilova faqat cache'dan so'raydi; miss bo'lsa cache o'zi DB'dan yuklaydi va qaytaradi. Ilova kodi soddalashadi (DB mantiqi cache qatlamida), lekin buni qo'llab-quvvatlaydigan cache kutubxonasi yoki abstraktsiya kerak. Ma'lumo naqshi cache-aside bilan bir xil, farqi — kim yuklaydi (cache vs ilova).
3) Write-through — yozish cache va DB'ga bir vaqtda (sinxron) boradi. Cache har doim yangi (o'qishda stale yo'q). Kamchilik: har yozish ikki operatsiya (sekinroq); kam o'qiladigan ma'lumot keshlanib, xotira behuda ketishi mumkin. Izchillik muhim bo'lgan (kesh va DB doim mos bo'lishi shart) tizimlarda.
4) Write-behind (write-back) — yozish avval faqat cache'ga (tez qaytadi), DB'ga keyinroq navbat (batch) orqali async yoziladi. Juda tez yozish, DB'ga yukni tekislaydi (masalan minglab yozishni bittalab emas, guruh bilan). Xavf: cache yozilib DB'ga o'tmasdan turib cache yiqilsa — ma'lumot yo'qoladi (durability yo'q). Yozish-og'ir, biroz yo'qotishga chidamli tizimlarda (metrika, hisoblagich, log).
5) Refresh-ahead — cache TTL tugashidan oldin (masalan 80% vaqt o'tganda) fon jarayoni ma'lumotni oldindan yangilaydi. Foydalanuvchi har doim keshdagi (issiq) ma'lumotni oladi, hech qachon miss'ga urilmaydi (latency barqaror). Kamchilik: kimga kerak bo'lishini oldindan taxmin qilish qiyin (noto'g'ri taxmin behuda yangilash). Bashorat qilinadigan, tez-tez so'raladigan issiq ma'lumot uchun.
6) Stale-while-revalidate — cache eskirsa ham darrov eski (stale) qiymat qaytariladi, fonda yangi qiymat yuklab qo'yiladi. Foydalanuvchi hech qachon kutmaydi (latency 0 ga yaqin), yangilanish fonda. HTTP standarti (Cache-Control: stale-while-revalidate) va CDN'lar buni qo'llaydi. Biroz eskilikka chidasa bo'ladigan (yangilik lenta, katalog) joyda ideal. Kesh stampede (2.4a) muammosini ham yumshatadi.
STRATEGIYA TANLASH (o'qish/yozish naqshiga qarab):
O'QISH-OG'IR (katalog, profil, 90% o'qish):
cache-aside yoki read-through (+ TTL invalidation)
issiq ma'lumot: refresh-ahead / stale-while-revalidate (latency barqaror)
YOZISH-OG'IR + izchillik muhim (balans, buyurtma holati):
write-through (kesh doim mos)
YOZISH-OG'IR + tezlik muhim, biroz yo'qotishga chidamli (metrika, hisoblagich):
write-behind (batch DB — tez, DB yukini tekislaydi)Strategiyalarni chuqurroq: cache-aside — ilova cache'ni o'zi boshqaradi (birinchi so'rov sekin, keyingilar tez — standart tanlov); read-through — cache DB oldida proxy (ilova soddaroq, cache kutubxonasi kerak); write-through — yozish cache+DB sinxron (doim mos, yozish sekin); write-behind — yozish avval cache, DB'ga async batch (juda tez, cache yiqilsa yo'qoladi — durability yo'q); refresh-ahead — TTL tugashidan oldin fon yangilaydi (foydalanuvchi hech qachon miss'ga urilmaydi — latency barqaror); stale-while-revalidate — eskirsa ham darrov eski qiymat, fonda yangilaydi (latency ~0 — HTTP/CDN standarti). Tanlov naqshga: o'qish-og'ir cache-aside/read-through (issiq refresh-ahead/SWR); yozish-og'ir+izchillik write-through; yozish-og'ir+tezlik write-behind.
2.3. Cache qatlamlari (ko'p daraja)
CACHE QATLAMLARI (mijozdan DB'gacha — har daraja tezroq):
Brauzer cache (mijoz) ── eng tez (tarmoq yo'q)
▼
CDN (edge — geografik yaqin) ── statik (rasm, JS, CSS)
▼
Load balancer / reverse proxy cache (Nginx)
▼
Application cache (in-process — eng tez server'da)
▼
Distributed cache (Redis — 8.15 — ko'p server bo'lishadi)
▼
Database (eng sekin — oxirgi chora)
Har qatlam DB yukini kamaytiradi (so'rov yuqorida to'xtasa — tez)Cache qatlamlari (ko'p daraja — har biri tezroq): brauzer (mijoz — eng tez), CDN (edge — geografik yaqin — statik: rasm/JS/CSS), reverse proxy (Nginx), in-process (server xotirasi — eng tez server'da), distributed (Redis — ko'p server bo'lishadi — 8.15), DB (oxirgi). So'rov yuqorida to'xtasa (CDN/cache) — DB'gacha bormaydi (tez, yuk kam). CDN — statik fayllar uchun eng katta yutuq (rasm — 8.24, foydalanuvchiga yaqin). Multi-layer cache — to'liq tezlik strategiyasi.
HTTP caching (brauzer + CDN qatlami)
Eng yuqori — brauzer va CDN qatlami — HTTP protokolining o'z keshlash mexanizmiga tayanadi. Bu qatlam server kodini o'zgartirmasdan, faqat javob sarlavhalari (header) orqali boshqariladi. To'g'ri sozlansa, so'rov serverga umuman kelmaydi (yoki juda arzon "o'zgardimi?" tekshiruviga aylanadi).
Cache-Control — asosiy sarlavha, javobni kim va qancha keshlashi mumkinligini aytadi:
public— istalgan kesh (brauzer, CDN) saqlashi mumkin;private— faqat brauzer (CDN emas — shaxsiy ma'lumot).max-age=31536000— necha soniya yangi hisoblanadi (bu yerda 1 yil — statik fayl).no-cache— keshlash mumkin, lekin har safar serverdan "o'zgardimi?" deb tasdiqlab olish shart.no-store— umuman keshlanmasin (maxfiy ma'lumot — bank balansi).immutable— bu fayl hech qachon o'zgarmaydi (brauzer tasdiqlashga ham bezovta qilmaydi).
Validatsiya — ETag va Last-Modified (shartli so'rov, 304). Statik fayllarga uzoq max-age beriladi, lekin dinamik ma'lumot uchun boshqa yondashuv kerak: ma'lumot o'zgarmagan bo'lsa uni qayta yubormaslik. Server javobga ETag (kontent "barmoq izi" — hash) yoki Last-Modified (oxirgi o'zgarish vaqti) qo'yadi. Keyingi so'rovda brauzer bu qiymatni If-None-Match (ETag uchun) yoki If-Modified-Since (sana uchun) sarlavhasida qaytaradi. Agar o'zgarmagan bo'lsa, server 304 Not Modified (bo'sh tana — body yo'q) qaytaradi — brauzer o'z keshidagini ishlatadi. Bu tarmoq trafigini keskin kamaytiradi (katta JSON o'rniga bo'sh 304).
HTTP CACHE OQIMI (dinamik ma'lumot — ETag):
1-so'rov: GET /api/product/1
200 OK ETag: "abc123" {katta JSON} (brauzer keshlaydi)
2-so'rov: GET /api/product/1 If-None-Match: "abc123"
304 Not Modified (BO'SH — brauzer keshdan oladi, tarmoq tejaldi)
(agar ma'lumot o'zgargan bo'lsa)
200 OK ETag: "def456" {yangi JSON}HTTP caching (brauzer + CDN qatlami — sarlavhalar orqali, kodsiz):
Cache-Control—public/private(kim keshlaydi),max-age(qancha yangi),no-cache(keshla, lekin tasdiqla),no-store(umuman keshlama — maxfiy),immutable(o'zgarmaydi). Validatsiya:ETag(kontent hash) yokiLast-Modified(vaqt) — brauzer keyingi so'rovdaIf-None-Match/If-Modified-Sincebilan qaytaradi; o'zgarmagan bo'lsa server304 Not Modified(bo'sh tana) — trafik keskin kamayadi. Statik fayl uzoqmax-age+immutable(versiyalangan URL bilan); dinamikETag+304. Server kodini o'zgartirmay eng katta tezlik yutug'i (so'rov serverga kelmaydi yoki arzon 304).
2.4. Cache invalidation (eng qiyin muammo)
"Eng qiyin 2 narsa: cache invalidatsiya va nomlash" (mashhur ibora)
INVALIDATION — eski cache'ni qachon o'chirish (aks holda stale):
- TTL (time-to-live): vaqt o'tib avtomatik eskirish (oddiy — 8.15)
- O'zgarganda del: update/delete cache.del (aniq — 8.15: 2.5)
- Tag/pattern: bog'liq keshlarni birga (mahsulot o'zgardi ro'yxat ham)
- Write-through: yozishda yangilash (doim mos — 2.2)
STALE muammo: eski ma'lumot ko'rsatish (cache yangilanmagan)
TTL (qisqa — tez yangilanadi) vs hit rate (uzun — ko'p kesh) balansiCache invalidation (eng qiyin — "cache invalidatsiya va nomlash"): eski cache'ni qachon o'chirish (aks holda stale — eski ma'lumot). Usullar: TTL (vaqt — oddiy — 8.15), o'zgarganda del (aniq — 8.15: 2.5), tag/pattern (bog'liq keshlar birga — mahsulot o'zgardi ro'yxat keshi ham), versioning (kalitga versiya qo'shish:
product:v2:123— eski versiyani o'chirmasdan yangisiga o'tish, hech qachon stale o'qilmaydi), write-through (yozishda). Balans: TTL qisqa (tez yangilanadi, lekin kam hit) vs uzun (ko'p hit, lekin stale xavfi). Invalidation — caching'ning eng nozik qismi (noto'g'ri eski ma'lumot yoki kam tezlik).
2.4a. Cache muammolari: stampede, penetration, avalanche
Cache faqat foyda emas — noto'g'ri qurilsa xavfli. Uch klassik muammo bor, uchchasi ham keshdagi bo'shliq (miss) tufayli birdaniga DB'ga ortiqcha yuk tushishiga olib keladi. Har biriga alohida yechim bor.
┌─────────────────┬──────────────────────────┬───────────────────────────┐
│ MUAMMO │ SABAB │ YECHIM │
├─────────────────┼──────────────────────────┼───────────────────────────┤
│ Cache stampede │ Issiq kalit TTL tugadi │ lock/mutex (bittasi │
│ (thundering │ minglab so'rov birdan │ yuklaydi); probabilistic │
│ herd) │ DB'ga (DB qulaydi) │ early expiration; SWR │
├─────────────────┼──────────────────────────┼───────────────────────────┤
│ Cache │ Yo'q kalit so'raladi │ null (bo'sh) natijani │
│ penetration │ (cache'da yo'q, DB'da │ qisqa TTL bilan keshlash; │
│ │ yo'q) har safar DB │ bloom filter (bor/yo'q) │
├─────────────────┼──────────────────────────┼───────────────────────────┤
│ Cache avalanche │ Ko'p kalit BIR VAQTDA │ TTL jitter (tasodifiy │
│ │ eskiradi DB'ga to'lqin │ qo'shimcha); TTL'larni │
│ │ (yoki Redis butun yiqildi)│ tarqatish; Redis HA │
└─────────────────┴──────────────────────────┴───────────────────────────┘Cache stampede (thundering herd — "gala hujumi"). Bitta juda mashhur kalit (masalan bosh sahifa ma'lumoti) TTL bilan eskiradi. Aynan shu lahzada minglab so'rov keladi — hammasi miss ko'radi va bir vaqtda DB'ga yuguradi. DB bitta so'rov o'rniga minglab bir xil so'rovni ko'taradi va qulaydi. Yechimlar: (a) lock/mutex — birinchi so'rov "lock" oladi va DB'dan yuklaydi, qolganlar biroz kutib keshdan oladi (Misol 8); (b) probabilistic early expiration — TTL tugashidan biroz oldin, tasodifiy ravishda, bitta so'rovga "sen yangila" deb qaror qilinadi (qolganlar hali issiq keshni oladi); (c) stale-while-revalidate 2.2-bob — eski qiymat qaytariladi, yangilanish fonda.
Cache penetration (kirib o'tish). Mavjud bo'lmagan ma'lumot so'raladi (masalan id=-1 yoki tasodifiy ID). Cache'da yo'q DB'ga boradi DB'da ham yo'q hech narsa keshlanmaydi. Keyingi safar yana o'sha yo'q ID so'ralsa, yana DB'ga boradi. Bu — hujum vektori bo'lishi mumkin (hujumchi mavjud emas ID'lar bilan DB'ni ko'mib tashlaydi). Yechimlar: (a) null caching — "yo'q" natijani ham qisqa TTL bilan keshlash (SET id:-1 "__NULL__" EX 60), keyingi so'rov DB'ga bormaydi; (b) bloom filter — juda ixcham ehtimollik strukturasi "bu ID umuman bormi?" degan savolga tez javob beradi (yo'q bo'lsa DB'ga umuman bormaymiz).
Cache avalanche (ko'chki). Ko'p kalit bir vaqtda eskiradi (masalan hammasi bir paytda yuklangan va bir xil TTL bergan) — natijada bir lahzada butun yuk DB'ga tushadi. Yoki og'irroq holat: Redis'ning o'zi yiqiladi va barcha so'rov to'g'ridan DB'ga o'tadi. Yechimlar: (a) TTL jitter — sobit TTL o'rniga tasodifiy qo'shimcha (300 + random(0..60) soniya) — eskirish vaqtlari tarqaladi; (b) muhim keshlarni oldindan qizdirish (cache warming) — tizim ishga tushganda; (c) Redis'ni HA qilish (cluster/sentinel — 2.13) — bitta Redis yiqilsa ham to'liq halokat bo'lmaydi.
Cache muammolari (3 klassik): stampede (thundering herd — issiq kalit TTL tugadi minglab so'rov birdan DB'ga DB qulaydi; yechim: lock/mutex, probabilistic early expiration, stale-while-revalidate); penetration (yo'q kalit so'raladi har safar DB, hujum vektori; yechim: null natijani qisqa TTL bilan keshlash, bloom filter); avalanche (ko'p kalit bir vaqtda eskiradi yoki Redis yiqiladi DB'ga to'lqin; yechim: TTL jitter — tasodifiy qo'shimcha, cache warming, Redis HA). Uchchasining ildizi bir — keshdagi bo'shliq birdaniga DB'ga urilishi. Production cache'da bu himoyalar shart (aks holda cache foyda o'rniga xavf).
2.5. Scalability: vertikal vs gorizontal
VERTIKAL (scale up) — kuchliroq server (ko'proq CPU/RAM):
Oddiy (kod o'zgarmaydi); darrov
Chegara bor (eng kuchli server ham cheklangan); qimmat; SPOF
GORIZONTAL (scale out) — ko'proq server (nusxalar):
Deyarli cheksiz (server qo'shaver); chidamli (biri yiqilsa, boshqa)
Murakkab (load balancer, stateless, DB masshtab)
┌──────────────────┬─────────────────────────┐
│ VERTIKAL │ GORIZONTAL │
│ 1 server, kuchli │ ko'p server, oddiy │
│ oson, chegarali │ murakkab, cheksiz │
└──────────────────┴─────────────────────────┘
Boshda vertikal (oddiy); o'sganda gorizontal (cheksiz)Scalability — vertikal vs gorizontal: vertikal (scale up — kuchliroq server: ko'proq CPU/RAM — oddiy, darrov, lekin chegara bor + qimmat + SPOF); gorizontal (scale out — ko'proq server nusxalari — deyarli cheksiz, chidamli, lekin murakkab: load balancer, stateless, DB masshtab). Boshda vertikal (oddiy — server kuchaytir); o'sganda gorizontal (cheksiz). Gorizontal uchun ilova stateless bo'lishi kerak 2.6-bob. Modern bulut — gorizontal (auto-scaling — 10). Tanlov: oddiy/chegarali vs murakkab/cheksiz.
2.6. Stateless (gorizontal masshtab sharti)
STATELESS — server so'rovlar orasida HOLAT saqlamasligi:
STATEFUL (server xotirasida holat):
- Sessiya server xotirasida boshqa server'da yo'q (load balancer muammo)
- Bir foydalanuvchi doim bir server'ga bog'lanishi kerak (sticky)
STATELESS (holat tashqarida):
- Sessiya Redis 8.15-bob / JWT (8.9 — tokenda holat)
- Fayl S3 5.11-bob, cache Redis
- Har server bir xil (har so'rovni istalgan server ko'taradi)
Gorizontal masshtab uchun STATELESS majburiy (har server teng)Stateless (gorizontal masshtab sharti): server so'rovlar orasida holat saqlamasligi. Stateful (holat server xotirasida — sessiya) boshqa server'da yo'q (load balancer muammo — sticky kerak). Stateless (holat tashqarida — sessiya Redis/JWT — 8.9, 8.15; fayl S3 — 5.11; cache Redis) har server bir xil (istalgan server har so'rovni ko'taradi). Gorizontal masshtab uchun majburiy (server xotirasiga ishonmaslik). Bu — masshtablanadigan dizaynning asosi.
2.7. DB masshtab: read replica (replication)
DB ko'pincha BOTTLENECK (server oson, DB qiyin masshtab)
READ REPLICA (replication) — o'qish uchun nusxalar:
Yozish ── PRIMARY (master) ── replicate ── REPLICA 1 (o'qish)
└── REPLICA 2 (o'qish)
O'qish masshtab (ko'p replica — o'qish-og'ir ilova — 90% o'qish)
Yozish bir joyda (primary); replikatsiya kechikishi (eventual — 9.7)
O'qish replica'lardan, yozish primary'ga (read-heavy uchun ideal)DB read replica (replication — DB masshtab): DB ko'pincha bottleneck (server oson, DB qiyin). Read replica: yozish primary replikatsiya replica'lar (o'qish). O'qish replica'lardan (ko'p replica — o'qish masshtab — aksariyat ilova 90% o'qish), yozish primary'ga. Replikatsiya kechikishi (eventual consistency — replica biroz orqada — 9.7: 2.7). Read-heavy ilova uchun ideal (o'qishni tarqatish). Connection pool 6.15-bob + cache 8.15-bob bilan birga.
2.8. DB masshtab: sharding (partitioning)
SHARDING — DB'ni bo'laklarga bo'lish (har shard — qism ma'lumot):
Bir katta DB ── Shard 1 (A-M foydalanuvchilar)
├── Shard 2 (N-Z)
└── Shard 3 (...)
(shard kaliti: userId, hudud, hash — qaysi shard)
Yozish ham masshtab (har shard mustaqil — replica yozishni masshtablamaydi)
Juda katta ma'lumot (bir DB sig'maydi)
Murakkab (cross-shard query qiyin; rebalancing; JOIN yo'q)
Sharding — OXIRGI chora (juda katta; replica+cache yetmaganda)Sharding (partitioning — DB bo'laklarga): har shard — qism ma'lumot (shard kaliti: userId/hudud/hash qaysi shard). Yozish ham masshtab (har shard mustaqil — replica faqat o'qishni masshtablaydi — 2.7); juda katta ma'lumot (bir DB sig'maydi). Lekin murakkab: cross-shard query qiyin (JOIN yo'q), rebalancing. Sharding — oxirgi chora (juda katta tizim; cache+replica+vertikal yetmaganda — masalan Instagram, Uber masshtabi). Ko'p loyiha sharding'ga yetmaydi (cache+replica yetadi). Murakkablik yuqori.
Partitioning va connection pooling — bog'liq tushunchalar. Partitioning — bitta jadvalni bir DB ichida qismlarga bo'lish (masalan orders jadvalini oy bo'yicha: orders_2026_01, orders_2026_02). Sharding'dan farqi: partitioning bir DB serverida qoladi (masshtab emas, boshqaruv/query optimizatsiyasi uchun — eski qismlarni o'chirish oson, so'rov faqat kerakli qismni o'qiydi). Sharding esa qismlarni turli serverlarga tarqatadi. Connection pooling 6.15-bob — masshtabning yashirin bottleneck'i: har DB ulanishi qimmat (DB'da xotira + jarayon). Ko'p ilova nusxasi (gorizontal — 2.5) bo'lsa, har biri o'z pool'ini ochadi va DB'ning ulanish limiti (masalan Postgres'da ~100) tez to'ladi. Yechim: har nusxada kichik pool + tashqi pooler (masalan PgBouncer) — minglab ilova ulanishini o'nlab DB ulanishiga siqadi.
2.13. Redis chuqur (cache dvigateli)
Redis (8.15'da texnik ko'rilgan) — distributed cache qatlamining eng keng ishlatiladigan dvigateli. Uni to'liq egallash uchun to'rt jihatni bilish kerak: qanday ma'lumot turlari cache'da qulay, eviction (xotira to'lganda nima o'chadi), persistence (qayta ishga tushganda ma'lumot qoladimi), va HA (bitta Redis yiqilsa nima bo'ladi).
Ma'lumot turlari (cache uchun). Redis — shunchaki kalit-qiymat emas, boy strukturalar beradi: String (oddiy qiymat, JSON, hisoblagich — INCR); Hash (obyekt maydonlari — bir foydalanuvchi profilining alohida maydonlarini yangilash); List (navbat, oxirgi N element); Set (unikal to'plam — teg, ko'rilgan mahsulotlar); Sorted Set (ball bilan tartiblangan — leaderboard, "eng ko'p sotilgan", vaqt oynasi); Bitmap/HyperLogLog (ixcham hisoblash — unikal tashrif taxminiy soni). To'g'ri tur tanlash — kesh mantiqini soddalashtiradi (masalan reyting uchun Sorted Set — o'zi tartiblaydi).
Eviction policy (xotira to'lganda). maxmemory limiti to'lganda Redis nimani o'chirishni tanlaydi:
noeviction— hech narsa o'chmaydi, yangi yozish xato beradi (cache emas, doimiy saqlash uchun).allkeys-lru— eng uzoq ishlatilmagan kalit o'chadi (Least Recently Used — umumiy cache uchun eng keng tanlov).allkeys-lfu— eng kam ishlatilgan (Least Frequently Used — issiq/sovuq naqsh aniq bo'lganda yaxshiroq).volatile-ttl/volatile-lru— faqat TTL o'rnatilgan kalitlar orasidan o'chiradi.
Cache sifatida ishlatilganda odatda allkeys-lru yoki allkeys-lfu (kesh to'lganda eng foydasiz kalit ketadi — issiqlari qoladi).
Persistence (RDB vs AOF). Redis xotirada ishlaydi, lekin diskka saqlashi ham mumkin:
- RDB (snapshot) — vaqti-vaqti bilan butun ma'lumotning nusxasi diskka yoziladi. Ixcham, qayta yuklash tez; lekin oxirgi snapshotdan keyingi o'zgarishlar yo'qolishi mumkin (masalan 5 daqiqa).
- AOF (Append Only File) — har yozish operatsiyasi jurnalga qo'shiladi. Ishonchliroq (deyarli hech narsa yo'qolmaydi), lekin fayl kattaroq, qayta yuklash sekinroq.
Sof cache uchun persistence umuman shart emas (yiqilsa DB'dan qayta to'ladi). Sessiya/navbat kabi muhim ma'lumot uchun AOF (yoki AOF+RDB) yoqiladi.
HA — Sentinel va Cluster. Bitta Redis — SPOF (yiqilsa — cache avalanche, 2.4a). Ikki yechim: Sentinel — primary + replica'lar, Sentinel jarayoni primary yiqilishini kuzatadi va replica'ni avtomatik primary qiladi (failover — HA, lekin ma'lumot hali bir tugunga sig'adi). Cluster — ma'lumot 16384 "slot"ga bo'linib bir necha primary'ga tarqatiladi (Redis'ning o'z sharding'i — ham HA, ham gorizontal masshtab, ma'lumot bir serverga sig'maganda).
Distributed lock (Redlock). Ko'p ilova nusxasi (gorizontal — 2.5) bir vaqtda bitta resursga tegmasligi kerak bo'lsa (masalan stampede lock'i — Misol 8, yoki "bir vaqtda bitta cron"), taqsimlangan qulf kerak. Oddiy usul: SET lock:kalit token NX EX 10 (NX — faqat yo'q bo'lsa o'rnat, EX — avtomatik muddat, deadlock bo'lmasin). Qulfni faqat egasi ochishi uchun tokenni tekshirib o'chirish (Lua skript bilan atomik). Bir necha Redis tuguni bo'lganda ishonchliroq Redlock algoritmi qo'llaniladi (ko'pchilik tugundan qulf olinsa — muvaffaqiyat). Redlock murakkab va bahsli — ko'p holatda bitta Redis'dagi oddiy SET NX EX yetarli; Redlock faqat qulf yo'qolishi jiddiy zarar keltiradigan holatlarda.
Redis chuqur (cache dvigateli — 8.15): ma'lumot turlari — String (qiymat/hisoblagich
INCR), Hash (obyekt maydonlari), List (navbat), Set (unikal), Sorted Set (leaderboard — o'zi tartiblaydi), HyperLogLog (unikal taxminiy); eviction (xotira to'lganda) —allkeys-lru(eng uzoq ishlatilmagan — umumiy cache),allkeys-lfu(eng kam ishlatilgan),noeviction(xato); persistence — RDB (snapshot — ixcham, biroz yo'qotadi), AOF (har yozish jurnali — ishonchli, sekinroq), sof cache uchun shart emas; HA — Sentinel (primary+replica, avtomatik failover), Cluster (16384 slot — HA + gorizontal masshtab); distributed lock —SET NX EX(token bilan, Lua atomik ochish), ko'p tugun uchun Redlock (ko'pchilikdan qulf — murakkab, ko'pincha oddiySET NXyetadi). Cache uchun:allkeys-lrueviction + persistence'siz; muhim ma'lumot uchun AOF + Sentinel/Cluster.
2.9. Load balancing (yuk taqsimlash)
LOAD BALANCER — so'rovlarni ko'p server orasida taqsimlash:
Mijoz ── Load Balancer ── Server 1
├── Server 2
└── Server 3
ALGORITMLAR:
- Round-robin: navbat bilan (1,2,3,1,2,3 — oddiy, teng)
- Least connections: eng kam bandga (yuk asosida)
- IP hash: bir IP doim bir server (sticky — sessiya)
- Weighted: kuchli server'ga ko'proq (server qudratiga qarab)
Yuk taqsimlash + HA (biri yiqilsa, boshqasiga — health check 9.8)
Nginx, HAProxy, cloud LB (AWS ELB — 10)Load balancing (yuk taqsimlash): load balancer so'rovlarni ko'p server orasida taqsimlaydi. Algoritmlar: round-robin (navbat bilan — oddiy, teng), least connections (eng kam bandga — yuk asosida), IP hash (bir IP bir server — sticky/sessiya), weighted (kuchliga ko'proq). Yuk taqsimlash + HA (high availability — biri yiqilsa boshqasiga — health check 9.8: 2.10). Nginx/HAProxy/cloud LB (AWS ELB — 10). Gorizontal masshtab load balancer'siz ishlamaydi (so'rov qayerga borishini hal qiladi).
L4 vs L7, algoritmlar, sticky session, health check
L4 vs L7 (qaysi qatlamda ishlaydi). Load balancer OSI modelining ikki qatlamida ishlashi mumkin:
- L4 (transport — TCP/UDP) — faqat IP va port'ga qaraydi, paket ichini ochmaydi. Juda tez, arzon, protokolga befarq (har qanday TCP trafik). Lekin so'rov mazmuniga qarab qaror qila olmaydi.
- L7 (application — HTTP) — so'rovni to'liq o'qiydi: URL, sarlavha, cookie. Shuning uchun aqlliroq qaror qiladi:
/api/*bir guruh serverga,/images/*boshqasiga; cookie asosida sticky session; SSL terminatsiyasi; javob keshi. Sekinroq (so'rovni ochish kerak), lekin real veb ilova uchun odatda L7 (Nginx, HAProxy L7 rejimda) ishlatiladi.
Algoritmlar (to'liqroq). 2.9 jadvalidagilarga qo'shimcha:
- Round-robin — navbat bilan (1,2,3,1,2,3). Oddiy, serverlar teng quvvatli bo'lsa yaxshi.
- Weighted round-robin — kuchliroq serverga ko'proq (og'irlik: kuchli=3, zaif=1).
- Least connections — hozir eng kam aktiv ulanishga. So'rovlar turli davomiylikda bo'lganda round-robin'dan yaxshiroq (band serverga qo'shmaydi).
- Least response time — eng kam ulanish + eng tez javob beradigan serverga (eng aqlli, lekin o'lchash kerak).
- IP hash — mijoz IP'sidan hash doim bir server (sticky — cookie'siz sessiya yopishqoqligi).
Sticky session (yopishqoq sessiya). Agar ilova stateful bo'lsa (sessiya server xotirasida — 2.6), bir foydalanuvchi doim bir serverga borishi kerak. LB buni cookie yoki IP hash bilan ta'minlaydi. Bu — vaqtinchalik chora: server yiqilsa o'sha foydalanuvchilar sessiyasi yo'qoladi, masshtab notekis bo'ladi. To'g'ri yechim — stateless 2.6-bob: sessiyani Redis'ga chiqarish, sticky umuman kerak bo'lmaydi.
Health check (sog'liq tekshiruvi). LB har serverga davriy so'rov yuboradi (masalan GET /health — 9.8). Server javob bermasa yoki xato qaytarsa — LB uni "sog'lom emas" deb belgilaydi va yangi so'rov yubormaydi (avtomatik chetlab o'tadi). Server tuzalgach qayta qo'shadi. Bu — HA (high availability) ning yuragi: yiqilgan server foydalanuvchiga ko'rinmaydi. Ikki tur: passive (real so'rovlardagi xatolarni sanaydi) va active (maxsus health endpoint'ni davriy so'raydi).
Load balancing chuqur: L4 (transport — IP/port, tez, protokolga befarq) vs L7 (HTTP — URL/sarlavha/cookie o'qiydi, aqlli marshrutlash, SSL terminatsiya, sticky — real veb uchun); algoritmlar — round-robin (teng), weighted (kuchliga ko'p), least-connections (kam bandga — turli davomiylikda yaxshi), least-response-time (eng tez javobga — aqlli), ip-hash (IP bir server, sticky); sticky session (stateful uchun cookie/IP hash — vaqtinchalik, to'g'risi stateless 2.6); health check (LB
/healthso'raydi — javob bermasa chetlaydi — HA yuragi, active/passive). Real ilova: L7 + least-connections + active health check + stateless (sticky'siz).
2.10. Bottleneck (to'siq) topish
BOTTLENECK — tizimning eng sekin/cheklangan qismi (zanjir eng zaif halqasi)
Tartib (odatda):
1. DB (eng keng bottleneck — sekin query, indeks yo'q — 6.10)
2. Tashqi API (sekin, kvota)
3. CPU (og'ir hisoblash)
4. Tarmoq (latency)
5. Xotira
Optimizatsiya tartibi:
1. O'lcha (profiling — qaysi sekin? taxmin qilma)
2. Bottleneck'ni top (eng sekin qism)
3. Tuzat (cache, indeks, query, replica)
4. Qayta o'lcha
"Premature optimization is the root of all evil" (avval o'lcha — 8.15)Bottleneck (to'siq — tizimning eng sekin qismi — zanjir eng zaif halqasi). Odatda: DB (eng keng — sekin query, indeks yo'q — 6.10), tashqi API, CPU, tarmoq. Optimizatsiya tartibi: o'lcha (profiling — qaysi sekin? taxmin qilma) bottleneck top tuzat (cache/indeks/replica) qayta o'lcha. "Premature optimization is the root of all evil" — avval o'lcha, keyin optimallashtir (noto'g'ri joyni optimallashtirish — behuda). Eng katta yutuq — DB (indeks 6.10 + cache 8.15 + query 6.10).
Performance o'lchash: latency, throughput, percentile
"Sekin" — noaniq so'z. Masshtabni o'lchash uchun uch aniq metrika bor:
- Latency (kechikish) — bitta so'rov qancha vaqt oldi (ms). Foydalanuvchi his qiladigan tezlik.
- Throughput (o'tkazuvchanlik) — tizim soniyada nechta so'rov ko'tara oladi (RPS — requests per second). Masshtab sig'imi. Ikkovi bog'liq, lekin bir emas: tizim yuqori throughput'da ham har so'rovni tez ko'tarishi (past latency) mumkin — yoki throughput oshgani sari latency o'sib ketishi mumkin (navbat to'ladi).
Percentile — nega o'rtacha yolg'on gapiradi. Latency'ni o'rtacha (average) bilan o'lchash xatarli: 99 ta so'rov 10ms, bittasi 5000ms bo'lsa, o'rtacha ~60ms — "yaxshi" ko'rinadi, lekin ayrim foydalanuvchi 5 soniya kutdi. Shuning uchun percentile ishlatiladi:
- p50 (median) — so'rovlarning yarmi bundan tez (tipik tajriba).
- p95 — 95% so'rov bundan tez (ko'pchilik his qiladigan yomon holat).
- p99 — 99% bundan tez; qolgan 1% — "tail latency" (dumdagi kechikish). Katta masshtabda bu muhim: 1% ko'p foydalanuvchi degani, va bitta sahifa o'nlab ichki so'rov qilsa, deyarli har foydalanuvchi kamida bitta sekin ("p99") so'rovga uriladi.
1000 so'rov latency'si (ms), tartiblab:
p50 = 12ms yarmi bundan tez (tipik)
p95 = 45ms 95% bundan tez
p99 = 320ms 99% bundan tez (1% dum — 320ms+)
avg = 28ms o'rtacha (dumni yashiradi — YOLG'ON tinchlik)
SLO odatda percentile'da: "p99 < 200ms" (o'rtacha emas)Yuk testi (load testing — masalan k6, wrk, autocannon) throughput'ni oshirib borib, latency percentile'lari qachon buzilishini topadi — bu tizimning haqiqiy sig'imi.
Performance o'lchash: latency (bitta so'rov vaqti — foydalanuvchi hisi), throughput (soniyadagi so'rov — RPS, masshtab sig'imi), percentile — o'rtacha (avg) dumni yashiradi (yolg'on tinchlik), shuning uchun p50 (median — tipik), p95 (ko'pchilikning yomon holati), p99 (dum — tail latency, katta masshtabda muhim). SLO percentile'da beriladi ("p99 < 200ms" — o'rtacha emas). Yuk testi (k6/wrk) throughput'ni oshirib latency qachon buzilishini topadi — haqiqiy sig'im. Har o'zgarishdan keyin qayta o'lcha 2.10-bob.
2.11. Masshtab strategiyasi (tartib)
MASSHTAB QADAMLARI (arzondan qimmatga — tartib bilan):
1. O'lcha + optimallash (query, indeks — 6.10) — ARZON, katta yutuq
2. Caching (Redis, CDN — 8.15) — arzon, eng katta tezlik 2.1-bob
3. Vertikal scaling (kuchliroq server) — oddiy, chegarali 2.5-bob
4. Read replica (o'qish masshtab — 2.7) — read-heavy uchun
5. Gorizontal scaling + load balancer (2.5, 2.9) — cheksiz
6. Sharding (yozish masshtab — 2.8) — OXIRGI (juda katta)
Tartib bilan (1-2 ko'p loyihaga yetadi; 5-6 — kam loyiha)
"Avval oddiy/arzon yechim; murakkab — kerak bo'lganda"Masshtab strategiyasi (tartib — arzondan qimmatga): 1) o'lcha + optimallash (query/indeks — 6.10 — arzon, katta yutuq); 2) caching (Redis/CDN — arzon, eng katta tezlik — 2.1); 3) vertikal (oddiy, chegarali); 4) read replica (read-heavy — 2.7); 5) gorizontal + load balancer (cheksiz); 6) sharding (oxirgi — juda katta — 2.8). Tartib bilan (1-2 ko'p loyihaga yetadi; 5-6 kam loyiha — Instagram darajasi). Avval arzon/oddiy (optimallash+cache), keyin murakkab (kerak bo'lganda). Pragmatik masshtab.
2.14. CDN chuqur, auto-scaling va CAP bog'liqligi
CDN (Content Delivery Network — edge caching). CDN — dunyo bo'ylab tarqalgan edge (chekka) serverlar tarmog'i; kontentni foydalanuvchiga geografik yaqin nuqtadan beradi (Toshkentdagi foydalanuvchi Toshkent/yaqin edge'dan oladi — origin serverga Amerikagacha bormaydi). Bu latency'ni keskin kamaytiradi va origin yukini yengillashtiradi.
- Statik kontent (rasm, JS, CSS, video — 8.24) — CDN'ning klassik ishi: bir marta origin'dan olib, edge'da uzoq keshlaydi.
- Dinamik kontent — zamonaviy CDN'lar dinamik javobni ham qisqa muddatga (yoki
stale-while-revalidatebilan — 2.2) keshlashi, hatto edge'da kod ishga tushirishi (edge functions) mumkin. - Cache purge (invalidatsiya). Fayl o'zgarsa edge'dagi eski nusxani tozalash kerak. Ikki usul: (a) versiyalangan URL — fayl nomiga hash qo'shish (
app.a1b2c3.js) — yangi versiya = yangi URL, eski keshda qolaveradi, hech qachon tozalash shart emas (eng toza yechim, statik fayl uchun standart); (b) explicit purge — CDN API orqali muayyan URL yoki teg keshini majburan bo'shatish (dinamik kontent yoki shoshilinch tuzatish uchun).
Auto-scaling (avtomatik masshtab — 10-QISM cross-ref). Gorizontal masshtabning 2.5-bob qo'lda emas, avtomatik shakli: yuk ko'rsatkichi (CPU %, so'rov soni, navbat uzunligi) belgilangan chegaradan oshsa — tizim yangi ilova nusxasini avtomatik ishga tushiradi (scale out) va load balancer'ga qo'shadi; yuk tushsa — nusxalarni o'chiradi (scale in — xarajat tejaladi). Bu faqat stateless 2.6-bob ilovada ishlaydi (yangi nusxa darrov teng huquqli bo'lishi kerak). Batafsil (Kubernetes HPA, cloud auto-scaling guruhlari) — 10-QISM (DevOps).
CAP teoremasi bilan bog'liqlik (keyingi bob — 9.10 cross-ref). Masshtab uchun ma'lumotni ko'paytirdik (read replica — 2.7, sharding — 2.8, Redis cache) — ammo bir nechta nusxa bo'lishi bilan izchillik (consistency) savoli tug'iladi: replica primary'dan orqada qoladi (2.7 — replikatsiya kechikishi), cache DB'dan farq qilishi mumkin (stale — 2.4). Bu — CAP teoremasining mavzusi: tarmoq bo'linishi (partition) sharoitida tizim Consistency (izchillik) va Availability (mavjudlik) o'rtasida tanlashga majbur. Bu bobdagi replica/cache qarorlari aslida CAP muvozanatining amaliy ko'rinishi (masalan "eventual consistency" — replica biroz orqada, lekin tizim ishlayveradi). Nazariy asosini keyingi bobda 9.10-bob chuqur ko'ramiz.
CDN chuqur: dunyoga tarqalgan edge serverlar — kontentni foydalanuvchiga yaqin nuqtadan beradi (latency , origin yuki ); statik (rasm/JS/CSS — klassik, uzoq kesh), dinamik (qisqa kesh / SWR / edge functions); cache purge — versiyalangan URL (
app.a1b2c3.js— yangi versiya = yangi URL, tozalash shart emas — standart) yoki explicit API purge (dinamik/shoshilinch). Auto-scaling (10-QISM) — yuk oshsa avtomatik nusxa qo'shish (scale out), tushsa o'chirish (scale in — xarajat) — faqat stateless 2.6-bob ishlaydi. CAP bog'liqligi 9.10-bob — ko'p nusxa (replica/cache) izchillik savoli (stale, replikatsiya kechikishi) — bu CAP muvozanatining amaliy ko'rinishi (eventual consistency).
2.12. Best practices (caching/scale/LB)
CACHING:
Cache-aside (eng keng — 2.2); to'g'ri narsani keshlash (8.15: 2.12)
Invalidation (TTL + o'zgarganda del — 2.4); CDN statik 2.3-bob
Multi-layer (brauzer CDN Redis DB — 2.3)
SCALABILITY:
Avval o'lcha + optimallash + cache (arzon — 2.1, 2.11)
Stateless (gorizontal sharti — 2.6)
Vertikal read replica gorizontal sharding (tartib — 2.11)
LOAD BALANCING:
Load balancer + health check (HA — 2.9, 9.8)
Bottleneck o'lcha (taxmin emas — 2.10); DB birinchi (6.10)3. Sintaksis — tez ma'lumotnoma
CACHE STRATEGIYA 2.2-bob: cache-aside | read-through | write-through | write-behind | refresh-ahead | stale-while-revalidate
QATLAM 2.3-bob: brauzer CDN Nginx in-process Redis DB
HTTP 2.3-bob: Cache-Control (public/private/max-age/no-store/immutable) | ETag/Last-Modified 304
INVALIDATION 2.4-bob: TTL + del + tag + versioning
CACHE MUAMMO (2.4a): stampede (lock) | penetration (null cache/bloom) | avalanche (TTL jitter)
REDIS 2.13-bob: turlar (String/Hash/Sorted Set) | eviction (LRU/LFU) | persistence (RDB/AOF) | HA (Sentinel/Cluster) | lock (SET NX/Redlock)
SCALE 2.5-bob: vertikal (up) | gorizontal (out — stateless 2.6)
DB (2.7, 2.8): read replica (o'qish) | sharding (yozish/juda katta) | partitioning | connection pool 6.15-bob
LB 2.9-bob: L4 vs L7 | round-robin | weighted | least-conn | least-response | IP-hash | sticky | health check
PERF 2.10-bob: latency | throughput (RPS) | p50/p95/p99 (avg emas)
CDN 2.14-bob: edge | statik/dinamik | purge (versiyalangan URL / API)
TARTIB 2.11-bob: optimallash cache vertikal replica gorizontal sharding auto-scaling (10)4. Batafsil kod namunalari
Misol 1 — Cache-aside (eng keng — 2.2, 8.15)
@Injectable()
export class ProductService {
constructor(
@InjectRepository(Product) private repo: Repository<Product>,
@Inject(CACHE_MANAGER) private cache: Cache,
) {}
async bitta(id: string): Promise<Product> {
const kalit = `product:${id}`;
// 1. Cache tekshir
const keshda = await this.cache.get<Product>(kalit);
if (keshda) return keshda; // HIT (tez — 2.1)
// 2. Miss DB
const product = await this.repo.findOneBy({ id });
if (!product) throw new NotFoundException();
// 3. Cache'ga (keyingi safar tez)
await this.cache.set(kalit, product, 300000); // TTL 5 daqiqa (2.4)
return product;
}
async yangila(id: string, dto: any) {
const product = await this.repo.save({ id, ...dto });
await this.cache.del(`product:${id}`); // INVALIDATION (2.4)
await this.cache.del("products:all"); // bog'liq kesh (tag — 2.4)
return product;
}
}Misol 2 — Write-through (doim mos — 2.2)
// Write-through — yozish: cache + DB BIRGA (doim sinxron)
async yangilaWriteThrough(id: string, dto: any) {
const product = await this.repo.save({ id, ...dto }); // DB
await this.cache.set(`product:${id}`, product, 300000); // cache BIRGA (yangilash)
return product;
// Cache doim mos (keyingi o'qish — yangi); yozish sekinroq (2.2)
}Misol 3 — Tag-based invalidation (bog'liq keshlar — 2.4)
// Bog'liq keshlarni birga o'chirish (tag/pattern)
async mahsulotOzgartir(id: string, dto: any) {
const product = await this.repo.save({ id, ...dto });
// Shu mahsulot bilan bog'liq BARCHA keshni o'chir (pattern)
await this.cache.del(`product:${id}`); // bitta
// Redis pattern (kategoriya ro'yxati, qidiruv — bog'liq)
const keys = await this.redis.keys(`products:category:${product.kategoriya}:*`);
if (keys.length) await this.redis.del(...keys); // bog'liq ro'yxatlar
await this.cache.del("products:featured"); // bosh sahifa keshi
return product;
}
// Bir o'zgarish ko'p bog'liq kesh (aks holda stale — 2.4)Misol 4 — Stateless: sessiya Redis'da (2.6)
// STATEFUL — sessiya server xotirasida (gorizontal masshtab buziladi)
// app.use(session({ store: new MemoryStore() })) // boshqa server'da yo'q!
// STATELESS — sessiya Redis'da (har server bir xil — 2.6)
import RedisStore from "connect-redis";
app.use(session({
store: new RedisStore({ client: redisClient }), // Redis (tashqarida — 8.15)
secret: config.get("SESSION_SECRET"),
}));
// har server Redis'dan sessiyani o'qiydi (load balancer istalgan server'ga yo'naltiradi)
// Yoki JWT (stateless — server holatsiz — 8.9)
// token ichida holat server hech narsa saqlamaydi (eng stateless)Misol 5 — Read replica (o'qish/yozish ajratish — 2.7)
// TypeORM — read replica (o'qish replica'lardan, yozish primary'ga)
TypeOrmModule.forRoot({
type: "postgres",
replication: {
master: { host: "primary-db", /* yozish */ }, // PRIMARY (yozish)
slaves: [
{ host: "replica-1" }, // REPLICA (o'qish)
{ host: "replica-2" },
],
},
});
// SELECT avtomatik replica'lardan; INSERT/UPDATE primary'ga (2.7)
// Yoki qo'lda
async hisobot() {
// O'qish-og'ir replica
return this.dataSource.createQueryBuilder().setQueryRunner(replicaRunner)/* ... */;
}Misol 6 — Load balancer (Nginx — 2.9)
# nginx.conf — load balancer (3 server orasida — 2.9)
upstream backend {
least_conn; # algoritm: eng kam band (2.9)
server app1:3000;
server app2:3000;
server app3:3000;
# server app4:3000 weight=2; # weighted (kuchli — ko'proq)
}
server {
listen 80;
location / {
proxy_pass http://backend; # yukni taqsimlash
proxy_set_header Host $host;
}
# Statik fayl — CDN/cache (2.3)
location /static/ {
expires 1y; # brauzer cache (2.3)
add_header Cache-Control "public";
}
}
# health check + ko'p server = HA (biri yiqilsa, boshqasi — 9.8)Misol 7 — CDN va statik kesh (2.3)
// Statik fayl (rasm — 8.24) CDN (foydalanuvchiga yaqin — 2.3)
@Get("images/:id")
async rasm(@Param("id") id: string, @Res() res: Response) {
const buffer = await this.s3.yuklab(`images/${id}`);
res.setHeader("Content-Type", "image/webp");
// CDN/brauzer kesh (uzoq — statik o'zgarmaydi — 2.3)
res.setHeader("Cache-Control", "public, max-age=31536000, immutable"); // 1 yil
res.send(buffer);
}
// Production: rasm to'g'ridan CDN'dan (Cloudflare/CloudFront — server'ga bormaydi)
// eng katta tezlik (statik fayl — foydalanuvchiga geografik yaqin)Misol 8 — Cache stampede himoyasi (2.4)
// MUAMMO: cache eskirdi 1000 so'rov bir vaqtda DB'ga (stampede — DB qulaydi)
// YECHIM: lock (faqat bittasi DB'dan yuklaydi, qolgani kutadi)
async bittaLockBilan(id: string): Promise<Product> {
const kalit = `product:${id}`;
let keshda = await this.cache.get<Product>(kalit);
if (keshda) return keshda;
// Lock (faqat bitta so'rov DB'ga — stampede oldini olish)
const lock = await this.redis.set(`lock:${kalit}`, "1", "EX", 10, "NX");
if (!lock) {
await this.sleep(100); // boshqa so'rov yuklayapti — kut
return this.bittaLockBilan(id); // qayta urin (endi keshda)
}
try {
const product = await this.repo.findOneBy({ id }); // faqat bitta DB so'rovi
await this.cache.set(kalit, product, 300000);
return product;
} finally {
await this.redis.del(`lock:${kalit}`);
}
}Misol 8b — Cache penetration himoyasi (null caching — 2.4a)
// MUAMMO: mavjud bo'lmagan ID (id=-1, tasodifiy) har safar DB'ga (penetration)
// YECHIM: "yo'q" natijani ham KESHLASH (qisqa TTL — hujum vektorini yopadi)
async bittaXavfsiz(id: string): Promise<Product | null> {
const kalit = `product:${id}`;
const keshda = await this.cache.get<Product | "__NULL__">(kalit);
if (keshda === "__NULL__") return null; // keshdagi "yo'q" — DB'ga bormaymiz
if (keshda) return keshda as Product; // oddiy hit
const product = await this.repo.findOneBy({ id });
if (!product) {
await this.cache.set(kalit, "__NULL__", 60000); // "yo'q"ni QISQA TTL (60s) bilan kesh
return null; // keyingi so'rov DB'ga bormaydi
}
await this.cache.set(kalit, product, 300000);
return product;
}
// Alternativa: bloom filter — "bu ID umuman bormi?" (yo'q bo'lsa DB'ga umuman bormaymiz)Misol 8c — Cache avalanche himoyasi (TTL jitter — 2.4a)
// MUAMMO: ko'p kalit BIR VAQTDA eskiradi DB'ga to'lqin (avalanche)
// YECHIM: sobit TTL emas, TASODIFIY qo'shimcha (jitter) — eskirish tarqaladi
private ttlJitter(bazaSekund: number): number {
const jitter = Math.floor(Math.random() * 60); // 0..60s tasodifiy
return (bazaSekund + jitter) * 1000; // ms
}
async keshla(kalit: string, qiymat: unknown) {
// Har kalit biroz boshqa vaqtda eskiradi DB'ga bir lahzada urilmaydi
await this.cache.set(kalit, qiymat, this.ttlJitter(300)); // 300..360s
}
// + muhim keshlarni oldindan qizdirish (cache warming — tizim startida)
// + Redis HA (Sentinel/Cluster — 2.13): bitta Redis yiqilsa to'liq avalanche bo'lmasinMisol 8d — Stale-while-revalidate (latency ~0 — 2.2)
// Eskirsa ham DARROV eski qiymat qaytariladi, YANGISI fonda yuklanadi
// (foydalanuvchi hech qachon kutmaydi + stampede yumshaydi)
async bittaSWR(id: string): Promise<Product> {
const kalit = `product:${id}`;
const wrap = await this.cache.get<{ data: Product; freshUntil: number }>(kalit);
if (wrap) {
if (Date.now() > wrap.freshUntil) {
// Eskirgan — lekin darrov eski qiymatni qaytaramiz, fonda yangilaymiz
this.fondaYangila(id, kalit).catch(() => {}); // await YO'Q — bloklamaydi
}
return wrap.data; // hamisha tez (miss yo'q)
}
return this.fondaYangila(id, kalit); // birinchi marta — yuklaymiz
}
private async fondaYangila(id: string, kalit: string): Promise<Product> {
const product = await this.repo.findOneBy({ id });
await this.cache.set(kalit, { data: product, freshUntil: Date.now() + 60000 }, 600000);
return product; // TTL 10min, "fresh" 1min
}Misol 8e — Redis konfiguratsiyasi (eviction + persistence — 2.13)
# redis.conf — cache sifatida sozlash (2.13)
maxmemory 2gb # xotira limiti
maxmemory-policy allkeys-lru # to'lganda eng uzoq ishlatilmagan kalit o'chadi (cache)
# maxmemory-policy allkeys-lfu # yoki eng kam ishlatilgan (issiq/sovuq aniq bo'lsa)
# Persistence — SOF CACHE uchun o'chirish mumkin (yiqilsa DB'dan qayta to'ladi):
save "" # RDB snapshot o'chirilgan (cache — durability shart emas)
appendonly no # AOF o'chirilgan
# Muhim ma'lumot (sessiya/navbat) uchun esa:
# appendonly yes # AOF (har yozish jurnali — deyarli yo'qolmaydi)// Distributed lock (Redlock g'oyasi — 2.13): SET NX EX + atomik ochish
async qulfOlib<T>(kalit: string, ish: () => Promise<T>): Promise<T> {
const token = crypto.randomUUID(); // egalikni isbotlash uchun
const olindi = await this.redis.set(`lock:${kalit}`, token, "EX", 10, "NX");
if (!olindi) throw new Error("qulf band"); // boshqa jarayon ushlab turibdi
try {
return await ish();
} finally {
// Faqat EGASI ochsin (Lua — atomik: tekshir+o'chir bir amalda)
const lua = `if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end`;
await this.redis.eval(lua, 1, `lock:${kalit}`, token);
}
}
// Ko'p Redis tuguni Redlock kutubxonasi; bitta tugunda bu yetadiMisol 8f — HTTP caching: ETag va 304 (2.4)
import { createHash } from "crypto";
// Dinamik javob uchun ETag — o'zgarmagan bo'lsa 304 (bo'sh — tarmoq tejaladi)
@Get("product/:id")
async product(@Param("id") id: string, @Req() req: Request, @Res() res: Response) {
const product = await this.service.bitta(id);
const etag = createHash("sha1").update(JSON.stringify(product)).digest("hex");
// Brauzer eski ETag'ni yubordi — o'zgarganmi?
if (req.headers["if-none-match"] === etag) {
return res.status(304).end(); // 304 — BO'SH tana (keshdan ol)
}
res.setHeader("ETag", etag);
res.setHeader("Cache-Control", "private, max-age=0, must-revalidate"); // doim tasdiqla
return res.json(product);
}
// Statik fayl (rasm/JS) — versiyalangan URL bilan uzoq kesh (purge shart emas — 2.14):
// res.setHeader("Cache-Control", "public, max-age=31536000, immutable");Misol 8g — Load balancer: HAProxy (L7 + health check — 2.9)
# haproxy.cfg — L7 load balancer (health check bilan — 2.9)
frontend web
bind *:80
mode http # L7 (HTTP — URL/sarlavha o'qiydi — 2.9)
default_backend app_servers
backend app_servers
balance leastconn # algoritm: eng kam ulanish (2.9)
option httpchk GET /health # ACTIVE health check (9.8 — javob bermasa chetlaydi)
server app1 10.0.0.1:3000 check
server app2 10.0.0.2:3000 check
server app3 10.0.0.3:3000 check weight 2 # weighted (kuchli — ko'proq yuk)
# sog'lom bo'lmagan server avtomatik chetlanadi (HA); tuzalgach qaytadiMisol 8h — Percentile o'lchash (p50/p95/p99 — 2.10)
// Latency percentile — o'rtacha (avg) dumni yashiradi, percentile aniq (2.10)
function percentile(latencies: number[], p: number): number {
const tartib = [...latencies].sort((a, b) => a - b); // o'sish tartibida
const idx = Math.ceil((p / 100) * tartib.length) - 1;
return tartib[Math.max(0, idx)];
}
// Yuk testidan yig'ilgan latency'lar (ms)
const l = collectedLatencies;
console.log("p50 :", percentile(l, 50)); // median — tipik tajriba
console.log("p95 :", percentile(l, 95)); // ko'pchilikning yomon holati
console.log("p99 :", percentile(l, 99)); // dum (tail) — katta masshtabda muhim
const avg = l.reduce((a, b) => a + b, 0) / l.length;
console.log("avg :", avg); // dumni yashiradi — percentile'ga ishon
// SLO odatda: "p99 < 200ms" (o'rtacha emas — 2.10)Misol 9 — Masshtab tartibi (qaror — 2.11)
Ilova sekin/yuk ko'tarilmayapti — nima qilish? (tartib — 2.11):
1. O'LCHA (profiling — qaysi sekin? — 2.10)
DB query 2s? indeks yo'q 6.10-bob — TUZAT (arzon, katta yutuq)
2. CACHE (tez-tez o'qiladigan — 8.15)
katalog cache DB yuki 80% kamaydi (arzon — 2.1)
3. Hali sekin? VERTIKAL (kuchliroq server — oddiy — 2.5)
4. O'qish ko'p? READ REPLICA 2.7-bob
5. Bir server yetmayapti? GORIZONTAL + LB (stateless — 2.5, 2.6)
6. DB juda katta (yozish ham)? SHARDING (oxirgi — 2.8)
Ko'p loyiha 1-2 da to'xtaydi (optimallash + cache yetadi)Misol 10 — To'liq masshtablanadigan arxitektura
KATTA YUKKA CHIDAMLI ARXITEKTURA:
Mijoz
│
CDN (statik — rasm/JS/CSS — 2.3) ──────────┐
│ (dinamik) │
Load Balancer (round-robin/least-conn — 2.9)
│ (stateless — 2.6)
┌──┼──┐
▼ ▼ ▼
App App App gorizontal (ko'p nusxa — 2.5)
└──┼──┘
▼
Redis (cache 8.15 + sessiya — stateless — 2.6)
│ (cache miss)
┌──┴──────┐
▼ ▼
DB Primary DB Replica (o'qish — 2.7)
(yozish) (o'qish)
│ (juda katta bo'lsa)
└ Sharding 2.8-bob
CDN + LB + stateless app + Redis + replica = millionlab so'rov/kun5. To'g'ri va noto'g'ri holatlar
1) Optimallashtirmasdan masshtab
sekin query'ga ko'proq server (pulni isrof — 2.11)
avval o'lcha + optimallash + cache (arzon)2) Stateful (gorizontal masshtab)
sessiya server xotirasida (load balancer buziladi — 2.6)
stateless (Redis/JWT)3) Cache invalidation yo'q
o'zgargach eski cache (stale — 2.4)
TTL + o'zgarganda del4) Erta sharding
kichik DB'ga sharding (keraksiz murakkablik — 2.8)
cache + replica avval (sharding — oxirgi)5) Taxmin bilan optimallash
"shu sekin shekilli" (noto'g'ri joy — 2.10)
o'lcha (profiling) bottleneck tuzat6. Keng tarqalgan xatolar va yechimlari
Xato 1 — Sekin sayt (cache yo'q)
Sababi: har so'rov DB/hisoblash 2.1-bob. Yechimi: cache (cache-aside + CDN).
Xato 2 — Eski ma'lumot (stale)
Sababi: invalidation yo'q 2.4-bob. Yechimi: TTL + del + tag.
Xato 3 — Load balancer'da sessiya yo'qoladi
Sababi: stateful 2.6-bob. Yechimi: stateless (Redis/JWT).
Xato 4 — DB bottleneck
Sababi: indeks yo'q, ko'p o'qish (2.7, 6.10). Yechimi: indeks + cache + read replica.
Xato 5 — Cache stampede (DB qulaydi)
Sababi: cache eskirdi barcha DB'ga 2.4-bob. Yechimi: lock (Misol 8) / staggered TTL.
Xato 6 — Server yiqilsa hammasi to'xtaydi
Sababi: bitta server / SPOF 2.9-bob. Yechimi: load balancer + ko'p server (HA).
Xato 7 — Cache penetration (yo'q ID DB'ni ko'madi)
Sababi: mavjud emas ID har safar DB (hujum vektori — 2.4a). Yechimi: null natijani qisqa TTL bilan keshlash / bloom filter (Misol 8b).
Xato 8 — Cache avalanche (bir vaqtda eskirish)
Sababi: ko'p kalit sobit bir xil TTL DB'ga to'lqin, yoki Redis yiqildi (2.4a). Yechimi: TTL jitter (Misol 8c) + cache warming + Redis HA (Sentinel/Cluster — 2.13).
Xato 9 — Redis to'lib xato bermoqda (yoki noto'g'ri eviction)
Sababi: maxmemory yetmaydi / noeviction policy 2.13-bob. Yechimi: cache uchun allkeys-lru/allkeys-lfu (Misol 8e).
Xato 10 — "O'rtacha tez" lekin ba'zi foydalanuvchi sekin
Sababi: avg dumni yashiradi — tail latency ko'rilmagan 2.10-bob. Yechimi: p95/p99 o'lchash (Misol 8h), SLO percentile'da.
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- Redis cache 8.15-bob: strategiyalar, eviction, persistence, HA, lock 2.13-bob.
- DB indeks/optimization 6.10-bob: bottleneck.
- Connection pool 6.15-bob: DB masshtab, partitioning 2.8-bob.
- Load balancer / health check 9.8-bob: Gateway HA, L4/L7 2.9-bob.
- Stateless 8.9-bob: JWT 2.6-bob.
- Image/CDN 8.24-bob: statik kesh, edge, purge 2.14-bob.
- DevOps (10): auto-scaling 2.14-bob, deploy.
- Eventual consistency 9.7-bob: replica kechikishi 2.7-bob.
- CAP teoremasi (9.10 — keyingi bob): replica/cache izchillik muvozanati 2.14-bob.
8. Eng yaxshi amaliyotlar (best practices)
- Cache-aside (eng keng — 2.2); to'g'ri narsani keshlash 8.15-bob; issiq ma'lumot uchun refresh-ahead/SWR 2.2-bob.
- Invalidation (TTL + del + tag + versioning — 2.4); HTTP caching (Cache-Control + ETag/304 — 2.3); CDN statik (2.3, 2.14).
- Multi-layer cache (brauzerCDNRedisDB — 2.3).
- Cache himoyalari: stampede (lock — Misol 8), penetration (null cache/bloom — 2.4a), avalanche (TTL jitter — 2.4a).
- Redis: cache uchun
allkeys-lrueviction + persistence'siz; muhim ma'lumot uchun AOF + Sentinel/Cluster 2.13-bob. - Avval o'lcha + optimallash + cache (arzon — 2.11); percentile p95/p99 (avg emas — 2.10).
- Stateless (gorizontal + auto-scaling sharti — 2.6, 2.14); sticky o'rniga Redis sessiya.
- Vertikal replica gorizontal sharding (tartib — 2.11); partitioning + connection pool (2.8, 6.15).
- Load balancer (L7 + least-connections + active health check — HA — 2.9).
- Bottleneck o'lcha (taxmin emas — 2.10); DB birinchi 6.10-bob.
- Sharding — oxirgi chora (juda katta — 2.8).
9. Amaliy loyiha: "Masshtablanadigan Tizim"
Caching/scalability/load balancing'ni amalda mustahkamlash.
Maqsad
Yuqori yukka chidamli tizim: multi-layer cache, stateless, read replica, load balancer.
Talablar (requirements)
- Cache-aside: Redis + invalidation (Misol 1, 2.2).
- Write-through (muqobil): doim mos (Misol 2).
- Tag invalidation: bog'liq keshlar (Misol 3, 2.4).
- Stateless: sessiya Redis/JWT (Misol 4, 2.6).
- Read replica: o'qish/yozish ajratish (Misol 5, 2.7).
- Load balancer: Nginx (Misol 6, 2.9).
- CDN: statik kesh (Misol 7, 2.3).
- Stampede himoyasi: lock (Misol 8, 2.4a).
- Penetration/avalanche himoyasi: null caching + TTL jitter (Misol 8b, 8c, 2.4a).
- HTTP caching: ETag + 304 (Misol 8f, 2.3).
- Redis sozlash: eviction + distributed lock (Misol 8e, 2.13).
- Masshtab tartibi: qaror (Misol 9, 2.11).
- Bottleneck + percentile: o'lchash, p95/p99 (Misol 8h, 2.10).
Maslahatlar (hint)
- Cache-aside + invalidation (2.2, 2.4, 3-xato).
- Stateless (2.6, 3-xato).
- Read replica o'qish (2.7, 4-xato).
- Avval o'lcha (2.10, 5-holat).
- Sharding oxirgi (2.8, 4-holat).
- Stampede lock (Misol 8, 5-xato).
"Tayyor" mezonlari (acceptance criteria)
- Cache-aside.
- Write-through.
- Tag invalidation.
- Stateless.
- Read replica.
- Load balancer.
- CDN.
- Stampede himoyasi.
- Penetration/avalanche himoyasi.
- HTTP caching (ETag/304).
- Redis eviction + lock.
- Masshtab tartibi.
- Bottleneck + percentile o'lchash.
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda tezlik va masshtabni chuqur o'rgandik:
- Caching (eng katta tezlik — 2.1); strategiyalar (cache-aside/read-through/write-through/write-behind/refresh-ahead/SWR — 2.2); qatlamlar (CDNRedisDB — 2.3) + HTTP caching (ETag/304 — 2.3); invalidation (eng qiyin — 2.4); cache muammolari (stampede/penetration/avalanche — 2.4a); Redis chuqur (eviction/persistence/HA/lock — 2.13).
- Scalability (vertikal vs gorizontal — 2.5); stateless (gorizontal sharti — 2.6); DB masshtab (read replica — 2.7, sharding/partitioning — 2.8, connection pool — 6.15).
- Load balancing (L4/L7, algoritmlar, sticky, health check — 2.9); bottleneck (o'lcha — 2.10) + percentile (p50/p95/p99 — 2.10); CDN + auto-scaling 2.14-bob; masshtab tartibi (arzondan qimmatga — 2.11).
Keyingi bob — 9.10: Distributed systems, CAP teoremasi. Masshtabni bildik; endi 9-QISM'ning yakuniy, eng nazariy mavzusini — taqsimlangan tizimlar va CAP teoremasi (Consistency/Availability/Partition — uchtasidan ikkitasi) — o'rganamiz. Bu — barcha taqsimlangan tizim qarorining nazariy asosi.
Foydalanilgan rasmiy/ishonchli manbalar
Caching:
- Redis rasmiy hujjatlari — ma'lumot turlari,
maxmemoryeviction policy (LRU/LFU), persistence (RDB/AOF), Sentinel va Cluster, distributed lock (Redlock). - MDN Web Docs — HTTP caching:
Cache-Control,ETag,Last-Modified, shartli so'rov va304 Not Modified,stale-while-revalidate. - AWS Prescriptive Guidance — caching strategiyalari (cache-aside, read-through, write-through, write-behind, refresh-ahead) va cache muammolari (stampede/penetration/avalanche).
Scalability va DB:
- PostgreSQL rasmiy hujjatlari — replication (streaming), partitioning; PgBouncer — connection pooling.
- System design adabiyoti (masalan "Designing Data-Intensive Applications", M. Kleppmann) — replikatsiya, sharding, izchillik, CAP.
Load balancing va CDN:
- Nginx rasmiy hujjatlari —
upstreamload balancing (round-robin,least_conn,ip_hash, weighted), health check, static caching. - HAProxy rasmiy hujjatlari — L4/L7 rejim,
balancealgoritmlari,option httpchkhealth check. - Cloudflare / AWS CloudFront hujjatlari — CDN edge caching, static/dynamic, cache purge (versiyalangan URL va API invalidatsiya).
Performance:
- Yuk testi vositalari hujjatlari (k6, wrk) — latency, throughput (RPS), percentile (p50/p95/p99) o'lchash metodikasi.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!