GH GambleHub

Paginatsiya va kursorlar

1) Nima uchun paginatsiya kerak?

Paginatsiya mijoz tomonidan uzatiladigan va renderlanadigan ma’lumotlar hajmini cheklaydi, omborxonalar/tarmoqlarga yukni kamaytiradi va kolleksiya bo’ylab determinizatsiya usulini o’rnatadi. Haqiqiy tizimlarda paginatsiya faqat’page = 1 & limit = 50’emas, balki protokol kontraktlari va muvofiqlik invariantlari to’plamidir.

Namunaviy maqsadlar:
  • Soʻrov uchun latentlik va xotirani nazorat qilish.
  • Maʼlumotlar toʻplamini oʻzgartirishda barqaror navigatsiya (qoʻyish/oʻchirish).
  • Joydan qaytish imkoniyati (resumption).
  • Keshlash va oldindan yuklash (prefetch).
  • Foydalanishdan himoya qilish (rate limiting, backpressure).

2) Paginatsiya modellari

2. 1 OFFSET/LIMIT (sahifali)

G’oya: «N satrni o’tkazib yuboring, M ni qaytaring».
Afzalliklari: soddalik, deyarli har qanday SQL/NoSQL bilan mos keladi.

Minuslar:
  • Chiziqli degradatsiya: katta OFFSET to’liq skanerga/skip-costga olib keladi.
  • Soʻrovlar orasidagi qoʻyish/olib tashlashda beqarorlik (siljishlar «suzadi»).
  • «Qayta tiklanish» ni aniq ta’minlash qiyin.
SQL misoli:
sql
SELECT
FROM orders
ORDER BY created_at DESC, id DESC
OFFSET 1000 LIMIT 50;

2. 2 Cursor/Keyset/Seek-paginatsiya

G’oya: «K kalitidan davom et». Kursor - saralangan toʻplamdagi pozitsiya.

Afzalliklar:
  • O (1) indeks mavjud bo’lganda davom etish uchun foydalanish.
  • Kolleksiya oʻzgarishlarida barqarorlik.
  • Chuqur sahifalardagi eng yaxshi latentlik.
Minuslar:
  • Qatʼiy belgilangan, noyob va monoton saralash kalitlari kerak.
  • Amalga oshirish va tuzatish qiyinroq.
SQL namunasi (seek):
sql
-- Resumption after steam (created_at, id) = (:last_ts,:last_id)
SELECT
FROM orders
WHERE (created_at, id) < (:last_ts,:last_id)
ORDER BY created_at DESC, id DESC
LIMIT 50;

2. 3 Continuation tokens (noaniq tokenlar)

G’oya: server «pozitsiya» kodlangan opaque-tokenni qaytaradi (va ehtimol shard/filtr holati). Mijoz ichki qismini tushunmaydi va shunchaki keyingi sahifa uchun tokenni qaytaradi.
Afzalliklari: moslashuvchanlik, APIni buzmasdan sxemani o’zgartirish qobiliyati.
Kamchiliklar: tokenlarning umr ko’rish muddatini boshqarish, deplolarda muvofiqlik.

2. 4 Vaqtinchalik va mantiqiy kursorlar

Time-based: «barcha yozuvlar T gacha», kursor - vaqt belgisi (append-only oqimlarida mos keladi).
Log-sequence/offset-based: kursor - logdagi siljish (Kafka offset, journal seq).
Global monotonic IDs: barqaror seek uchun saralanadigan kalitlar sifatida Snowflake/UUIDv7.

3) Kurslar va tokenlarni loyihalash

3. 1 Yaxshi kursor xususiyatlari

Shaffoflik (opaque): mijoz formatga bogʻliq emas.
Mualliflik/yaxlitlik: almashtirish/manipulyatsiyaning oldini olish uchun HMAC imzosi.
Kontekst: saralash, filtrlar, sxema versiyasi, tenant/shard.
Umr ko’rish muddati: TTL va «nomutanosiblik» (non-replay).
Oʻlchami: ixcham (<= 1-2 KB), URL uchun yaroqli.

3. 2 Token formati

Tavsiya etilgan stek: JSON → siqish (zstd/deflate) → Base64URL → HMAC.

Foydali yuklamaning tuzilmasi (misol):
json
{
"v": 3 ,//token version
"sort": ["created_at:desc","id:desc"],
"pos": {"created_at":"2025-10-30T12:34:56. 789Z","id":"987654321"},
"filters": {"user_id":"42","status":["paid","shipped"]},
"tenant": "eu-west-1",
"shards": [{"s ": "a, "" hi":"..."}] ,//optional: cross-shard context
"issued_at": "2025-10-31T14:00:00Z",
"ttl_sec": 3600
}

