GH GambleHub

Σελιδοδείκτες και δρομείς

1) Γιατί απαιτείται η σελιδοποίηση

Η σελιδοποίηση περιορίζει την ποσότητα των δεδομένων που διαβιβάζονται και παρέχονται από τον πελάτη, μειώνει το φορτίο στην αποθήκευση/στα δίκτυα και θέτει έναν καθοριστικό τρόπο για να «περπατήσει» μέσα από τη συλλογή. Στα πραγματικά συστήματα, η σελιδοποίηση δεν είναι μόνο «σελίδα = 1 & όριο = 50», αλλά ένα σύνολο συμβάσεων πρωτοκόλλου και αναλλοίωτων συνοχής.

Τυπικοί στόχοι:
  • Καθυστέρηση και έλεγχος μνήμης ανά αίτημα.
  • Σταθερή πλοήγηση κατά την αλλαγή ενός συνόλου δεδομένων (εισαγωγή/διαγραφή).
  • Η ικανότητα επανάληψης από έναν τόπο (επανάληψη).
  • Κατακράτηση και κήρυγμα (prefetch).
  • Προστασία από την κατάχρηση (περιορισμός του ποσοστού, αντίθλιψη).

2) Μοντέλα σελιδοποίησης

2. 1 OFFET/ΟΡΙΑΚΟ (σελιδοποιημένο)

Η ιδέα: «παραλείψτε N γραμμές, επιστρέψτε M.»

Pros: απλότητα, συμβατή με σχεδόν οποιοδήποτε SQL/NoSQL.

Κώνοι:
  • Γραμμική υποβάθμιση: τα μεγάλα OFFSET οδηγούν σε πλήρη σάρωση/παράλειψη κόστους.
  • Αστάθεια κατά την εισαγωγή/διαγραφή μεταξύ αιτήσεων (αντισταθμίζει «επίπλευση»).
  • Είναι δύσκολο να εξασφαλιστεί η ακριβής «δυνατότητα ανανέωσης».
Παράδειγμα SQL:
sql
SELECT
FROM orders
ORDER BY created_at DESC, id DESC
OFFSET 1000 LIMIT 50;

2. 2 Δρομέας/Κλειδί/Ειδοποίηση αναζήτησης

Η ιδέα: "προχωρήστε με το κλειδί Κ. "Ο δρομέας είναι η θέση στο επιλεγμένο σύνολο.

Υπέρ:
  • O (1) πρόσβαση για συνέχιση με δείκτη.
  • Σταθερότητα κατά τις αλλαγές συλλογής.
  • Καλύτερη καθυστέρηση σε βαθιές «σελίδες».
Κώνοι:
  • Χρειαζόμαστε αυστηρά καθορισμένα, μοναδικά και μονότονα κλειδιά.
  • Πιο δύσκολο να εφαρμοστεί και να αποσφαλματωθεί.
Παράδειγμα SQL (αναζήτηση):
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 Δρομείς χρόνου και λογικής

Χρονοσφραγίδα: «όλες οι εγγραφές έως T», δρομέας - χρονοσφραγίδα (κατάλληλη μόνο για προσθήκη νημάτων).
Log-sequence/offset-based: δρομέας - όφσετ στο ημερολόγιο (Kafka offset, journal seq).
Παγκόσμιες μονοτονικές ταυτότητες: Snowflake/UUIDv7 ως θολά κλειδιά για σταθερή αναζήτηση.

3) Σχεδιασμός μαθημάτων και μαρκών

3. 1 Καλές ιδιότητες δρομέα

Αδιαφανές-Ο πελάτης είναι ανεξάρτητος.
Συγγραφέας/ακεραιότητα: υπογραφή HMAC για την πρόληψη της παραποίησης/παραποίησης.
Πλαίσιο: περιλαμβάνει διαλογή, φίλτρα, έκδοση σχήματος, ενοικιαστής/θραύσμα.
Διάρκεια ζωής: TTL και «μη αναπαραγωγή» κατά την αλλαγή δεικτών/δικαιωμάτων πρόσβασης.
Μέγεθος: συμπαγές (<= 1-2 KB) κατάλληλο για URL.

3. Μορφότυπος 2

Η συνιστώμενη στοίβα: JSON → συμπίεση (zstd/αποπληθωρισμός) → 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).
Προαιρετικά κρυπτογράφηση (AES-GCM) παρουσία ευαίσθητων τιμών (PII).
Επικύρωση εξυπηρετητή: έκδοση, TTL, αρχή χρήστη (RBAC/ABAC).

4) Συνέπεια και αναλλοίωτες

4. 1 Σταθερή διαλογή

