IlmHamroh
Python kursi/Bazalar va ORM10/12-dars16 daqiqa
Mundarija (22)

23.10-dars: Redis va kesh

23-QISM — BAZALAR VA ORM · 10-dars


1. Kirish va motivatsiya

23.9 da N+1'ni yechdik — so'rovlar sonini kamaytirdik. Lekin ba'zi ma'lumot juda tez-tez so'raladi: bosh sahifa kurslari, foydalanuvchi profili, valyuta kursi. Har so'rovda bazaga borish — hatto optimallashtirilgan so'rov ham — keraksiz yuk. Agar ma'lumot kam o'zgarsa, uni xotirada saqlash (kesh) mumkin: birinchi marta bazadan, keyingi martalar xotiradan (mikrosoniya).

Kesh (cache) — tez-tez so'ralgan ma'lumotni tez xotirada vaqtincha saqlash. Redis — eng mashhur kesh (xotirada ishlaydigan kalit-qiymat baza): juda tez (RAM), TTL (yashash muddati), turli tuzilma (string, hash, list, set). Kesh-aside namunasi: bazaga borishdan oldin keshni tekshir — bor bo'lsa keshdan (tez), yo'q bo'lsa bazadan + keshga yoz.

Real vaziyat. Bosh sahifa har ochilganda 20 ta so'rov bazaga borardi — 300ms. Ma'lumot soatda bir marta o'zgarardi, lekin har foydalanuvchi uchun qayta hisoblanardi. Redis kesh qo'shildi: birinchi so'rov bazadan (300ms) + keshga yozildi (TTL 300s). Keyingi 5 daqiqada barcha so'rov keshdan — 2ms. Baza yuki 95% kamaydi, sahifa 150 barobar tez. Bir kesh qatlami katta farq qildi.

Bu darsda Redis va keshni — xotira baza, TTL, kesh-aside namunasini o'rganamiz.

Bu darsda:

  • Kesh nima va nega
  • Redis nima
  • Asosiy amallar (get/set/incr)
  • TTL (yashash muddati)
  • Kesh-aside namunasi
  • Kesh invalidatsiya
  • Tuzilmalar (hash, list)
  • Amaliy: kesh qatlami

ℹ Misollarda fakeredis (haqiqiy Redis API, xotirada) bilan sinaladi.


2. Nazariya — chuqur tushuntirish

2.1. Kesh nima va nega

Kesh — tez-tez kerak ma'lumotni tez joyda saqlash:

So'rov → keshda bormi?
   ha  → keshdan qaytar (tez, ~1ms)
   yo'q → bazadan o'qi (sekin, ~50ms) + keshga yoz

Kesh — tez-tez so'ralgan, kam o'zgaradigan ma'lumotni tez xotirada vaqtincha saqlash. Maqsad: bazaga murojaatni kamaytirish (baza sekin — disk, tarmoq). Kesh tez (RAM), lekin vaqtincha (o'chib ketishi mumkin) va eskirishi mumkin (ma'lumot o'zgarsa). "Tez, lekin ishonchsiz nusxa".

2.2. Redis nima

Redis — xotirada ishlaydigan kalit-qiymat baza:

python
import redis
r = redis.Redis(host="localhost", port=6379, decode_responses=True)
r.set("kurs:1", "Python")
r.get("kurs:1")            # "Python"