Yuqoriga’mac = HMAC (secret, payload)’qo’shiladi va hammasi bitta satrli tokenga kodlanadi.

3. 3 Xavfsizlik

Imzolash (HMAC/SHA-256).
Sezgir qiymatlar (PII) mavjud bo’lganda (AES-GCM) shifrlash.
Serverda validatsiya: versiya, TTL, foydalanuvchi vakolatlari (RBAC/ABAC).

4) Muvofiqlik va invariantlar

4. 1 Barqaror saralash

Toʻliq determinizmdan foydalaning:’ORDER BY ts DESC, id DESC’.
Saralash kaliti noyob boʻlishi kerak (’id’ni tiebreaker sifatida qoʻshing).
Indeks saralash (covering index) ga mos kelishi kerak.

4. 2 Rasmlar (snapshot) va izolyatsiya

«Notoʻgʻri» sahifalar uchun read-consistent snapshot (MVCC/txid) dan foydalaning.
Agar snapshot maqsadga muvofiq bo’lmasa (qimmat/ko’p ma’lumotlar), kontraktni tuzing: «kursor pozitsiyadan qat’iy oldin elementlarni qaytaradi». Bu yangiliklar uchun tabiiy holat.

4. 3 Sahifalar orasiga qoʻyish/oʻchirish

Seek modeli «dublikatlar/oʻtkazmalar» ni minimallashtiradi.
Olib tashlash/oʻzgartirishda xatti-harakatlarni hujjatlashtiring: sahifalar orasidagi kamdan-kam «teshiklarga» yoʻl qoʻyiladi, lekin «vaqtga orqaga» emas.

5) Indekslash va identifikatorlar sxemalari

Kompozit indekslar qat’iy saralash tartibida:’(created_at DESC, id DESC)’.
Monoton ID: Snowflake/UUIDv7 vaqt tartibini beradi → tezlashtiradi seek.
Issiq kalitlar: shard-key (masalan,’tenant _ id’,’region’) orqali taqsimlang va shard ichida saralang.
ID generatorlari: «kelajak soatlari» (clock skew) - vaqt sinxronlashuvi, NTP sakrashda «regressiya» dan qoching.

6) Kross-shard paginatsiyasi

6. 1 Sxemalar

Scatter-Gather: barcha sharlarga parallel so’rovlar, mahalliy seek-kurslar, so’ngra agregatorda k-way merge.
Per-Shard Cursors: tokenda har bir shard boʻyicha pozitsiyalar mavjud.
Bounded fan-out: Bir qadamda shardlarni cheklang (rate limiting/timeout budget).

6. 2 Multi-shard uchun tokenlar

’{shard _ id, last_pos}' massivini saqlang. Keyingi qadamda har bir faol shard uchun qayta tiklang va global tartiblangan sahifani bering.

7) Protokol kontraktlari

7. 1 REST

Soʻrov:

GET /v1/orders? limit=50&cursor=eyJ2IjoiMyIsInNvcnQiOiJjcmVh... (opaque)
Javob:
json
{
"items": [ /... / ],
"page": {
"limit": 50,
"next_cursor": "eyJ2IjozLCJwb3MiOiJjcmVh...==",
"has_more": true
}
}
Tavsiyalar:
  • yuqori chegarali’limit’(masalan, max = 200).
  • ’next _ cursor’ mavjud emas, agar’has _ more = false’boʻlsa.
  • GET idempotentligi,’next _ cursorsiz’javoblarning keshlanishi (birinchi sahifa oʻrnatilgan filtrlar va snapshot bilan).

7. 2 GraphQL (Relay-yondashuv)

Tipik’connection’kontrakti:
graphql type Query {
orders(first: Int, after: String, filter: OrderFilter): OrderConnection!
}

type OrderConnection {
edges: [OrderEdge!]!
pageInfo: PageInfo!
}

type OrderEdge {
node: Order!
cursor: String! // opaque
}

type PageInfo {
hasNextPage: Boolean!
endCursor: String
}

’cursor’ shaffof bo’lmasligi va imzolanishi kerak; «xom Base64 (id)» dan HMACsiz foydalanmang.

7. 3 gRPC

’page _ size’ va’page _ token’dan foydalaning:
proto message ListOrdersRequest {
string filter = 1;
int32 page_size = 2;
string page_token = 3; // opaque
}

message ListOrdersResponse {
repeated Order items = 1;
string next_page_token = 2; // opaque bool has_more = 3;
}

7. 4 Oqimlar va WebSockets

