نسخ D1 للقراءة عانت من تأخير لمدة 6 ثوانٍ

تأخرت إحدى نسخ D1 للقراءة في طوكيو بمقدار 6.1 ثانية عن عملية كتابة في أمريكا الشمالية.

علمتُ ذلك من خلال أداة تتبع قامت بتقييد الانطباعات الخاطئة (throttling wrong impressions). تذكر الوثائق التقنية "الاتساق النهائي" (eventual consistency)، لكنها لا تعطيك وقتاً محدداً لتخطط بناءً عليه.

قمت ببناء أداة فحص للحداثة (staleness probe) لمعرفة الأرقام الحقيقية. تقوم أداة الفحص بكتابة صف يحتوي على UUID و epoch، ثم تقوم باستطلاع النسخة (polling the replica) حتى يظهر الصف، وبعد ذلك تسجل مقدار التأخير.

نتائج 200 عملية فحص في آسيا:

يكون التأخير مرتفعاً إذا كانت القاعدة الأساسية (primary) في أمريكا الشمالية وكان المستخدمون في آسيا.

واجهتُ أيضاً خطأً في المخطط (schema error). حيث تم تشغيل عملية ترحيل (migration) على القاعدة الأساسية، ثم أعيد تشغيل Worker. أصابت الطلبات الأولى نسخة القراءة قبل وصول الجدول الجديد. أظهر الخطأ أن الجدول غير موجود، بينما كان الجدول موجوداً بالفعل، لكن النسخة كانت متأخرة.

قمت بحل هذه المشكلة عن طريق التوجيه حول التأخير (routing around the lag)، فأنا لا أحاول محاربته.

إليكم تصميمي:

  1. يضيف الكاتب (writer) قيمة written_at من نوع epoch إلى الصف.
  2. يضيف الكاتب ترويسة X-D1-Written-At إلى الاستجابة.
  3. يقارن القارئ (reader) تلك الترويسة بالبيانات الواردة من النسخة.
  4. إذا كانت بيانات النسخة أقدم من الترويسة، ينتقل القارئ لاستخدام KV كبديل.

يعمل KV في أقل من 500 مللي ثانية في نفس المنطقة. وهو مجاني لما يصل إلى 10 ملايين عملية قراءة يومياً. يوفر هذا وسيلة رخيصة للحصول على بيانات حديثة للأعلام (flags) الهامة.

ستستخدم KV فقط خلال النافذة الزمنية القصيرة التي تكون فيها النسخة متأخرة. أما معظم عمليات القراءة فستتم عبر D1 بشكل طبيعي بمجرد أن تلحق النسخة بالبيانات.

لقد شاركتُ النص البرمجي الكامل ونمط الترحيل (migration pattern) في منشوري التفصيلي.

المصدر: https://dev.to/riversea/d1-read-replicas-returned-stale-data-for-6-seconds-heres-what-i-measured-and-how-i-designed-mme