Cache وQueue في تصميم الأنظمة
استخدم التخزين المؤقت والطوابير لحل مشكلة مقاسة، مع فهم الاتساق والفشل وإعادة المحاولة بدل إضافة بنية تحتية بلا داعٍ.
ابدأ بالاختناق المقاس
لا تضف Redis أو queue لأن الرسم المعماري يبدو أكثر احترافًا. قِس أولًا: هل قاعدة البيانات بطيئة بسبب استعلام متكرر؟ هل طلب المستخدم ينتظر إرسال بريد؟ هل الحمل يأتي في اندفاعات أسرع من قدرة العامل؟ تحديد المشكلة يحدد الأداة ومكانها.
قد يكون الحل فهرسًا أو query محسنة أو عملًا غير متزامنًا بسيطًا داخل النظام الحالي. كل خدمة جديدة تحتاج نشرًا ومراقبة وأمانًا وخطة فشل. التعقيد له تكلفة ثابتة حتى عندما يكون المرور منخفضًا.
Cache: أين تعيش الحقيقة؟
في نمط cache-aside يبحث التطبيق في cache، فإن لم يجد يقرأ من قاعدة البيانات ويخزن النتيجة لمدة. قاعدة البيانات تظل مصدر الحقيقة. هذا مناسب للقراءات المتكررة التي تتحمل قدمًا قصيرًا، لكنه يعرضك إلى cache miss متزامن قد يرسل طلبات كثيرة للمصدر.
اختر key يتضمن كل ما يغير النتيجة، وحدد TTL بناءً على تحمل العمل للقدم. عند الكتابة، إما أن تبطل المفتاح أو تحدثه بطريقة متسقة. لا تستخدم cache لبيانات صلاحيات حساسة دون فهم نافذة القدم وتأثيرها.
async function getPlatform(id: string) {
const key = `platform:${id}`;
const cached = await cache.get(key);
if (cached) return JSON.parse(cached);
const platform = await database.platform.findUnique({ where: { id } });
if (platform) await cache.set(key, JSON.stringify(platform), { ttl: 300 });
return platform;
}Queue: فصل الزمن والقدرة
عندما ينشئ المستخدم إشعارًا لآلاف الطلاب، لا يجب أن ينتظر إرسال كل push داخل طلب HTTP واحد. يسجل النظام العمل الدائم ثم يعالجه عامل بقدرة محدودة. تمتص queue الاندفاع وتسمح بإعادة المحاولة ومراقبة backlog.
لكن التسليم غالبًا at-least-once: قد ينفذ المستهلك العمل ثم يفشل تأكيد الرسالة، فتصل مرة أخرى. لذلك يجب أن يكون المستهلك idempotent عبر مفتاح فريد أو انتقال حالة شرطي. لا تعتمد على أمل أن الرسالة لن تتكرر.
- •حدد حدًا لعدد المحاولات وتأخيرًا متزايدًا مع jitter.
- •انقل الرسائل المستنفدة إلى dead-letter path قابلة للفحص.
- •راقب عمر أقدم رسالة وليس عدد الرسائل فقط.
- •لا تسجل payload حساسًا في logs التشخيصية.
سيناريوهات الفشل قبل الإطلاق
ماذا يحدث إذا تعطلت cache؟ يجب أن يكون هناك fallback محدود لا يحول العطل إلى انهيار قاعدة البيانات. ماذا يحدث إذا توقف العامل؟ يجب أن يبقى العمل دائمًا ويظهر backlog في المراقبة. ماذا لو كانت الرسالة سامة وتفشل كل مرة؟ يجب ألا تحجب الصف كله.
اختبر فقد الاتصال والمهلة والتكرار والضغط، وحدد SLO بسيطًا مثل عمر 95% من المهام. عندما تستطيع شرح مصدر الحقيقة، وحدود القدم، وضمان التسليم، وسلوك التكرار، تكون الأداة جزءًا مفهومًا من النظام لا صندوقًا أسود.
المراجع ومزيد من القراءة
عن المؤلف
يراجع أسامة زيدان محتوى كود هاب بهدف تقديم شرح عربي واضح يربط المفاهيم البرمجية بالقرارات التي يواجهها المتعلم أثناء التطبيق.
صفحة المؤلف