Davomli lentalar uchun: kursor «oxirgi koʻrilgan offset/ts» sifatida.

Rekonnektda’resume _ from’ni qoʻllab-quvvatlang:
json
{ "action":"subscribe", "topic":"orders", "resume_from":"2025-10-31T12:00:00Z#987654321" }

8) Keshlash, oldindan yuklash, CDN

ETAG/If-None-Match - birinchi sahifa uchun.
Ochiq roʻyxatlar uchun qisqa TTL (masalan, 5-30 s) bilan Cache-Control.
Prefetch:’next _ cursor’va maslahatlarni qaytaring (’Link: rel =’next’’), mijoz keyingi sahifani oldindan yuklashi mumkin.
Variatsiyalar:’filter/sort/locale/tenant’ni kesh qismining kaliti sifatida hisobga oling.

9) Yuklamani boshqarish va limitlash

Yuqori chegara’limit’, masalan 200.
Server-side backpressure: agar so’rov vaqti> budget bo’lsa, javobda’limit’ni kamaytiring (va mijozga haqiqiy sahifaning o’lchamini aniq ayting).
Rate limits/token/tenant.
Timeout/Retry: eksponensial pauza, idempotent takroriy soʻrovlar.

10) UX-jihatlar

Skroll vs raqamlash: cheksiz aylantirish → kursorlar; raqamlar → offset (lekin yangilanishdagi noaniqlikni tushuntiring).
«Joyga qaytish» tugmasi: Mijoz kursorlarini saqlang.
Boʻsh sahifalar: agar’has _ more = false’boʻlsa, «Boshqa» tugmasini koʻrsatmang.
Barqaror chegaralar: aniq’total’ni faqat arzon boʻlsa koʻrsating (aks holda taxminan’approx _ total’).

11) Test va edge-keyslar

Chek varaqlari:
  • Barqaror saralash: bir xil’ts’elementlari «miltillamaydi».
  • Qoʻyish/oʻchirish: betlar kesishmasida takrorlash koʻrinmaydi.
  • Sahifalar orasidagi filtrlarni oʻzgartirish: token «eskirgan/mos kelmaydigan» sifatida chetga chiqishi kerak.
  • TTL tokeni: muddati tugaganidan keyin xato roʻy berdi.
  • Katta chuqurlik: yashirin chiziqli o’smaydi.
  • Multishard: to’g "ri merge-tartib, starvation" sekin "shardlarning yo’qligi.
Property-based test (psevdokod) misoli:
python
Generate N entries with random inserts between calls
Verify that all pages are merged = = whole ordered fetch

12) Kuzatuv va SLO

Metriklar:
  • ’list _ request _ latency _ ms’ (P50/P95/P99) sahifaning uzunligi boʻyicha.
  • ’seek _ index _ hit _ ratio’ (qoplovchi indeks boʻyicha oʻtgan soʻrovlar ulushi).
  • ’next _ cursor _ invalid _ rate’ (validatsiya xatosi/TTL/imzolar).
  • ’merge _ fanout’ (sahifa uchun foydalanilgan shardlar soni).
  • ’duplicates _ on _ boundary’ va’gaps _ on _ boundary’(mijoz telemetriyasidagi detekt).
Logi/treysing:
  • ’cursor _ id’ ni log bilan bogʻlang va payloadni yashiring.
  • Spanlarni teglang:’page _ size’,’source _ shards’,’db _ index _ used’.
SLO misoli:
  • Foydalanish imkoniyati: 99. ’List’ usullarida 9%.
  • Maxfiylik: P95 <200 ms uchun’page _ size <= 50’lokal shardda.
  • Token xatosi: <0. Umumiy qoʻngʻiroqlar sonining 1%.

13) Migratsiya va muvofiqlik

Tokenga’v’qoʻshing va N haftaning eski versiyalarini qoʻllab-quvvatlang.
Saralashning kalitlari almashtirilganda,’409 Conflict’xatosini yangi listingni kursorsiz bajarish uchun yuboring.
Halokatli hodisa (barcha tokenlarning revoklari):’signing _ key _ id’ni oʻzgartiring va eskisini rad eting.

14) Amalga oshirish namunalari

14. 1 Token generatsiyasi (psevdokod)

python payload = json. dumps({...}). encode()
compressed = zlib. compress(payload)
mac = hmac_sha256(signing_key, compressed)
token = base64url_encode(mac + compressed)

14. 2 Token validatsiyasi

python raw = base64url_decode(token)
mac, compressed = raw[:32], raw[32:]
assert mac == hmac_sha256(signing_key, compressed)
payload = json. loads(zlib. decompress(compressed))
assert now() - payload["issued_at"] < payload["ttl_sec"]
assert payload["filters"] == req. filters

