التثبيت والمؤشرات
1) سبب الحاجة إلى التثبيت
يحد التثبيت من كمية البيانات التي يتم إرسالها وتقديمها من قبل العميل، ويقلل من الحمل على التخزين/الشبكات، ويضع طريقة حتمية «للمشي» خلال عملية الجمع. في الأنظمة الحقيقية، التثبيت ليس فقط «صفحة = 1 & حد = 50»، ولكن مجموعة من عقود البروتوكول وثوابت الاتساق.
الأهداف النموذجية:- الكمون والتحكم في الذاكرة لكل طلب.
- التنقل الثابت عند تغيير مجموعة البيانات (تدرج/تحذف).
- القدرة على الاستئناف من مكان ما (الاستئناف).
- التخزين المؤقت والتحميل المسبق (presetch).
- الحماية من سوء المعاملة (الحد من الأسعار والضغط الخلفي).
2) نماذج التثبيت
2. 1 OFFSET/LIMITE (page)
الفكرة: «تخطي خطوط N، أعد M».
الإيجابيات: البساطة، متوافقة مع أي SQL/NoSQL تقريبًا.
- التحلل الخطي: تؤدي الأوفست الكبيرة إلى مسح كامل/تكلفة تخطي.
- عدم الاستقرار أثناء الإدراج/الحذف بين الطلبات (يعوض «تعويم»).
- من الصعب ضمان «قابلية التجديد» الدقيقة.
sql
SELECT
FROM orders
ORDER BY created_at DESC, id DESC
OFFSET 1000 LIMIT 50;
2. 2 مؤشر/Keyset/Seek-pagination
الفكرة: "استمر في مفتاح K. "المؤشر هو الموضع في المجموعة المصنفة.
الإيجابيات:- O (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 مؤشرات الوقت والمنطق
يعتمد على الوقت: «جميع السجلات حتى T»، المؤشر - ختم الوقت (مناسب للخيط الملحق فقط).
Log-sequence/offset-based: cursor - offessed in the log (Kafka offset, journal seq).
المعرفات الرتيبة العالمية: Snowflake/UUIDv7 كمفاتيح قابلة للفرز للبحث المستقر.
3) تصميم الدورات والرموز
3. 1 خصائص المؤشر الجيد
Opaque-العميل مستقل التنسيق.
التأليف/النزاهة: توقيع HMAC لمنع الانتحال/التلاعب.
السياق: يشمل الفرز، المرشحات، إصدار المخطط، المستأجر/الشارد.
مدى الحياة: TTL و «عدم إعادة التشغيل» عند تغيير المؤشرات/حقوق الوصول.
الحجم: مضغوط (<= 1-2 كيلوبايت) مناسب لعنوان URL.
3. 2 تنسيق رمزي
المكدس الموصى به: ضغط → JSON (zstd/dreflate) → 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».
يجب أن يكون مفتاح الفرز فريدًا (أضف «هوية» كفاصل).
يجب أن يتطابق المؤشر مع مؤشر التغطية.
4. 2 لقطات وعزل
بالنسبة للصفحات غير الجامبو، استخدم لقطة متسقة للقراءة (MVCC/txid).
إذا كانت اللقطة غير عملية (باهظة الثمن/الكثير من البيانات)، صاغ عقدًا: "يعيد المؤشر العناصر بدقة قبل الموضع. "هذا أمر طبيعي لموجز الأخبار.
4. 3 الإدخالات/الحذف بين الصفحات
نموذج البحث يقلل من «التكرارات/الإغفالات».
سلوك حذف/تعديل المستند: يُسمح بـ «ثقوب» نادرة بين الصفحات، ولكن ليس «بالزمن».
5) مخططات الفهرسة والهوية
الفهارس المركبة مرتبة بدقة: «(created_at DESC، id DESC)».
معرفات Monotone: Snowflake/UUIDv7 تعطي النظام في الوقت المناسب → تسريع البحث.
المفاتيح الساخنة: قم بالتوزيع بواسطة مفتاح شظية (على سبيل المثال، «المستأجر _ id»، «المنطقة») وفرز داخل الشظية.
مولدات الهوية: تجنب الاصطدامات و «انحراف الساعة» - التزامن الزمني، «الانحدار» أثناء قفزات NTP.
6) استدعاء الشظايا المتقاطعة
6. 1 مخططات
Spatter-Gather: طلبات موازية لجميع الشظايا، دورات البحث المحلية، ثم اندماج k-way على المجمع.
Per-Shard Cursors: يحتوي الرمز المميز على مواضع على كل قطعة.
حد محدود لعدد الشظايا لكل خطوة (ميزانية تحديد المعدل/المهلة).
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' مع الحد العلوي (على سبيل المثال، الحد الأقصى = 200).
- "next _ المؤشر" مفقود إذا "has _ more = fall'.
- احصل على الغباء، وإمكانية اختزال الردود بدون «المؤشر التالي» (الصفحة الأولى مع مرشحات ثابتة ولقطة سريعة).
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
}
يجب أن تكون مبهمة وموقعة ؛ لا تستخدم «Base64 الخام (هوية)» بدون 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
للأشرطة المستمرة: المؤشر على أنه «آخر مرة شوهدت أوفست/تي إس».
دعم 'استئناف _ من' أثناء إعادة الاتصال:json
{ "action":"subscribe", "topic":"orders", "resume_from":"2025-10-31T12:00:00Z#987654321" }
8) التخزين المؤقت، التحميل المسبق، CDN
ETag/If-None-Match للصفحة الأولى مع مرشحات ثابتة.
Cache-Control مع TTL قصير (على سبيل المثال، 5-30 ثانية) للقوائم العامة.
Prefetch: عودة "المؤشر التالي" والتلميحات ("الرابط: rel =" التالي ")، يمكن للعميل تحميل الصفحة التالية مسبقًا.
الاختلافات: ضع في اعتبارك «المرشح/الفرز/الموقع/المستأجر» كمفتاح لجزء المخبأ.
9) إدارة الأحمال والحد منها
الحد الأعلى، على سبيل المثال 200.
الضغط الخلفي بجانب الخادم: إذا كان وقت الطلب> الميزانية، قلل «الحد» في الاستجابة (وأخبر العميل صراحة بحجم الصفحة الفعلي).
حدود الأسعار لكل مستخدم/رمز/مستأجر.
المهلة/إعادة التجربة: توقف أسي، طلبات متكررة غبية.
10) جوانب UX
التمرير ضد الترقيم: التمرير اللامتناهي → المؤشرات ؛ عدد الصفحات → أوفست (ولكن شرح عدم الدقة عند تحديث البيانات).
العودة إلى زر المكان: قم بتخزين كومة مؤشر العميل.
الصفحات الفارغة: إذا كان «لديه _ المزيد = خطأ»، فلا تظهر زر المزيد.
الحدود الثابتة: إظهار «المجموع» الدقيق فقط إذا كان رخيصًا (وإلا فهو «نهج _ إجمالي» تقريبي).
11) حالات الاختبار والحافة
القوائم المرجعية:- الفرز الثابت: العناصر التي تحتوي على نفس الأشياء لا «ترمش».
- تدرج/تحذف - لا تظهر نسخ مكررة عند تقاطع الصفحة.
- فلاتر التغيير بين الصفحات: يجب رفض الرمز المميز باعتباره عفا عليه الزمن/غير متوافق.
- الرمز TTL: خطأ صحيح بعد انتهاء الصلاحية.
- عمق كبير: الكمون لا ينمو خطيا.
- Multishard: ترتيب الدمج الصحيح، عدم وجود شظايا «بطيئة» للمجاعة.
python
Generate N entries with random inserts between calls
Verify that all pages are merged = = whole ordered fetch
12) إمكانية الرصد و SLO
المقاييس:- "list _ request _ latency _ ms' (P50/P95/P99) حسب طول الصفحة.
- «search _ index _ hit _ ratio» (نسبة الطلبات التي يتركها مؤشر التغطية).
- «next _ cursor _ invalid _ rate» (التحقق/TTL/أخطاء التوقيع).
- "merge _ fanout' (عدد الشظايا المعنية لكل صفحة).
- «duplicates _ on _ boundary» و «baps _ on _ boundary» (الكشف عن القياس عن بعد للعميل).
- ربط «مؤشر _ معرف» في جذوع الأشجار، قناع الحمولة.
- تمتد العلامة: "page _ size"، "source _ shards'،" db _ index _ used ".
- التوافر: 99. 9٪ على طرق «القائمة».
- زمن الوصول: P95 <200 ms لـ «page _ size <= 50» بشحنة محلية.
- خطأ رمزي: <0. 1٪ من إجمالي عدد المكالمات.
13) الهجرات وقابلية التشغيل البيني
مكّن 'v' في رمز ودعم الإصدارات القديمة من N أسابيع.
عند تغيير مفاتيح الفرز - أرسل خطأ "ناعمًا" "409 Conflict' مع مطالبة بإجراء قائمة جديدة بدون مؤشر.
حالة كارثية (هدير جميع الرموز): تغيير «توقيع _ مفتاح _ معرف» ورفض القديمة.
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) السلامة والامتثال
لا تتضمن الحقول الخام في الرموز التي يمكن اشتقاق PII منها.
قم بالتوقيع والحد من TTL.
حاول جعل الرموز غير محتملة بين المستخدمين (اكتب «فرعي/مستأجر/أدوار» في الحمولة وتحقق أثناء التحقق).
سجل فقط تجزئة رمزية.
16) الأخطاء المتكررة والأنماط المضادة
Base64 (هوية) كمؤشر: سهل التزييف/الالتقاط، يخرق العقد عند تغيير النوع.
لا يوجد فاصل التعادل: «طلب بواسطة ts DESC» بدون «معرف» → مكرر/قفزات.
قم بتغيير المرشحات بين الصفحات دون إبطال الرمز.
التعويض العميق: بطيء ولا يمكن التنبؤ به.
الرموز بدون إصدار و TTL.
17) تنفيذ القائمة المرجعية المصغرة
1. حدد النوع وأضف فاصل التعادل الفريد.
2. قم بإنشاء فهرس ممتد لهذا الترتيب.
3. حدد النموذج: ابحث عن + رمز غير شفاف.
4. تنفيذ التوقيع الرمزي (والتشفير إذا لزم الأمر).
5. ضع TTL والإصدار.
6. صياغة وتوثيق العقود «لديها _ المزيد»، «المؤشر التالي _».
7. ضع في اعتبارك مخططًا متقاطعًا (إذا لزم الأمر) ودمج k-way.
8. أضف المقاييس والتنبيهات و SLOs.
9. قم بتغطية حدود الصفحة القائمة على الممتلكات بالاختبارات.
10. وصف استراتيجية الهجرة للرموز.
18) توصيات موجزة لاختيار نهج
الدلائل/عمليات البحث حيث يكون «رقم الصفحة» والإجمالي التقريبي مهمين: لنقل «OFFSET/LIMITE» + ذاكرة التخزين المؤقت ؛ أن المجموع تقريبي.
الخلاصات، التحليلات، القوائم العميقة، RPS عالية: المؤشر/البحث فقط.
المجموعات الشاردية/الموزعة: المؤشرات لكل شظية + رمز الدمج.
الخيوط/مراكز السيطرة على الأمراض والوقاية منها: المؤشرات كتعويضات/ts مع السيرة الذاتية.
19) مثال على اتفاق API (موجز)
'الحصول على/v1/العناصر ؟ الحد = 50 & مؤشر =... "
تتضمن الإجابة دائمًا صفحة. "، الصفحة. has_more'، صفحة اختيارية. next_cursor'.
المؤشر مبهم وموقع مع TTL.
النوع هو «ترتيب حسب created_at DESC، معرف DESC».
ضبط تغيير السلوك العناصر لا «العودة» نسبة إلى المؤشر.
المقاييس والأخطاء موحدة: «غير صالح _ مؤشر»، «منتهي الصلاحية _ مؤشر»، «عدم تطابق _ مرشحات».
توفر هذه المقالة المبادئ المعمارية والأنماط الجاهزة لتصميم الوثب الذي يظل سريعًا ويمكن التنبؤ به وآمنًا حتى في سجلات البيانات الضخمة والقشرية والمتغيرة بنشاط.