Redis (REmote DIctionary Server) — xotirada (RAM) ishlaydigan kalit-qiymat baza. Juda tez (mikrosoniya), turli tuzilma (string, hash, list, set, sorted set), TTL (avtomatik o'chirish). Asosiy ishlatilishi: kesh, sessiya, navbat (queue), hisoblagich, real-vaqt reyting. redis.Redis() — Python mijozi.

2.3. Asosiy amallar (get/set/incr)

Redis asosiy buyruqlari:

python
r.set("kalit", "qiymat")       # yoz
r.get("kalit")                 # o'qi
r.delete("kalit")              # o'chir
r.exists("kalit")              # bormi (1/0)
r.incr("hisoblagich")          # +1 (atomik)
r.set("k", "v", nx=True)       # faqat yo'q bo'lsa

Asosiy amallar: set/get (yoz/o'qi), delete (o'chir), exists (bormi), incr/decr (atomik +1/-1 — hisoblagich uchun), nx=True (faqat mavjud bo'lmasa). incr atomik — ko'p mijoz bir vaqtda ishlatsa ham to'g'ri (23.4 tranzaksiya kabi). Kalit odatda tur:id (kurs:1).

2.4. TTL (yashash muddati)

TTL — kalitning avtomatik o'chish muddati:

python
r.setex("sessiya:abc", 300, "user42")   # 300 soniya, keyin o'chadi
r.expire("kalit", 60)                    # mavjud kalitga TTL
r.ttl("kalit")                           # qolgan soniya
r.persist("kalit")                       # TTL'ni olib tashla

TTL (Time To Live) — kalit necha soniyadan keyin avtomatik o'chish. setex(kalit, soniya, qiymat) (TTL bilan yoz), expire (mavjudga TTL), ttl (qolgan vaqt), persist (TTL olib tashla). Kesh uchun muhim: eski ma'lumot avtomatik o'chadi (TTL tugasa qayta bazadan). Sessiya, vaqtincha ma'lumot uchun ideal.

2.5. Kesh-aside namunasi

Eng keng tarqalgan kesh namunasi:

python
def kurs_ol(id):
    kesh = r.get(f"kurs:{id}")
    if kesh is not None:           # kesh hit
        return kesh
    qiymat = bazadan_ol(id)        # kesh miss → baza
    r.setex(f"kurs:{id}", 300, qiymat)   # keshga yoz
    return qiymat

Kesh-aside (cache-aside / lazy loading): 1) keshni tekshir, 2) bor bo'lsa qaytar (hit — tez), 3) yo'q bo'lsa bazadan o'qi (miss), keshga yoz (TTL bilan), qaytar. Bu eng keng tarqalgan namuna. "Hit nisbati" (hit rate) — necha % kesh'dan keldi (yuqori = yaxshi). Birinchi so'rov sekin (miss), keyingilar tez (hit).

2.6. Kesh invalidatsiya

Ma'lumot o'zgarsa — keshni yangila:

python
def kurs_yangila(id, yangi):
    bazada_yangila(id, yangi)      # bazani yangila
    r.delete(f"kurs:{id}")         # keshni o'chir (invalidatsiya)
    # keyingi o'qishda yangi qiymat keshga

Kesh invalidatsiya — ma'lumot o'zgarganda keshni o'chirish yoki yangilash (aks holda eski ma'lumot qaytadi). Ikki usul: o'chir (delete — keyingi o'qishda qayta yuklanadi) yoki yangila (set — darrov yangi). "Keshda faqat ikki qiyin narsa bor: kesh invalidatsiya va nomlash" (mashhur ibora) — invalidatsiya qiyin (qachan, qaysini).

2.7. Tuzilmalar (hash, list)

Redis turli tuzilma:

Tuzilma Buyruq Ishlatilish
String set/get oddiy qiymat, JSON
Hash hset/hgetall obyekt (maydonlar)
List rpush/lrange navbat, oxirgi N
Set sadd/smembers noyob to'plam
Sorted set zadd/zrange reyting (ball bilan)

Redis — nafaqat string: hash (hset — obyekt maydonlari), list (rpush/lpush — navbat, oxirgi hodisalar), set (sadd — noyob to'plam, 4.x), sorted set (zadd — reyting, ball bo'yicha). Bu Redis'ni kuchli qiladi: kesh + navbat + reyting + sessiya — bir vositada.

2.8. Kesh xavflari

Xavf Yechim
Eski ma'lumot TTL + invalidatsiya
Kesh o'chib ketdi Bazadan qayta (kesh ixtiyoriy)
Kesh bo'roni (miss to'lqini) TTL tarqatish, qulf
Xotira to'ldi LRU siyosat (eskini chiqar)