Χρήση πλήρους προσδιορισμού: 'ORDER BY ts DESC, id DESC'.
Το πλήκτρο ταξινόμησης πρέπει να είναι μοναδικό (προσθήκη 'id' ως tipebreaker).
Ο δείκτης πρέπει να αντιστοιχεί στον δείκτη κάλυψης.

4. 2 Στιγμιότυπα και απομόνωση

Για μη jumbo σελίδες, χρησιμοποιήστε στιγμιότυπο με συνοχή ανάγνωσης (MVCC/txid).
Αν το στιγμιότυπο δεν είναι πρακτικό (ακριβά/πολλά δεδομένα), διατυπώστε ένα συμβόλαιο: "ο δρομέας επιστρέφει στοιχεία αυστηρά πριν από τη θέση. "Αυτό είναι φυσικό για ειδήσεις.

4. 3 Προσθήκες/διαγραφές μεταξύ σελίδων

Το μοντέλο αναζήτησης ελαχιστοποιεί τα «αντίγραφα/παραλείψεις».
Συμπεριφορά διαγραφής/τροποποίησης εγγράφου: επιτρέπονται σπάνιες «τρύπες» μεταξύ σελίδων, αλλά όχι «πίσω στο χρόνο».

5) Συστήματα τιμαριθμικής αναπροσαρμογής και ταυτότητας

Οι σύνθετοι δείκτες είναι αυστηρά σε σειρά ταξινόμησης: '(created_at DESC, id DESC)'.
Μονοτονικές ταυτότητες: Snowflake/UUIDv7 δίνετε τάξη στο χρόνο → επιταχύνετε την αναζήτηση.
Καυτά κλειδιά: διανομή με θραύσμα (για παράδειγμα, 'ενοικιαστής _ id', 'περιφέρεια') και ταξινόμηση μέσα στο θραύσμα.
ID γεννήτριες: αποφυγή συγκρούσεων και «ρολόι skew» - συγχρονισμός χρόνου, «παλινδρόμηση» κατά τη διάρκεια άλματα NTP.

6) Cross-shard pagination

6. 1 Συστήματα

Scatter-Gather: παράλληλα αιτήματα σε όλα τα θραύσματα, τοπικά μαθήματα αναζήτησης, στη συνέχεια k-way συγχωνεύονται στο σύνολο.
Per-Shard Cursors: Το σύμβολο περιέχει θέσεις σε κάθε θραύσμα.
Οριοθετημένος ανεμιστήρας-out-Limit ο αριθμός των θραυσμάτων ανά βήμα (περιορισμός επιτοκίου/προϋπολογισμός χρονικού περιθωρίου).

6. 2 Μάρκες για πολλαπλά θραύσματα

Φυλάσσετε τη διάταξη '{shard _ id, last_pos}'. Στο επόμενο βήμα, συνεχίστε για κάθε ενεργό θραύσμα και κρατήστε ξανά, δίνοντας την παγκόσμια ταξινομημένη σελίδα.

7) Συμβάσεις πρωτοκόλλου

7. 1 ΑΝΑΠΑΥΣΗ

Αίτηση:

GET /v1/orders? limit=50&cursor=eyJ2IjoiMyIsInNvcnQiOiJjcmVh... (opaque)
Απάντηση:
json
{
"items": [ /... / ],
"page": {
"limit": 50,
"next_cursor": "eyJ2IjozLCJwb3MiOiJjcmVh...==",
"has_more": true
}
}
Συστάσεις:
  • 'limit' with a ανώτερο όριο (για παράδειγμα, max = 200).
  • 'next _ cursor' is λείπει αν 'has _ more = false'.
  • idempotence, cachability των απαντήσεων χωρίς 'next _ cursor' (πρώτη σελίδα με σταθερά φίλτρα και στιγμιότυπο).

7. 2 GraphQL (Προσέγγιση αναμετάδοσης)

Τυπική σύμβαση «σύνδεσης»:
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 να είναι αδιαφανές και υπογεγραμμένο· δεν χρησιμοποιούν «ακατέργαστο Base64 (id)» χωρίς HMAC.

7. 3 gRPC

Χρήση 'page _ size' και 'page _ token':
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 νήματα και WebSockets

Για συνεχείς ταινίες: δρομέας ως «τελευταία εμφάνιση όφσετ/ts».

Υποστήριξη 'επανάληψη _ από' κατά την επανασύνδεση:
json
{ "action":"subscribe", "topic":"orders", "resume_from":"2025-10-31T12:00:00Z#987654321" }

8) Αποθήκευση, Κήρυγμα, CDN

ETag/If-No-Match για την πρώτη σελίδα με σταθερά φίλτρα.
Cache-Control με σύντομο TTL (για παράδειγμα, 5-30 s) για δημόσιους καταλόγους.
Prefetch: επιστροφή 'next _ cursor' και υποδείξεις ('Link: rel = "nex '), ο πελάτης μπορεί να προφορτώσει την επόμενη σελίδα.
Παραλλαγές: Θεωρήστε το «φίλτρο/είδος/τοποθεσία/ενοικιαστής» ως το κλειδί του μέρους της κρύπτης.