14. 3 Kompozit kalitli Seek-soʻrov

sql
-- Page # 1
SELECT FROM feed
WHERE tenant_id =:t
ORDER BY ts DESC, id DESC
LIMIT:limit;

-- Next pages, continued after (ts0, id0)
SELECT FROM feed
WHERE tenant_id =:t
AND (ts <:ts0 OR (ts =:ts0 AND id <:id0))
ORDER BY ts DESC, id DESC
LIMIT:limit;

15) Xavfsizlik va muvofiqlik

Tokenlarga PII chiqariladigan xom maydonlarni kiritmang.
TTLni imzolang va cheklang.
Tokenlarni foydalanuvchilar o’rtasida murosasiz qilishga harakat qiling (payload’sub/tenant/roles’ga yozing va validatsiya paytida solishtiring).
Faqat tokenlarning xeshlarini yozib oling.

16) Tez-tez xatolar va anti-patternlar

Base64 (id) kursor sifatida: soxtalashtirish/tanlash oson, saralash almashtirilganda shartnomani buzadi.
tie-breaker yo’qligi:’ORDER BY ts DESC’bez’id’→ dublikatlar/poygalar.
Tokenni nogironlashtirmagan sahifalar orasidagi filtrlarni almashtirish.
Chuqur OFFSET: sekin va oldindan aytib bo’lmaydigan.
TTL va versiyasiz tokenlar.

17) Joriy etishning mini-cheklisti

1. Saralashni aniqlab, oʻziga xos tie-breaker qoʻshing.
2. Ushbu tartib uchun yopish indeksini yarating.
3. Modelni tanlang: seek + shaffof boʻlmagan token.
4. Tokenning imzosini (va kerak boʻlsa shifrlashni) amalga oshiring.
5. TTL va versiyani oʻrnating.
6. ’has _ more’,’next _ cursor’shartnomalarini shakllantiring va hujjatlashtiring.
7. Agar kerak bo’lsa, kross-shard sxemasi va k-way merge haqida o’ylang.
8. Metrik, alerta va SLO qo’shing.
9. Property-based sahifalar chegarasini testlar bilan yoping.
10. Tokenlarning migratsiya strategiyasini tavsiflang.

18) Yondashuvni tanlash bo’yicha qisqacha tavsiyalar

«Sahifa raqami» muhim boʻlgan kataloglar/qidiruvlar va taxminan total: masalan’OFFSET/LIMIT’+ kesh; total taxminiy ekanligini ayting.
Lentalar, tahlillar, chuqur roʻyxatlar, yuqori RPS: faqat cursor/seek.
Shardlangan/taqsimlangan kolleksiyalar: per-shard cursors + merge token.
/ CDC oqimlari: kursorlar offsets/ts sifatida yangilanmoqda.

19) API kelishuvining misoli (xulosa)

`GET /v1/items? limit=50&cursor=...`

Javob har doim’page’ni oʻz ichiga oladi. limit`, `page. has_more'’opsion’page. next_cursor`.
TTL bilan imzolangan noaniq kursor.
Saralash aniqlangan:’ORDER BY created_at DESC, id DESC’.
Toʻplamdagi xatti-harakatlar: elementlar kursorga nisbatan «orqaga qaytmaydi».
Metrika va xatolar standartlashtirilgan:’invalid _ cursor’,’expired _ cursor’,’mismatch _ filters’.

Ushbu maqola, hatto katta ma’lumotlar, shardlash va faol ravishda o’zgaruvchan yozuvlar to’plami sharoitida ham tez, oldindan aytib bo’ladigan va xavfsiz bo’lib qoladigan paginatsiyani loyihalash uchun arxitektura tamoyillari va tayyor namunalarni beradi.

Contact

Biz bilan bog‘laning

Har qanday savol yoki yordam bo‘yicha bizga murojaat qiling.Doimo yordam berishga tayyormiz.

Integratsiyani boshlash

Email — majburiy. Telegram yoki WhatsApp — ixtiyoriy.

Ismingiz ixtiyoriy
Email ixtiyoriy
Mavzu ixtiyoriy
Xabar ixtiyoriy
Telegram ixtiyoriy
@
Agar Telegram qoldirilgan bo‘lsa — javob Email bilan birga o‘sha yerga ham yuboriladi.
WhatsApp ixtiyoriy
Format: mamlakat kodi va raqam (masalan, +998XXXXXXXX).

Yuborish orqali ma'lumotlaringiz qayta ishlanishiga rozilik bildirasiz.