पृष्ठभूमि और संकेतक
1) पृष्ठभूमि की आवश्यकता क्यों है
पृष्ठभूमि ग्राहक द्वारा प्रेषित और प्रदान किए गए डेटा की मात्रा को सीमित करता है, भंडारण/नेटवर्क पर लोड को कम करता है, और संग्रह के माध्यम से "चलने" के लिए एक नियतात्मक तरी वास्तविक प्रणालियों में, पृष्ठभूमि न केवल 'पृष्ठ = 1 और सीमा = 50' है, बल्कि प्रोटोकॉल अनुबंधों और स्थिरता आक्रमणकारियों का एक सेट है।
विशिष्ट उद्देश्य:- अनुरोध के अनुसार विलंबता और मेमोरी नियंत्रण।
- डेटासेट बदलते समय स्थिर नेविगेशन (डालें/हटाएँ)।
- एक स्थान से फिर से शुरू करने की क्षमता (फिर से शुरू)।
- कैचिंग और प्रचार (प्रीफेच)।
- दुरुपयोग के खिलाफ सुरक्षा (दर सीमित, बैकप्रेशर)।
2) पैगिनेशन मॉडल
2. 1 ऑफसेट/लिमिट (पृष्ठ)
विचार: "एन लाइनों को छोड़ दें, एम।"
पेशेवरों: सादगी, लगभग किसी भी SQL/NoSQL के साथ संगत।
विपक्ष:- रैखिक गिरावट: बड़े OFSET के परिणामस्वरूप एक पूर्ण स्कैन/स्किप-लागत होती है।
- अनुरोध (ऑफसेट "फ्लोट") के बीच सम्मिलन/विलोपन के दौरान अस्थिरता।
- सटीक "नवीनीकरण" सुनिश्चित करना मुश्किल है।
sql
SELECT
FROM orders
ORDER BY created_at DESC, id DESC
OFFSET 1000 LIMIT 50;
2. 2 कर्सर/कीसेट/सीक-पैगिनेशन
विचार: "K कुंजी के साथ मिलता है। "संकेतक क्रमबद्ध सेट में स्थिति है।
पेशेवर:- ओ (1) सूचकांक के साथ जारी रखने के लिए पहुंच।
- संग्रह परिवर्तन के दौरान स्थिरता।
- गहरे "पृष्ठों" में सर्वश्रेष्ठ विलंबता।
- हमें कड़ाई से परिभाषित, अद्वितीय और नीरस प्रकार की कुंजियों की आवश्यकता है।
- लागू करने और डिबग करने में अधिक कठिन।
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 निरंतरता टोकन
विचार: सर्वर एक अपारदर्शी टोकन लौटाता है जिसमें "स्थिति" एन्कोड किया जाता है (और संभवतः शार्ड/फ़िल्टर की स्थिति)। क्लाइंट इंटर्नल को नहीं समझता है और बस अगले पृष्ठ के लिए एक टोकन लौटाता है।
पेशेवरों: लचीलापन, एपीआई को तोड़े बिना योजना को बदलने की क्षमता।
विपक्ष: टोकन आजीवन प्रबंधन, जमा के साथ संगतता।
2. 4 समय और तर्क संकेतक
समय-आधारित: "सभी रिकॉर्ड टी तक", कर्सर - समय मुहर (केवल-धागे के लिए उपयुक्त)।
लॉग-सीक्वेंस/ऑफसेट-आधारित: लॉग में कर्सर - ऑफसेट (काफ्का ऑफसेट, जर्नल seq)।
वैश्विक मोनोटोनिक आईडी: Snowflake/UUIDv7 स्थिर खोज के लिए छंटनी योग्य कुंजी के रूप में।
3) पाठ्यक्रम और टोकन डिजाइन करना
3. 1 अच्छा संकेतक गुण
अपारदर्शी-ग्राहक स्वतंत्र प्रारूप है।
लेखक/अखंडता: स्पूफिंग/हेरफेर को रोकने के लिए एचएमएसी हस्ताक्षर।
संदर्भ: छंटाई, फ़िल्टर, स्कीमा संस्करण, किरायेदार/शार्ड शामिल हैं।
लाइफटाइम: इंडेक्स/एक्सेस राइट्स बदलते समय टीटीएल और "नॉन-रीप्ले"।
आकार: URL के लिए उपयुक्त (<= 1-2 KB).
3. 2 टोकन प्रारूप
अनुशंसित स्टैक: JSON → संपीड़न (zstd/deflate) → Base64URL → HMAC।
नीतभार संरचना (उदाहरण):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
}
'mac = HMAC (गुप्त, पेलोड)' शीर्ष पर जोड़ा जाता है और सब कुछ एक स्ट्रिंग टोकन में एन्कोड किया जाता है।
3. 3 सुरक्षा
साइन (HMAC/SHA-256)।
संवेदनशील मूल्यों (पीआईआई) की उपस्थिति में वैकल्पिक रूप से एन्क्रिप्ट (एईएस-जीसीएम)।
सर्वर सत्यापन: संस्करण, टीटीएल, उपयोगकर्ता प्राधिकरण (आरबीएसी/एबीएसी)।
4) स्थिरता और अपरिवर्तनीय
4. 1 स्थिर छंटाई
पूर्ण नियतात्मकता का उपयोग करें: 'ऑर्डर बाय ts DESC, id DESC'।
सॉर्ट कुंजी अद्वितीय होनी चाहिए ('आईडी' को टाईब्रेकर के रूप में जोड़ें)।
सूचकांक को कवर सूचकांक से मेल खाना चाहिए।
4. 2 स्नैपशॉट और अलगाव
गैर-जंबो पृष्ठों के लिए, रीड-सुसंगत स्नैपशॉट (MVCC/txid) का उपयोग करें।
यदि स्नैपशॉट अव्यावहारिक (महंगा/बहुत सारा डेटा) है, तो एक अनुबंध तैयार करें: "कर्सर स्थिति से पहले तत्वों को सख्ती से लौटाता है। "यह समाचार फ़ीड के लिए स्वाभाविक है।
4. 3 पृष्ठों के बीच सम्मिलन/विलोपन
सीक-मॉडल "डुप्लिकेट/चूक" को कम करता है।
दस्तावेज़ विलोपन/संशोधन व्यवहार: पृष्ठों के बीच दुर्लभ "छेद" की अनुमति है, लेकिन "समय में वापस" नहीं।
5) अनुक्रमण और आईडी योजनाएं
समग्र सूचकांक कड़ाई से क्रम में हैं: '(created_at DESC, id DESC)'।
मोनोटोन आईडी: समय में आदेश दें - गति की तलाश करें।
हॉट कुंजी: शार्ड-कुंजी (उदाहरण के लिए, 'किरायेदार _ आईडी', 'क्षेत्र') द्वारा वितरित करें और शार्ड के अंदर सॉर्ट करें।
आईडी जनरेटर: टकराव और "घड़ीतिरछा" से बचें - एनटीपी कूदने के दौरान "प्रतिगमन"।
6) क्रॉस-शार्ड पेगिनेशन
6. 1 योजनाएं
स्कैटर-गेदर: सभी शार्क के समानांतर अनुरोध, स्थानीय तलाश पाठ्यक्रम, फिर एग्रीगेटर पर के-वे विलय।
प्रति-शार्ड कर्सर: टोकन में प्रत्येक शार्ड पर स्थिति होती है।
बाउंड फैन-आउट-लिमिट प्रति चरण (दर सीमित/टाइमआउट बजट) की संख्या।
6. मल्टी-शार्ड के लिए 2 टोकन
स्टोर करें '{shard _ id, last_pos}'। अगले चरण में, प्रत्येक सक्रिय शार्क के लिए फिर से शुरू करें और फिर से पकड़ें, जिससे विश्व स्तर पर क्रमबद्ध पृष्ठ मिल जाए।
7) प्रोटोकॉल अनुबंध
7. 1 REST
निवेदन:
GET /v1/orders? limit=50&cursor=eyJ2IjoiMyIsInNvcnQiOiJjcmVh... (opaque)
उत्तर:
json
{
"items": [ /... / ],
"page": {
"limit": 50,
"next_cursor": "eyJ2IjozLCJwb3MiOiJjcmVh...==",
"has_more": true
}
}
सिफारिशें:
- 'लिमिट' विथ एक ऊपरी सीमा (उदाहरण के लिए, अधिकतम = 200)।
- 'next _ cursor' गायब है अगर 'has _ more = fall'।
- GET idempotence, 'next _ cursor' (फिक्स्ड फिल्टर और स्नैपशॉट के साथ पहला पृष्ठ) के बिना प्रतिक्रियाओं की कैचबिलि
7. 2 ग्राफक्यूएल (रिले दृष्टिकोण)
विशिष्ट 'कनेक्शन' संविदा: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' must अपारदर्शी और हस्ताक्षरित हो; HMAC के बिना "रॉ Base64 (id)" का उपयोग न करें।
7. 3 जीआरपीसी
'पृष्ठ आकार' और 'पृष्ठ _ टोकन' का उपयोग करें: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 थ्रेड्स और वेब सॉकेट्स
निरंतर टेप के लिए: संकेतक "अंतिम बार देखा गया ऑफसेट/टीएस" के रूप में।
पुनर्संयोजन के दौरान 'फिर से शुरू करें' समर्थन करें:json
{ "action":"subscribe", "topic":"orders", "resume_from":"2025-10-31T12:00:00Z#987654321" }
8) कैशिंग, प्रीलोड, सीडीएन
स्थिर फिल्टर के साथ पहले पृष्ठ के लिए ETag/if-None-Match।
सार्वजनिक सूचियों के लिए एक छोटे टीटीएल (उदाहरण के लिए, 5-30 एस) के साथ कैश-कंट्रोल।
Prefetch: 'next _ cursor' और संकेत ('Link: rel = "next"), क्लाइंट अगले पृष्ठ को पहले से लोड कर सकता है।
भिन्नताएँ: कैश भाग की कुंजी के रूप में 'फ़िल्टर/सॉर्ट/लोकेल/किरायेदार' पर विचार करें।
9) लोड प्रबंधन और सीमित
ऊपरी बाध्य 'लिमिट', उदा। 200.
सर्वर-साइड बैकप्रेशर: यदि अनुरोध समय> बजट है, तो प्रतिक्रिया में 'सीमा' को कम करें (और स्पष्ट रूप से क्लाइंट को वास्तविक पृष्ठ आकार बताएं)।
दर प्रति उपयोगकर्ता/टोकन/किरायेदार।
टाइमआउट/रीट्री: घातीय ठहराव, पहचाने गए दोहराए गए अनुरोध।
10) यूएक्स पहलू
नंबरिंग के खिलाफ स्क्रॉलिंग: अनंत स्क्रॉलिंग → कर्सर; संख्या पृष्ठ → ऑफसेट (लेकिन डेटा अपडेट करते समय अशुद्धि की व्याख्या)।
स्थान बटन पर लौटें: क्लाइंट कर्सर स्टैक को संग्रहीत करें।
रिक्त पृष्ठों: यदि 'अधिक है = गलत', अधिक बटन न दिखाएँ.
स्थिर सीमाएं: सटीक 'कुल' केवल तभी दिखाएं जब यह सस्ता हो (अन्यथा यह एक अनुमानित 'दृष्टिकोण _ कुल' हो)।
11) परीक्षण और किनारे के मामले
चेकलिस्ट:- स्थिर छंटाई: एक ही 'ts' वाले आइटम "पलक नहीं झपकाते हैं।"
- प्रविष्ट/विलोपित - डुप्लिकेट पृष्ठ चौराहे पर प्रकट नहीं होते हैं।
- पृष्ठों के बीच फिल्टर बदलें: टोकन को अप्रचलित/असंगत के रूप में अस्वीकार किया जाना चाहिए।
- टोकन टीटीएल: समाप्ति के बाद वैध त्रुटि.
- महान गहराई: विलंबता रैखिक रूप से नहीं बढ़ ती है।
- मल्टीहार्ड: सही मर्ज-ऑर्डर, भुखमरी की अनुपस्थिति "धीमी" शार्क।
python
Generate N entries with random inserts between calls
Verify that all pages are merged = = whole ordered fetch
12) अवलोकन और एसएलओ
मेट्रिक्स:- पृष्ठ लंबाई के अनुसार 'list _ request _ latency _ ms' (P50/P95/P99)।
- 'search _ index _ hit _ ratio' (कवर इंडेक्स द्वारा छोड़े गए अनुरोधों का अनुपात)।
- 'next _ cursor _ inmalid _ rate' (सत्यापन/TTL/हस्ताक्षर त्रुटियां).
- 'मेर्ज _ फैनआउट' (प्रति पृष्ठ शामिल शार्ड्स की संख्या)।
- 'duplicates _ on _ barmary' and 'gaps _ on _ comminary' (क्लाइंट टेलीमेट्री पर पता लगाना)।
- लॉग, मास्क पेलोड में 'कर्सर _ आईडी' को सहसंबंधित करें.
- टैग स्पैन: 'पृष्ठ _ size', 'source _ shards', 'db _ index _ used'.
- उपलब्धता: 99। 9% 'सूची' विधियों पर.
- विलंबता: P95 <200 ms 'पृष्ठ _ size <= 50' के लिए एक स्थानीय चार्ज में।
- टोकन त्रुटि: <0। कॉल की कुल संख्या का 1%।
13) माइग्रेशन और इंटरऑपरेबिलिटी
टोकन में 'v' सक्षम करें और N सप्ताह के पुराने संस्करणों का समर्थन करें।
सॉर्ट कुंजी बदलते समय - एक संकेतक के बिना ताजा लिस्टिंग करने के लिए एक संकेत के साथ "सॉफ्ट" त्रुटि '409 संघर्ष भेजें।
भयावह मामला (सभी टोकन की दहाड़): 'साइनिंग _ key _ id' बदलें और पुराने लोगों को अस्वीकार करें।
14) कार्यान्वयन उदाहरण
14. 1 टोकन पीढ़ी (स्यूडोकोड)
python payload = json. dumps({...}). encode()
compressed = zlib. compress(payload)
mac = hmac_sha256(signing_key, compressed)
token = base64url_encode(mac + compressed)
14. 2 टोकन सत्यापन
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 समग्र कुंजी के साथ क्वेरी की तलाश करें
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) सुरक्षा और अनुपालन
कच्चे खेतों को टोकन में शामिल न करें जिससे पीआईआई प्राप्त किया जा सकता है।
हस्ताक्षर करें और टीटीएल को सीमित करें।
प्रयोक्ताओं के बीच टोकन असहनीय बनाने की कोशिश करें (पेलोड में 'उप/किरायेदार/भूमिकाएं' लिखें और सत्यापन के दौरान जांच करें)।
केवल टोकन हैश लॉग करें।
16) लगातार त्रुटियां और विरोधी पैटर्न
Base64 (आईडी) एक संकेतक के रूप में: नकली/लेने में आसान, इस तरह को बदलते समय अनुबंध को तोड़ ता है।
कोई टाई-ब्रेकर नहीं: 'ऑर्डर BY ts DESC' बिना 'id duplicates/jumps.
टोकन को अमान्य किए बिना पृष्ठों के बीच फिल्टर बदलें।
डीप ऑफ़ सेट: धीमी और अप्रत्याशित।
संस्करण और टीटीएल के बिना टोकन।
17) मिनी चेकलिस्ट कार्यान्वयन
1. सॉर्ट को परिभाषित करें और एक अद्वितीय टाई-ब्रेकर जोड़ें।
2. इस क्रम के लिए एक विस्तृत सूची बनाएँ।
3. मॉडल चुनें: खोज + अपारदर्शी टोकन।
4. टोकन हस्ताक्षर लागू करें (और, यदि आवश्यक हो, एन्क्रिप्शन)।
5. TTL और वर्शनिंग लेट करें।
6. दस्तावेज़ 'has _ more', 'next _ cursor' संविदाएँ बनाएँ.
7. एक क्रॉस-शार्ड योजना (यदि आवश्यक हो) और के-वे विलय पर विचार करें।
8. मैट्रिक्स, अलर्ट और एसएलओ जोड़ें।
9. परीक्षणों के साथ संपत्ति-आधारित पृष्ठ सीमाओं को कवर
10. टोकन के लिए प्रवासन रणनीति का वर्णन करें।
18) दृष्टिकोण चुनने के लिए संक्षिप्त सिफारि
निर्देशिका/खोज जहां "पृष्ठ संख्या" और अनुमानित कुल महत्वपूर्ण हैं: चलो कहते हैं 'OFFSET/LIMITE' + कैश; रिपोर्ट कि कुल अनुमानित है।
फ़ीड, एनालिटिक्स, गहरी सूची, उच्च आरपीएस: कर्सर/खोज।
शार्डी/वितरित संग्रह: प्रति-शार्ड कर्सर + विलय टोकन।
Threads/CDC: पुनः प्रारंभ के साथ ऑफसेट/ts के रूप में संकेतक.
19) एपीआई समझौते का उदाहरण (सारांश)
'GET/v1/आइटम? सीमा = 50 और कर्सर =... '
उत्तर में हमेशा 'पृष्ठ' शामिल होता है। सीमा ',' पृष्ठ। has_more', वैकल्पिक 'पेज। next_cursor'।
संकेतक अपारदर्शी है, टीटीएल के साथ हस्ताक्षरित है।
सॉर्ट नियतात्मक 'ऑर्डर बाय created_at DESC, id DESC' है।
परिवर्तन व्यवहार- आइटम संकेतक के सापेक्ष "वापस जाएँ" सेट नहीं करता है.
मेट्रिक्स और त्रुटियां मानकीकृत हैं: 'अवैध _ कर्सर', 'एक्सपायर्ड _ कर्सर', 'बेमेल _ फ़िल्टर'.
यह लेख पृष्ठभूमि को डिजाइन करने के लिए वास्तुशिल्प सिद्धांतों और तैयार पैटर्न प्रदान करता है जो बड़े डेटा, शर्मीले और सक्रिय रूप से बदलते रिकॉर्डसेट में भी तेज, अनुमानित और सुरक्षित रहता है।