سؤال

نحن نحاول تحديث الكائنات memcached عندما نكتب إلى قاعدة البيانات لتجنب الاضطرار إلى قراءتها من قاعدة البيانات بعد إدراج/تحديثات.

بالنسبة لكائن منشور المنتدى لدينا ، لدينا حقل ViewCount يحتوي على عدد المرات التي يتم فيها عرض المنشور.

نخشى أن نقدم حالة سباق من خلال تحديث الكائن المذبح ، حيث يمكن عرض نفس المنشور في نفس الوقت على خادم آخر في المزرعة.

أي فكرة عن كيفية التعامل مع هذا النوع من القضايا - يبدو أن هناك حاجة إلى نوع من القفل ولكن كيفية القيام بذلك بشكل موثوق عبر الخوادم في المزرعة؟

هل كانت مفيدة؟

المحلول

إذا كنت تتعامل مع البيانات التي لا تعود بالضرورة بحاجة إلى ليتم تحديثها في الوقت الفعلي ، وبالنسبة لي ، فإن عدد العرض هو واحد منهم ، ثم يمكنك إضافة حقل انتهاء الصلاحية إلى الكائنات المخزنة في Memcache.

بمجرد حدوث ذلك ، سيعود إلى قاعدة البيانات وقراءة القيمة الجديدة ، ولكن حتى ذلك الحين سيتركها بمفردها.

بالطبع بالنسبة للمنشورات الجديدة ، قد ترغب في تحديث هذا في كثير من الأحيان ، ولكن يمكنك رمز هذا.

يقوم Memcache بتخزين نسخة واحدة فقط من كائنك في إحدى حالاته ، وليس في العديد منها ، لذلك لن تقلق بشأن قفل الكائنات أو أي شيء. هذا هو لقاعدة البيانات للتعامل معها ، وليس ذاكرة التخزين المؤقت الخاصة بك.

يحرر:

لا تقدم Memcache أي ضمان أنه عندما تحصل على خوادم متنوعة من الخوادم المتنوعة ، فلن تتلاشى بياناتك.

من مستندات Memcache:

  • سلسلة من الأوامر ليست ذرية. إذا قمت بإصدار "الحصول" على عنصر ما ، أو العمل على البيانات ، ثم ترغب في "تعيين" مرة أخرى في memcached ، فأنت غير مضمون لتكون العملية الوحيدة التي تعمل على هذه القيمة. بالتوازي ، قد ينتهي بك الأمر إلى الكتابة فوق القيمة التي حددها شيء آخر.

ظروف السباق والبيانات التي لا معنى لها

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

لنفترض أنك تخبط آخر خمسة تعليقات للعرض على الشريط الجانبي في التطبيق الخاص بك. تقرر أن البيانات تحتاج فقط إلى تحديث مرة واحدة في الدقيقة. ومع ذلك ، فأنت تهمل أن تتذكر أن عرض الشريط الجانبي هذا يتم تسليمه 50 مرة في الثانية! وبالتالي ، بمجرد أن تتدحرج 60 ثانية وتنتهي ذاكرة التخزين المؤقت ، فجأة تدير 10+ عمليات SQL نفس استعلام SQL لإعادة تدوير تلك التخزين المؤقت. في كل مرة تنتهي صلاحية ذاكرة التخزين المؤقت ، ستؤدي الانفجار المفاجئ لحركة SQL.

والأسوأ من ذلك ، أن لديك عمليات متعددة تقوم بتحديث نفس البيانات ، وينتهي الأمر الخطأ إلى مواعدة ذاكرة التخزين المؤقت. ثم لديك بيانات قديمة قديمة تطفو عليها.

ينبغي للمرء أن يدرك القضايا المحتملة في ملء أو إعادة تخزين ذاكرة التخزين المؤقت لدينا. تذكر أن عملية فحص memcached ، وجلب SQL ، وتخزينها في memcached ، ليست ذرية على الإطلاق!

نصائح أخرى

أنا أفكر - هل يمكن أن يكون الحل لتخزين ViewCount بشكل منفصل من كائن البريد ، ثم قم بزيادةه. بالطبع ، سيتطلب هذا قراءة 2 قيم منفصلة من memcached عند عرض المعلومات.

واجهنا هذا في نظامنا. قمنا بتعديل الحصول على ذلك

  • إذا كانت القيمة غير محددة ، فإنها تقوم بتعيينها بعلم ('g') و [8] TTL الثاني ، ويعيد خطأ بحيث تنشئها وظيفة الاتصال.
  • إذا لم يتم وضع علامة على القيمة (! == 'g') ، فلا عطلها وإعادتها.
  • إذا تم وضع علامة على القيمة (=== 'g') ، فانتظر ثانية وحاول مرة أخرى حتى لا يتم وضع علامة عليها. سيتم تعيينها في النهاية بواسطة العملية الأخرى ، أو انتهت صلاحيتها بواسطة TTL.

انخفض تحميل قاعدة البيانات لدينا بعامل 100 عندما نفذنا هذا.

function get($key) {
  $value=$m->get($key);
  if ($value===false) $m->set($key, 'g', $ttl=8);
  else while ($value==='g') {
    sleep(1);
    $value=$m->get($key);
  }
  return $value;
}

العمليات memcached هي ذرية. ستقوم عملية الخادم بتصوير الطلبات وتخدم كل واحدة تمامًا قبل الذهاب إلى التالي ، لذلك ليست هناك حاجة إلى القفل.

تعديل: Memcached لديه أمر زيادة هو الذري. عليك فقط تخزين العداد كقيمة منفصلة في ذاكرة التخزين المؤقت.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top