9) Διαχείριση και περιορισμός του φορτίου

Ανώτερο όριο 'limit', π.χ. 200.
Ανταπόκριση εξυπηρετητή: αν ο χρόνος αίτησης είναι> προϋπολογισμός, μειώστε το 'όριο' στην απάντηση (και πείτε ρητά στον πελάτη το πραγματικό μέγεθος σελίδας).
Όρια τιμών ανά χρήστη/μάρκα/ενοικιαστή.
Timeout/Retry: εκθετική παύση, idempotent επαναλαμβανόμενες αιτήσεις.

10) Πτυχές UX

Κύλιση κατά της αρίθμησης: άπειροι κύλιση → δρομείς. αριθμός σελίδων → όφσετ (αλλά εξηγήστε την ανακρίβεια κατά την επικαιροποίηση των δεδομένων).
Επιστροφή στο κουμπί τοποθέτησης: Αποθήκευση της στοίβας δρομέα πελάτη.
Κενές σελίδες: Αν 'έχει _ περισσότερα = ψευδή', μην εμφανίσετε το κουμπί More.
Σταθερά όρια: εμφανίστε το ακριβές «σύνολο» μόνο εάν είναι φθηνό (διαφορετικά πρόκειται για προσέγγιση «προσέγγιση _ σύνολο»).

11) Δοκιμές και ακμές

Κατάλογος επιλογών:
  • Σταθερή διαλογή: Τα αντικείμενα με το ίδιο 'ts' δεν «αναβοσβήνουν».
  • Ένθετα/Διαγραφές - Τα αντίγραφα δεν εμφανίζονται στην τομή της σελίδας.
  • Αλλαγή φίλτρων μεταξύ σελίδων: Το Token πρέπει να απορριφθεί ως παρωχημένο/ασύμβατο.
  • Tken TL: Έγκυρο σφάλμα μετά τη λήξη.
  • Μεγάλο βάθος: Η καθυστέρηση δεν αναπτύσσεται γραμμικά.
  • Multishard: σωστή τάξη συγχώνευσης, απουσία «αργών» θραυσμάτων λιμοκτονίας.
Παράδειγμα δοκιμής με βάση ιδιότητες (ψευδο-κωδικός):
python
Generate N entries with random inserts between calls
Verify that all pages are merged = = whole ordered fetch

12) Παρατηρησιμότητα και SLO

Μετρήσεις:
  • 'list _ request _ latency _ m ( ) ανά μήκος σελίδας.
  • 'search _ index _ hit _ ratio' (το ποσοστό των αιτήσεων που απομένουν από τον δείκτη κάλυψης).
  • 'next _ cursor _ invalid _ rate' (σφάλματα επικύρωσης/TTL/υπογραφής).
  • 'merge _ fanout' (αριθμός εμπλεκόμενων θραυσμάτων ανά σελίδα).
  • 'duplicates _ on _ boundary' and 'gaps _ on _ boundary' (ανίχνευση της τηλεμετρίας των πελατών).
Καταγραφές/ιχνηλάτηση:
  • Συσχετίστε το 'δρομέας _ id' στα αρχεία καταγραφής, το ωφέλιμο φορτίο μάσκας.
  • Εκτάσεις ετικετών: 'page _ size', 'source _ shard ,' db _ index _ used '.
Παράδειγμα SLO:
  • Διαθεσιμότητα: 99. 9% στις μεθόδους «λίστας».
  • Καθυστέρηση: P95 <200 ms για «σελίδα _ μέγεθος <= 50» σε τοπική χρέωση.
  • Σφάλμα ένδειξης: <0. 1% του συνολικού αριθμού των προσκλήσεων υποβολής προτάσεων.

13) Μετανάστευση και διαλειτουργικότητα

Ενεργοποίηση του 'v' στη μάρκα και υποστήριξη παλαιότερων εκδόσεων των N εβδομάδων.
Όταν αλλάζετε κλειδιά ταξινόμησης - στείλτε ένα «μαλακό» σφάλμα '409 Σύγκρουση' με μια πρωτοβουλία να εκτελέσετε μια νέα λίστα χωρίς δρομέα.
Καταστροφική περίπτωση (βρυχηθμός όλων των μαρκών): αλλαγή 'υπογραφή _ κλειδί _ 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. Αναζητήστε ερώτηση με σύνθετο κλειδί

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) Ασφάλεια και συμμόρφωση