Kesh xavflari: eski ma'lumot (stale — TTL va invalidatsiya bilan), kesh o'chishi (Redis vaqtincha — ilova bazadan ishlash davom etishi kerak, kesh ixtiyoriy bo'lsin), kesh bo'roni (bir vaqtda ko'p miss — bazaga zarba), xotira chegarasi (LRU — eng kam ishlatilganni chiqar). Kesh — yordamchi, asosiy manba emas.


3. Tez ma'lumotnoma

python
import redis
r = redis.Redis(host="localhost", port=6379, decode_responses=True)

# asosiy:
r.set("kurs:1", "Python"); r.get("kurs:1")
r.delete("kurs:1"); r.exists("kurs:1"); r.incr("koradi")

# TTL:
r.setex("sessiya:abc", 300, "user42")     # 300s
r.expire("k", 60); r.ttl("k"); r.persist("k")

# kesh-aside:
def ol(id):
    v = r.get(f"kurs:{id}")
    if v is not None: return v            # hit
    v = bazadan_ol(id)                    # miss
    r.setex(f"kurs:{id}", 300, v); return v

# invalidatsiya:
bazada_yangila(id); r.delete(f"kurs:{id}")

# tuzilmalar:
r.hset("user:1", mapping={"nom": "Ali"}); r.hgetall("user:1")
r.rpush("navbat", "a"); r.lrange("navbat", 0, -1)

Kesh xulosasi

Kesh: tez xotira (Redis) · kesh-aside: tekshir → hit/miss → yoz
TTL: avtomatik o'chish · invalidatsiya: o'zgarsa o'chir
Kesh ixtiyoriy: o'chsa bazadan

4. Batafsil misollar

Misollarda fakeredis (haqiqiy Redis API, xotirada — server kerak emas) bilan sinaladi. Real ilovada redis.Redis(host=...) ishlatiladi, API bir xil.

Misol 1 — Redis asosiy amallar

python
"""set/get (yoz/o'qi); delete/exists; incr (atomik hisoblagich); nx (faqat yo'q bo'lsa)."""

import warnings
warnings.filterwarnings("ignore")

import fakeredis


def main() -> None:
    r = fakeredis.FakeStrictRedis(decode_responses=True)

    print("=== 1. set / get ===")
    r.set("kurs:1", "Python")
    r.set("kurs:2", "Go")
    print(f"  kurs:1 = {r.get('kurs:1')}")
    print(f"  kurs:2 = {r.get('kurs:2')}")
    print(f"  yo'q kalit = {r.get('kurs:99')}")

    print("\n=== 2. exists / delete ===")
    print(f"  kurs:1 bormi: {r.exists('kurs:1')}")
    r.delete("kurs:1")
    print(f"  o'chirgandan keyin: {r.exists('kurs:1')}")

    print("\n=== 3. incr (atomik hisoblagich) ===")
    r.set("korishlar", 0)
    for _ in range(5):
        r.incr("korishlar")
    print(f"  ko'rishlar: {r.get('korishlar')}")

    print("\n=== 4. nx (faqat mavjud bo'lmasa) ===")
    r.set("bir_martalik", "birinchi", nx=True)
    r.set("bir_martalik", "ikkinchi", nx=True)   # o'zgarmaydi
    print(f"  qiymat: {r.get('bir_martalik')}")
    print("  ⭐ set/get/incr — Redis asosi (tez, atomik)")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. set / get ===
  kurs:1 = Python
  kurs:2 = Go
  yo'q kalit = None

=== 2. exists / delete ===
  kurs:1 bormi: 1
  o'chirgandan keyin: 0

=== 3. incr (atomik hisoblagich) ===
  ko'rishlar: 5

=== 4. nx (faqat mavjud bo'lmasa) ===
  qiymat: birinchi
  ⭐ set/get/incr — Redis asosi (tez, atomik)

Nima ko'rsatdi: 2.2, 2.3-bo'limlar.

Misol 2 — TTL (yashash muddati)

python
"""setex (TTL bilan yoz); expire (mavjudga TTL); ttl (qolgan); persist (TTL olib tashla)."""

import warnings
warnings.filterwarnings("ignore")

import fakeredis


def main() -> None:
    r = fakeredis.FakeStrictRedis(decode_responses=True)

    print("=== 1. setex (TTL bilan) ===")
    r.setex("sessiya:abc", 300, "user42")
    print(f"  qiymat: {r.get('sessiya:abc')}")
    print(f"  TTL bormi (0 dan katta): {r.ttl('sessiya:abc') > 0}")

    print("\n=== 2. expire (mavjud kalitga TTL) ===")
    r.set("kesh:kurslar", "Python,Go,Rust")
    print(f"  TTL oldin: {r.ttl('kesh:kurslar')}")   # -1 (TTL yo'q)
    r.expire("kesh:kurslar", 60)
    print(f"  TTL keyin (0 dan katta): {r.ttl('kesh:kurslar') > 0}")

    print("\n=== 3. persist (TTL olib tashla) ===")
    r.persist("kesh:kurslar")
    print(f"  TTL persist keyin: {r.ttl('kesh:kurslar')}")   # -1

    print("\n=== 4. TTL holatlari ===")
    print(f"  TTL yo'q kalit (-1): {r.ttl('kesh:kurslar')}")
    print(f"  mavjud emas kalit (-2): {r.ttl('yoq:kalit')}")
    print("  ⭐ TTL — kalit avtomatik o'chadi (kesh, sessiya)")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. setex (TTL bilan) ===
  qiymat: user42
  TTL bormi (0 dan katta): True

=== 2. expire (mavjud kalitga TTL) ===
  TTL oldin: -1
  TTL keyin (0 dan katta): True

=== 3. persist (TTL olib tashla) ===
  TTL persist keyin: -1

=== 4. TTL holatlari ===
  TTL yo'q kalit (-1): -1
  mavjud emas kalit (-2): -2
  ⭐ TTL — kalit avtomatik o'chadi (kesh, sessiya)

Nima ko'rsatdi: 2.4-bo'lim.

Misol 3 — Kesh-aside namunasi (hit/miss)

python
"""kesh-aside: keshni tekshir → hit (tez) yoki miss (bazadan + keshga yoz); so'rov sanash."""

import warnings
warnings.filterwarnings("ignore")

import fakeredis


def main() -> None:
    r = fakeredis.FakeStrictRedis(decode_responses=True)

    # soxta baza (sekin manba)
    BAZA = {1: "Python", 2: "Go", 3: "Rust"}
    baza_sanoq = [0]

    def bazadan_ol(kurs_id: int) -> str:
        baza_sanoq[0] += 1
        return BAZA[kurs_id]

    def kurs_ol(kurs_id: int) -> str:
        kesh = r.get(f"kurs:{kurs_id}")
        if kesh is not None:
            return kesh                      # kesh hit
        qiymat = bazadan_ol(kurs_id)         # kesh miss
        r.setex(f"kurs:{kurs_id}", 300, qiymat)
        return qiymat

    print("=== 1. Birinchi so'rov (miss → baza) ===")
    print(f"  kurs 1: {kurs_ol(1)} (baza so'rovlari: {baza_sanoq[0]})")

    print("\n=== 2. Ikkinchi so'rov (hit → kesh) ===")
    print(f"  kurs 1: {kurs_ol(1)} (baza so'rovlari: {baza_sanoq[0]})")

    print("\n=== 3. Ko'p so'rov (bir necha kurs) ===")
    for _ in range(3):
        for kid in (1, 2, 3):
            kurs_ol(kid)
    print(f"  9 takror so'rov, baza so'rovlari: {baza_sanoq[0]}")

    print("\n=== 4. Xulosa ===")
    print(f"  jami baza so'rovi: {baza_sanoq[0]} (3 noyob kurs)")
    print("  qolgan hammasi keshdan (hit)")
    print("  ⭐ kesh-aside — birinchi miss, keyingilar hit (tez)")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Birinchi so'rov (miss → baza) ===
  kurs 1: Python (baza so'rovlari: 1)

=== 2. Ikkinchi so'rov (hit → kesh) ===
  kurs 1: Python (baza so'rovlari: 1)

=== 3. Ko'p so'rov (bir necha kurs) ===
  9 takror so'rov, baza so'rovlari: 3

=== 4. Xulosa ===
  jami baza so'rovi: 3 (3 noyob kurs)
  qolgan hammasi keshdan (hit)
  ⭐ kesh-aside — birinchi miss, keyingilar hit (tez)

Nima ko'rsatdi: 2.1, 2.5-bo'limlar.

Misol 4 — Amaliy: kesh qatlami (invalidatsiya + tuzilma)

Real kesh qatlami: kesh-aside o'qish, o'zgarishda invalidatsiya, hash bilan obyekt saqlash. Bu — production kesh mantiqining namunasi.

python
"""to'liq kesh qatlami: hash (obyekt kesh), kesh-aside, invalidatsiya (o'zgarsa o'chir)."""

import warnings
warnings.filterwarnings("ignore")

import fakeredis


def main() -> None:
    r = fakeredis.FakeStrictRedis(decode_responses=True)
    BAZA = {1: {"nom": "Python", "narx": "100"}}
    baza_sanoq = [0]

    def bazadan_ol(kid: int) -> dict:
        baza_sanoq[0] += 1
        return dict(BAZA[kid])

    def kurs_ol(kid: int) -> dict:
        kalit = f"kurs:{kid}"
        if r.exists(kalit):
            return r.hgetall(kalit)          # hit (hash)
        obyekt = bazadan_ol(kid)             # miss
        r.hset(kalit, mapping=obyekt)
        r.expire(kalit, 300)
        return obyekt

    def kurs_yangila(kid: int, yangi_narx: str) -> None:
        BAZA[kid]["narx"] = yangi_narx       # baza
        r.delete(f"kurs:{kid}")              # invalidatsiya

    print("=== 1. Birinchi o'qish (miss → hash kesh) ===")
    print(f"  {kurs_ol(1)} (baza: {baza_sanoq[0]})")

    print("\n=== 2. Ikkinchi o'qish (hit) ===")
    print(f"  {kurs_ol(1)} (baza: {baza_sanoq[0]})")

    print("\n=== 3. Yangilash (invalidatsiya) ===")
    kurs_yangila(1, "150")
    print(f"  kesh o'chdi, keshda bormi: {r.exists('kurs:1')}")

    print("\n=== 4. Qayta o'qish (miss → yangi qiymat) ===")
    print(f"  {kurs_ol(1)} (baza: {baza_sanoq[0]})")
    print("  ⭐ kesh qatlami — hit/miss, invalidatsiya, hash (obyekt)")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Birinchi o'qish (miss → hash kesh) ===
  {'nom': 'Python', 'narx': '100'} (baza: 1)

=== 2. Ikkinchi o'qish (hit) ===
  {'nom': 'Python', 'narx': '100'} (baza: 1)

=== 3. Yangilash (invalidatsiya) ===
  kesh o'chdi, keshda bormi: 0

=== 4. Qayta o'qish (miss → yangi qiymat) ===
  {'nom': 'Python', 'narx': '150'} (baza: 2)
  ⭐ kesh qatlami — hit/miss, invalidatsiya, hash (obyekt)

Nima ko'rsatdi: 2.1–2.8-bo'limlar.


5. To'g'ri va noto'g'ri tushunishlar

Noto'g'ri fikr To'g'risi
"Kesh — asosiy manba" Yordamchi (o'chsa bazadan)
"Redis doim to'g'ri" Eskirishi mumkin (invalidatsiya)
"Hammani keshla" Tez-tez, kam o'zgaradigan
"TTL keraksiz" Eski ma'lumotni oldini oladi
"Redis faqat string" Hash, list, set, sorted set
"Kesh o'zi yangilanadi" Invalidatsiya qo'lda
"Redis = baza o'rnida" Kesh (asosiy baza — PostgreSQL)
"incr xavfli (poyga)" Atomik (xavfsiz)

6. Keng tarqalgan xatolar va yechimlari

1. Kesh invalidatsiyasini unutish

python
bazada_yangila(id)                      # ⚠️ kesh eski qoladi
bazada_yangila(id); r.delete(f"kurs:{id}")  # ✅

2. TTL'siz keshlash

python
r.set("kesh:x", qiymat)                 # ⚠️ abadiy (eskiradi)
r.setex("kesh:x", 300, qiymat)          # ✅

3. Keshni majburiy (o'chsa ilova buziladi)

python
qiymat = r.get(kalit)                   # ⚠️ Redis o'chsa?
# try: kesh; except: bazadan            # ✅ (kesh ixtiyoriy)

4. Hammani keshlash

python
# har so'rovni keshla                    # ⚠️ xotira, murakkablik
# faqat tez-tez, kam o'zgaradiganni      # ✅

5. Katta obyektni string sifatida

python
r.set("user:1", katta_json)             # ⚠️ har o'qishda to'liq
r.hset("user:1", mapping=...)           # ✅ (maydon bo'yicha)

6. Kalit nomi tartibsiz

python
r.set("kurs1")  r.set("k_2")            # ⚠️ tartibsiz
r.set("kurs:1")  r.set("kurs:2")        # ✅ (tur:id)

7. Sessiyani faqat xotirada (ko'p server)

python
sessiyalar = {}                         # ⚠️ bir server (masshtab yo'q)
r.setex(f"sessiya:{id}", 3600, ...)     # ✅ (umumiy Redis)

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 23.9-dars (o'tilgan): N+1 — kesh so'rovni kamaytiradi
  • 23.5-dars (o'tilgan): PostgreSQL — asosiy baza (kesh ustida)
  • 20.10-dars (o'tilgan): Fon vazifalari — kesh yangilash
  • 20.7-dars (o'tilgan): Auth — sessiya Redis'da
  • 31-qism: Deploy — Redis konteyner

8. Eng yaxshi amaliyotlar

  1. Faqat tez-tez, kam o'zgaradigan ma'lumot keshla.

  2. Har keshda TTL (avtomatik eskirish).

  3. O'zgarishda invalidatsiya (delete).

  4. Kesh ixtiyoriy (o'chsa bazadan).

  5. Kalit nomi tizimli (tur:id).

  6. Obyekt uchun hash (string emas).

  7. Sessiya/hisoblagich Redis'da (masshtab).

  8. Hit nisbatini kuzat (kesh samarasi).


9. Amaliy topshiriq

Vazifa 1: Bashorat qiling

python
1.  # Kesh nima?
2.  # Redis nima?
3.  # set/get nima?
4.  # incr nima (atomik)?
5.  # TTL nima?
6.  # setex nima?
7.  # kesh-aside nima?
8.  # kesh hit/miss nima?
9.  # invalidatsiya nima?
10. # hash nima?
11. # kesh ixtiyoriymi?
12. # nima keshlash kerak?
Javoblar
  1. Tez-tez kerak ma'lumotni tez xotirada saqlash
  2. Xotira kalit-qiymat baza (kesh)
  3. Yoz / o'qi
  4. Atomik +1 (hisoblagich)
  5. Kalit avtomatik o'chish muddati
  6. TTL bilan yoz
  7. Tekshir → hit yoki miss (baza + keshga)
  8. Hit — keshda bor, miss — yo'q
  9. O'zgarsa keshni o'chir/yangila
  10. Obyekt (maydon bilan)
  11. Ha (o'chsa bazadan)
  12. Tez-tez, kam o'zgaradigan

Vazifa 2: Xatolarni tuzating

python
1.  bazada_yangila(id)                  # invalidatsiya

2.  r.set("kesh:x", qiymat)             # setex (TTL)

3.  qiymat = r.get(kalit)               # kesh ixtiyoriy

4.  r.set("kurs1")                      # kurs:1

5.  sessiyalar = {}                     # Redis
Javoblar
python
1.  bazada_yangila(id); r.delete(f"kurs:{id}")

2.  r.setex("kesh:x", 300, qiymat)

3.  # try: kesh; except: bazadan

4.  r.set("kurs:1", ...)

5.  r.setex(f"sessiya:{id}", 3600, ...)

Vazifa 3: Kesh-aside

To'liq namuna:

  1. Soxta baza (sanoq)
  2. get → hit/miss
  3. Miss → baza + setex
  4. So'rov sonini ko'r

Vazifa 4: TTL

Muddat:

  1. setex (TTL bilan)
  2. expire (mavjudga)
  3. ttl (qolgan)
  4. persist

Vazifa 5: Invalidatsiya

O'zgarish:

  1. Kesh + baza
  2. Bazani yangila
  3. Keshni o'chir
  4. Qayta o'qi (yangi)

Vazifa 6: Tuzilmalar

Redis tuzilma:

  1. Hash (obyekt)
  2. List (navbat)
  3. Incr (hisoblagich)
  4. Har birini sina

Vazifa 7: O'ylash

Kesh tez-tez so'ralgan ma'lumotni tez xotirada saqlaydi — bazaga murojaatni kamaytiradi (tez). Lekin kesh eskirishi mumkin (ma'lumot bazada o'zgarsa, kesh eski) — bu "kesh invalidatsiya" muammosi. "Tezlik vs to'g'rilik (freshness)" tanlovi — kesh tezlik beradi, lekin to'g'rilikni (eng yangi ma'lumot) qurbon qilishi mumkin. Nima uchun "kesh invalidatsiya qiyin", va yaxshi muhandis bu tanlovni (TTL, invalidatsiya) qanday boshqaradi?

Javob

Qisqa javob: Kesh tezlik (xotiradan o'qish) va to'g'rilik (eng yangi ma'lumot) orasidagi tanlov. Kesh tez, lekin ma'lumot bazada o'zgarsa kesh eskiradi (stale). "Kesh invalidatsiya qiyin" (mashhur ibora), chunki: qachan o'chirish (har o'zgarishda? — ko'p joyda?), qaysini o'chirish (bog'langan kesh — kurs o'zgarsa, ro'yxat keshi ham?), poyga (o'zgarish va o'qish bir vaqtda). Yaxshi muhandis: TTL (avtomatik eskirish — eng ko'p N soniya eski), invalidatsiya (o'zgarishda o'chir — muhim ma'lumot uchun), tanlov (qancha eskilik qabul qilsa bo'ladi? — bank balansi yo'q, bosh sahifa — ha). "Barchaga mos yechim yo'q" — ma'lumotga qarab tanla.

1. Tezlik vs to'g'rilik

Tezlik (kesh) To'g'rilik (baza)
Xotiradan (~1ms) Diskdan (~50ms)
Eski bo'lishi mumkin Doim yangi
Yuk kam Har so'rov baza

2. Nega invalidatsiya qiyin

  • Qachan: har o'zgarishda? (o'zgarish ko'p joyda)
  • Qaysini: bog'langan kesh (kurs → ro'yxat keshi?)
  • Poyga: o'zgarish va keshga yozish bir vaqtda (eski yozilib qolishi)

3. Yaxshi muhandis qanday boshqaradi

Usul Qachan
TTL Ozroq eskilik qabul (bosh sahifa)
Invalidatsiya Muhim (narx o'zgarishi)
Keshlamaslik Kritik (bank balansi)

4. Ma'lumotga qarab tanlov

  • Kam o'zgaradi, eskilik zararsiz → kesh + uzun TTL
  • Tez-tez o'zgaradi, muhim → kesh + invalidatsiya yoki keshlama
  • Kritik (pul, xavfsizlik) → keshlama (doim baza)

5. Muhandislik saboqlari

  1. Kesh — tezlik/to'g'rilik tanlovi
  2. TTL — avtomatik eskirish (oddiy)
  3. Invalidatsiya — aniq, lekin qiyin
  4. Ma'lumotga qarab tanla (barchaga bir yechim yo'q)

6. Xulosa

  1. Kesh tezlik beradi, to'g'rilikni qurbon qilishi mumkin
  2. Invalidatsiya qiyin (qachan, qaysini, poyga)
  3. TTL — oddiy, invalidatsiya — aniq
  4. Ma'lumot muhimligiga qarab tanla

Nimani mustahkamlaydi: 2.1–2.8-bo'limlar.


Xulosa

Bu darsda Redis va keshni o'rgandik.

Eng muhim uch fikr:

  1. Kesh — tez-tez kerak ma'lumotni tez xotirada. Kesh — tez-tez so'ralgan, kam o'zgaradigan ma'lumotni tez xotirada vaqtincha saqlash (bazaga murojaatni kamaytirish). Redis — xotirada (RAM) ishlaydigan kalit-qiymat baza: juda tez, TTL (avtomatik o'chirish), turli tuzilma (string, hash, list, set, sorted set). Asosiy amallar: set/get (yoz/o'qi), incr (atomik hisoblagich), setex (TTL bilan), expire/ttl/persist. Kalit odatda tur:id (kurs:1).

  2. Kesh-aside va invalidatsiya. Kesh-aside (eng keng tarqalgan namuna): 1) keshni tekshir, 2) bor bo'lsa qaytar (hit — tez), 3) yo'q bo'lsa bazadan o'qi (miss), keshga yoz (TTL bilan). Birinchi so'rov sekin (miss), keyingilar tez (hit) — "hit nisbati" yuqori = yaxshi. Kesh invalidatsiya — ma'lumot o'zgarganda keshni o'chirish (delete) yoki yangilash (aks holda eski qaytadi). Invalidatsiya qiyin (qachan, qaysini) — mashhur muammo.

  3. Kesh — yordamchi, asosiy manba emas. Kesh xavflari: eski ma'lumot (TTL + invalidatsiya), kesh o'chishi (ilova bazadan ishlash davom etsin — kesh ixtiyoriy), kesh bo'roni (ko'p miss — bazaga zarba), xotira chegarasi (LRU). Kesh tezlik vs to'g'rilik tanlovi — tez, lekin eskirishi mumkin. Ma'lumotga qarab tanla: kam o'zgaradi → uzun TTL; muhim → invalidatsiya; kritik (pul, xavfsizlik) → keshlama. Redis tuzilmalari (hash — obyekt, list — navbat, sorted set — reyting) uni kesh'dan kengroq qiladi.

Keyingi darsda NoSQL: MongoDB ni o'rganamiz: jadval-sxema o'rniga hujjat (JSON kabi) saqlash — moslashuvchan sxema, boshqacha ma'lumot modeli.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
23.10-dars: Redis va kesh — IlmHamroh