يدرس هذه المقالة بشكل أساسي المحتوى ذي الصلة من ذاكرة التخزين المؤقت ذات الإنتاجية العالية وآمنة مؤشرات الترابط ، على النحو التالي.
قبل بضع سنوات ، قمت بتنفيذ ذاكرة التخزين المؤقت LRU للعثور على معرفها للكلمات الرئيسية. بنية البيانات مثيرة للاهتمام للغاية لأن الإنتاجية المطلوبة كبيرة بما يكفي للتخلص من مشاكل الأداء الناجمة عن العدد الكبير من locks والكلمات الرئيسية synchronized . يتم تنفيذ التطبيق في Java.
اعتقدت أن سلسلة من المخصصات المرجعية الذرية ستحافظ على ترتيب LRU و LRU في ConcurrenthashMap. في البداية ، لفت القيمة في الإدخال. يحتوي الإدخال على عقدة في سلسلة LRU من القائمة المزدوجة المرتبطة. يحافظ ذيل السلسلة على الإدخال المستخدم مؤخرًا ، وتخزن عقدة الرأس الإدخال الذي قد يتم مسحه عندما تصل ذاكرة التخزين المؤقت إلى حجم معين. كل عقدة تشير إلى الإدخال المستخدم للعثور عليه.
عندما تبحث عن القيمة من خلال المفتاح ، تحتاج ذاكرة التخزين المؤقت أولاً إلى البحث عن الخريطة لمعرفة ما إذا كانت هذه القيمة موجودة. إذا لم يكن موجودًا ، فسوف يعتمد على المحمل لقراءة القيمة من مصدر البيانات بطريقة قراءة وإضافتها في الخريطة في "إضافة إذا فقدت". التحدي المتمثل في ضمان إنتاجية عالية هو الحفاظ على سلسلة LRU بشكل فعال. يتم تجزئة خريطة التجزئة المتزامنة هذه ومستوى مؤشر الترابط على مستوى معين (يمكنك تحديد مستوى التزامن عند إنشاء الخريطة) لن يواجه الكثير من المنافسة الخيطية. ولكن لا يمكن تقسيم سلسلة LRU بنفس الطريقة؟ لحل هذه المشكلة ، قدمت قائمة انتظار مساعدة للعمليات المقاصة.
هناك ست طرق أساسية في ذاكرة التخزين المؤقت. بالنسبة لضربات ذاكرة التخزين المؤقت ، يتضمن البحث عمليتين أساسيتين: الحصول على وعرض ، ولخسارة خشنة ، هناك أربع طرق أساسية: الحصول على ، تحميل ، وضع ، عرض. في طريقة PUT ، قد نحتاج إلى تتبع العملية الواضحة. عندما تضرب ذاكرة التخزين المؤقت ، نقوم ببعض المقاصة بشكل سلبي على سلسلة LRU تسمى عملية التطهير.
الحصول على: إدخال البحث في الخريطة بواسطة المفتاح
التحميل: قيمة التحميل من مصدر البيانات
ضع: إنشاء إدخال ورسم خريطة إلى المفتاح
العرض: إلحاق عقدة في ذيل قائمة LRU التي تشير إلى إدخال تم الوصول إليه مؤخرًا
إدلاء: قم بإزالة العقد على رأس القائمة والإدخالات المرتبطة بها من الخريطة (بعد أن تصل ذاكرة التخزين المؤقت إلى حجم معين)
تطهير: حذف العقد غير المستخدمة في قائمة LRU - نشير إلى هذه العقد كثقوب ، وتتبع قائمة انتظار التنظيف هذه
تشغيل عملية المقاصة وتنقية كلاهما مجموعات كبيرة من بيانات المعالجة. دعونا نلقي نظرة على تفاصيل كل عملية.
تعمل عملية GET على النحو التالي:
احصل على (k) -> v إدخال البحث عن طريق المفتاح k إذا ضربت ذاكرة التخزين المؤقت ، لدينا إدخال e إدخال e try try purge بعض الثقوب الأخرى
إذا كان المفتاح موجودًا ، فنحن نقدم عقدة جديدة في ذيل سلسلة LRU للإشارة إلى أن هذه قيمة تستخدم مؤخرًا. إن تنفيذ GET والعرض ليس عملية ذرية (لا يوجد قفل هنا) ، لذلك لا يمكننا القول أن هذه العقدة المقدمة هذه تشير إلى الكيان الأكثر استخدامًا ، ولكنه بالتأكيد هو الكيان الأكثر استخدامًا الذي تم الحصول عليه عندما ننفذ بشكل متزامن. نحن لا نجبر على الحصول على الطلب ونقدم تنفيذ الطلب بين المواضيع ، لأن هذا قد يحد من الإنتاجية. بعد تقديم عقدة ، نحاول القيام ببعض العمليات لمسح القيمة وإرجاعها. دعنا نلقي نظرة على العرض وتطهير العمليات بالتفصيل أدناه.
في حالة حدوث فقدان ذاكرة التخزين المؤقت ، سنقوم بالاتصال بالعملية لتحميل القيمة لهذا المفتاح ، وإنشاء كيان جديد ووضعه في الخريطة ، وتكون عملية PUT هي كما يلي:
ضع (e) -> e إدخال موجود ex < - map.putifabsent (ek ، e) إذا كان العرض غائبًا إدخال e ؛ إذا وصول الحجم إخلاء العتبة إخلاء بعض الإدخالات إدخال إرجاع إرجاع e els
كما ترون ، قد تكون هناك منافسة عندما يضع خيطان أو أكثر كيانًا في الخريطة ، ولكن سيتم السماح بنجاح واحد فقط وسيتم استدعاء العرض. بعد توفير عقدة في ذيل سلسلة LRU ، نحتاج إلى التحقق مما إذا كانت ذاكرة التخزين المؤقت قد وصلت إلى عتبةها ، وهو المعرف الذي نستخدمه لبدء تشغيل الدفعة الواضحة. في سيناريو التطبيق المحدد هذا ، يكون إعداد العتبة أصغر من السعة. تحدث عملية المقاصة في دفعة صغيرة وليس عند إضافة كل كيان. قد تشارك خيوط متعددة في عملية المقاصة حتى تصل سعة ذاكرة التخزين المؤقت إلى قدرتها. القفل سهل ولكن يمكن أن تكون المواضيع آمنة. يتطلب تطهير عقدة الرأس لسلسلة LRU الإزالة ، والتي تتطلب عمليات ذرية دقيقة لتجنب عمليات الإزالة متعددة الخيوط في الخريطة.
عملية العرض هذه ممتعة للغاية. يحاول دائمًا إنشاء عقدة ولكنه لا يحاول إزالة وحذف العقد التي لم تعد تستخدم في LRU على الفور.
عرض (e) إذا لم تشير عقدة الذيل إلى الإدخال e ، قم بتعيين العقدة الحالية c <-en قم بإنشاء عقدة جديدة n (e) ، ومشتركين عقدة جديدة إلى الإدخال e إذا كانت العقدة الذرية المقارنة والجماعية en ، توقع c ، envis n add n add n to tail of lru end end end end end int
أولاً ، سوف نتحقق من أن العقدة الموجودة في ذيل السلسلة لا تشير إلى الكيان الذي تم الوصول إليه ، وهو أمر لا يختلف إلا إذا كانت جميع مؤشرات الترابط تصل بشكل متكرر إلى نفس زوج القيمة الرئيسية. سوف ينشئ عقدة جديدة في ذيل السلسلة. عندما يكون هذا الكيان مختلفًا ، قبل توفير عقدة جديدة ، فإنه يحاول إجراء مقارنة وتعيين التشغيل للكيان ، مما سيمنع مؤشرات ترابط متعددة من فعل نفس الشيء.
يوفر الخيط الذي يخصص العقد بنجاح عقدة جديدة في نهاية سلسلة LRU. هذه العملية هي نفسها الاكتشاف في concurrentLinkedqueue. تم وصف خوارزمية التبعية في المقالة التالية. بسيطة وسريعة وعملية غير حظر وحظر خوارزميات قائمة انتظار متزامنة. سيقوم الخيط بعد ذلك بالتحقق مما إذا كان الكيان مرتبطًا بالعقد الأخرى من قبل. إذا كان الأمر كذلك ، فلن يتم حذف العقدة القديمة على الفور ، ولكن سيتم تمييزها كفتحة (سيتم تعيين الإشارة إلى كيانها إلى فارغة)
ما ورد أعلاه هو كل التفسير التفصيلي لهذه المقالة حول ذاكرة التخزين المؤقت عالية الإنتاجية وآمنة مؤشرات الترابط ، وآمل أن تكون مفيدة للجميع. يمكن للأصدقاء المهتمين الاستمرار في الرجوع إلى الموضوعات الأخرى ذات الصلة على هذا الموقع. إذا كانت هناك أي أوجه قصور ، فيرجى ترك رسالة لإشارةها. شكرا لك يا أصدقائك لدعمكم لهذا الموقع!