Μη συμπεριλαμβάνετε τα ακατέργαστα πεδία σε μάρκες από τις οποίες μπορεί να προκύψει PII.
Υπογραφή και περιορισμός του TTL.
Προσπαθήστε να κάνετε τις μάρκες απαράδεκτες μεταξύ των χρηστών (γράψτε «υπο/ενοικιαστής/ρόλοι» στο ωφέλιμο φορτίο και ελέγξτε κατά την επικύρωση).
Καταγραφή μόνο συμβολικών hashes.

16) Συχνά σφάλματα και αντι-πρότυπα

(id) ως δρομέας: εύκολο να προσποιηθεί/να πάρει, σπάει το συμβόλαιο κατά την αλλαγή του είδους.
Χωρίς διακόπτη ισοπαλίας: 'ORDER BY ts DESC' χωρίς 'id' → αντίγραφα/άλματα.
Αλλαγή φίλτρων μεταξύ σελίδων χωρίς ακύρωση της μάρκας.
Βαθιά OFFSET: Αργή και απρόβλεπτη.
Μάρκες χωρίς έκδοση και TTL.

17) Εφαρμογή μίνι καταλόγου ελέγχου

1. Ορισμός της ταξινόμησης και προσθήκη ενός μοναδικού διακόπτη ισοπαλίας.
2. Δημιουργία ενός ευρετηρίου για αυτή τη σειρά.
3. Επιλογή μοντέλου: αναζήτηση + αδιαφανές σύμβολο.
4. Εφαρμογή συμβολικής υπογραφής (και, εάν είναι απαραίτητο, κρυπτογράφησης).
5. Ορίστε το TTL και την έκδοση.
6. Διατύπωση και έγγραφο "έχει _ more ',' next _ cursor 'συμβάσεις.
7. Εξετάστε ένα σύστημα cross-shard (εάν είναι απαραίτητο) και συγχώνευση k-way.
8. Προσθήκη μετρήσεων, προειδοποιήσεων και SLO.
9. Καλύψτε τα όρια σελίδων που βασίζονται σε περιουσιακά στοιχεία με δοκιμές.
10. Περιγράψτε τη στρατηγική μετάβασης για τις μάρκες.

18) Σύντομες συστάσεις για την επιλογή μιας προσέγγισης

Καταλόγους/αναζητήσεις όπου ο «αριθμός σελίδας» και το κατά προσέγγιση σύνολο είναι σημαντικά: ας πούμε 'OFFSET/LIMIT' + cache? αναφέρει ότι το σύνολο είναι κατά προσέγγιση.
Ζωοτροφές, αναλύσεις, βαθιές λίστες, υψηλή RPS: δρομέας/αναζήτηση μόνο.
Shardy/κατανεμημένες συλλογές: per-shard cursors + menge token.
Νήματα/CDC: δρομείς ως αντισταθμίσεις/ts με επανάληψη.

19) Παράδειγμα συμφωνίας API (περίληψη)

'GET/v1/αντικείμενα όριο = 50 & δρομέας =... '

Η απάντηση περιλαμβάνει πάντα τη σελίδα. όριο ',' σελίδα. , προαιρετικό 'page. .
Ο δρομέας είναι αδιαφανής, υπογεγραμμένος, με TTL.
Η ταξινόμηση είναι deterministic 'ORDER BY created_at DESC, id DESC'.
Ορισμός συμπεριφοράς αλλαγής - Τα αντικείμενα δεν «επιστρέφουν» σε σχέση με τον δρομέα.
Οι μετρήσεις και τα σφάλματα είναι τυποποιημένα: 'άκυρο _ δρομέας', 'έληξε _ δρομέας', 'αναντιστοιχία _ φίλτρα'.

Το άρθρο αυτό παρέχει αρχιτεκτονικές αρχές και έτοιμα μοτίβα για το σχεδιασμό σελίδων που παραμένουν γρήγορες, προβλέψιμες και ασφαλείς ακόμα και σε μαζικά δεδομένα, ντροπαλές και ενεργά μεταβαλλόμενες ηχογραφήσεις.

Contact

Επικοινωνήστε μαζί μας

Επικοινωνήστε για οποιαδήποτε βοήθεια ή πληροφορία.Είμαστε πάντα στη διάθεσή σας.

Έναρξη ολοκλήρωσης

Το Email είναι υποχρεωτικό. Telegram ή WhatsApp — προαιρετικά.

Το όνομά σας προαιρετικό
Email προαιρετικό
Θέμα προαιρετικό
Μήνυμα προαιρετικό
Telegram προαιρετικό
@
Αν εισαγάγετε Telegram — θα απαντήσουμε και εκεί.
WhatsApp προαιρετικό
Μορφή: κωδικός χώρας + αριθμός (π.χ. +30XXXXXXXXX).

Πατώντας «Αποστολή» συμφωνείτε με την επεξεργασία δεδομένων.