كيف يمكن تسريع الوصول إلى تطبيقات API بسرعة وسهولة؟

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



حول المشكلة الأصلية



أنشأت منصة الفيديو PREMIER ، بما يتناسب مع مورد حديث ، خدمة توصية لعملائها تعتمد على التعلم الآلي. يلجأ الكثير من المستخدمين إلى منصة الفيديو - حوالي مليون مستخدم يوميًا ، PREMIER تحظى بشعبية كبيرة - وتأتي المكالمات من خلال نموذج ويب ، من تطبيقات الأجهزة المحمولة ومن التلفزيون الذكي.



يتم تخزين البيانات الأولية التي على أساسها يعمل التعلم الآلي لخدمتنا في عمود ClickHouse DBMS. وفقًا للجدول الزمني ، تتم معالجة البيانات في الخلفية لبناء النماذج (والتي سيتم استخدامها لإصدار التوصيات النهائية). يتم حفظ نتائج الحساب في نظام DBMS العلائقي لـ PostgreSQL.



دائمًا ما يكون حل مشكلة التفاعل السريع بين خادم التطبيق والعميل في وقت قصير مناسبًا. لضمان سرعة العمل المطلوبة - ويجب ألا يكون وقت الاستجابة أكثر من 50 مللي ثانية - كان علينا تحسين بنية قاعدة البيانات العلائقية وتنفيذ التخزين المؤقت والقياس الأفقي. سنتحدث عن بعض التقنيات الآن.







حول التخزين المؤقت



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



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



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



هناك عدة خيارات لمكان تخزين الموارد المخزنة مؤقتًا: محليًا - على مثيل العميل في المستعرض ، في خدمة CDN لجهة خارجية ، على جانب التطبيق. سنتحدث عن التخزين المؤقت داخل التطبيق. من المحتمل أن تكون ذاكرة عملية التطبيق هي الخيار الأكثر شيوعًا للتخزين المؤقت للبيانات الذي ستصادفه. ومع ذلك ، فإن هذا الحل له عيوبه ، منذ ذلك الحين الذاكرة مرتبطة بعملية تؤدي مهمة محددة. يكون هذا أكثر أهمية إذا كنت تخطط لتوسيع نطاق التطبيق ، حيث لا يتم تخصيص الذاكرة بين العمليات ، أي لن تكون متاحة في عمليات أخرى ، مثل تلك المسؤولة عن المعالجة غير المتزامنة. نعم ، يعمل التخزين المؤقت ، لكننا في الحقيقة لا نحصل على الفائدة الكاملة منه.



التوصية بالتخزين المؤقت







بالعودة إلى المشروع ، نفهم الحاجة إلى حل مركزي للتخزين المؤقت. بالنسبة لذاكرة التخزين المؤقت المشتركة ، يمكنك استخدام Memcached ، على سبيل المثال: إذا كان أحد التطبيقات متصلاً بالمثيل نفسه ، فيمكنك استخدامه في العديد من العمليات. من ناحية ، يعد Memcached حلاً بسيطًا ومريحًا ، ومن ناحية أخرى ، فهو محدود نوعًا ما عندما يتعلق الأمر بالإدارة الدقيقة لإلغاء الصلاحية وكتابة البيانات والاستعلامات الأكثر تعقيدًا في مخزن البيانات المخزن مؤقتًا. الآن ، في الواقع ، أصبح تخزين Redis هو المعيار في مهام التخزين المؤقت ، والذي يخلو من عيوب Memcached.



Redis هو مخزن سريع للقيم الأساسية. يزيد من كفاءة العمل مع البيانات ، لأن يصبح من الممكن تحديد الهيكل. يوفر تحكمًا دقيقًا في الإعاقة والوقاية ، مما يتيح لك الاختيار من بين ست سياسات مختلفة. يدعم Redis كلاً من الإجراءات الوقائية البطيئة والمتحمسة ، بالإضافة إلى وقائية الوقت. يمكن أن يوفر استخدام هياكل بيانات Redis تحسينات ملموسة ، اعتمادًا على كيانات الأعمال. على سبيل المثال ، بدلاً من تخزين الكائنات كسلاسل متسلسلة ، يمكن للمطورين استخدام بنية بيانات التجزئة لتخزين ومعالجة الحقول والقيم حسب المفتاح. يلغي Hash الحاجة إلى جلب السلسلة بأكملها وإلغاء تسلسلها واستبدالها في ذاكرة التخزين المؤقت بقيمة جديدة في كل تحديث ، مما يعني استهلاك أقل للموارد وأداء أفضل. هياكل البيانات الأخرى ،يمكن استخدام "الأوراق" المقترحة من Redis و "المجموعات" و "المجموعات المصنفة" و "المدونات التشعبية" و "الصور النقطية" و "المؤشرات الجغرافية") لتنفيذ سيناريوهات أكثر تعقيدًا. توفر المجموعات المصنفة لتحليل بيانات السلاسل الزمنية تعقيدًا وحجمًا أقل في معالجة البيانات ونقلها. يمكن استخدام بنية بيانات HyperLogLog لحساب العناصر الفريدة في مجموعة باستخدام مقدار صغير ومستمر من الذاكرة ، على وجه التحديد 12 كيلوبايت لكل HyperLogLog (بالإضافة إلى بضع بايت للمفتاح نفسه). تم تخصيص جزء كبير من حوالي 200 أمر متوفر في Redis لعمليات معالجة البيانات وتضمين المنطق في قاعدة البيانات نفسها باستخدام برامج Lua النصية.توفر الأوامر المدمجة وقدرات البرمجة النصية مرونة في معالجة البيانات مباشرةً في Redis دون الحاجة إلى إرسال البيانات عبر الشبكة إلى التطبيق الخاص بك ، مما يقلل من عبء تنفيذ منطق التخزين المؤقت الإضافي. يمكن أن يؤدي توفر بيانات ذاكرة التخزين المؤقت فورًا بعد إعادة التشغيل إلى تقليل وقت إحماء ذاكرة التخزين المؤقت بشكل كبير وتخفيف عبء إعادة حساب محتوى ذاكرة التخزين المؤقت من مخزن البيانات الرئيسي. سنتحدث عن ميزات تكوين Redis واحتمالات التجميع في المقالات التالية.سنتحدث عن ميزات تكوين Redis واحتمالات التجميع في المقالات التالية.سنتحدث عن ميزات تكوين Redis واحتمالات التجميع في المقالات التالية.



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



الطريقة الأساسية والشائعة لتحديث البيانات هي تقادم الوقت. نستخدم هذه الطريقة أيضًا ، مع مراعاة التحديث المركزي الدوري لبيانات تطبيق التوصية. ومع ذلك ، فكل شيء ليس بهذه البساطة كما يبدو للوهلة الأولى: في هذه الحالة ، من المهم للغاية مراقبة الترتيب بحيث لا تدخل ذاكرة التخزين المؤقت سوى البيانات الشائعة حقًا. يصبح هذا ممكنًا بفضل جمع إحصاءات الاستعلام وتنفيذ "الاحترار المسبق للبيانات" ، أي تحميل البيانات مسبقًا في ذاكرة التخزين المؤقت في بداية التطبيق. تعد إدارة حجم ذاكرة التخزين المؤقت أيضًا جانبًا مهمًا من التخزين المؤقت. في تطبيقنا ، يتم إنشاء حوالي ملايين التوصيات ، وبالتالي ، من غير الواقعي تخزين كل هذه البيانات في ذاكرة التخزين المؤقت. تتم إدارة حجم ذاكرة التخزين المؤقت عن طريق إزالة البيانات من ذاكرة التخزين المؤقت لتوفير مساحة للبيانات الجديدة.هناك عدة طرق قياسية: TTL ، FIFO ، LIFO ، آخر دخول. في الوقت الحالي نستخدم TTL ، لا يتجاوز مثيل Redis موارد الذاكرة والقرص المخصصة.



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



التوسع في تطبيق التوصية



لتوفير وصول PREMIER إلى تطبيق التوصية ، نستخدم بروتوكول HTTP ، والذي غالبًا ما يكون الخيار الرئيسي في تفاعل التطبيقات. إنه مناسب لتنظيم التفاعل بين التطبيقات ، خاصة إذا تم استخدام Kubernetes و Ingress Controller كبيئة بنية أساسية. يجعل استخدام Kubernetes القياس أسهل. الأداة قادرة على موازنة الطلب تلقائيًا بين الكبسولات في المجموعة للتشغيل المتساوي ، مما يسهل على المطورين التوسع. وحدة التحكم في الدخول مسؤولة عن ذلك ، والذي يحدد قواعد الاتصال الخارجي بالتطبيقات في Kubernetes. افتراضيًا ، لا يمكن الوصول إلى تطبيقات Kubernetes من الشبكة الخارجية. لتوفير وصول خارجي للتطبيقات ، يجب أن تعلن عن مورد دخول يدعم الموازنة التلقائية.نحن نستخدم Nginx Ingress Controller ، الذي يدعم SSL / TLS ، وقواعد إعادة كتابة URI ، و VirtualServer و VirtualServerRoute لتوجيه الطلبات إلى تطبيقات مختلفة اعتمادًا على URI ورأس المضيف.



يسمح لك التكوين الأساسي في Ingress Controller باستخدام الوظائف الأساسية لـ Nginx فقط - وهذا هو التوجيه بناءً على المضيف والمسار ، والوظائف الإضافية مثل قواعد إعادة كتابة URI ، ورؤوس الاستجابة الإضافية ، ومهلة الاتصال غير متوفرة. تتيح لك التعليقات التوضيحية المطبقة على مورد الدخول استخدام وظائف Nginx نفسها (عادةً ما تكون متاحة من خلال تكوين التطبيق نفسه) وتغيير سلوك Nginx لكل مورد دخول.



نخطط لاستخدام Nginx Ingress Controller ليس فقط في المشروع الذي ندرسه الآن ، ولكن أيضًا في عدد من التطبيقات الأخرى ، والتي سنتحدث عنها لاحقًا. سنتحدث عن هذا في المقالات التالية.







مخاطر وعواقب استخدام التخزين المؤقت



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



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



يجب مراعاة مخاطر تقديم البيانات القديمة ، وزيادة تعقيد الحلول بشكل عام ، واحتمالية إدخال أخطاء كامنة قبل تطبيق أي طريقة تخزين مؤقت على المشروع. بعد كل شيء ، في هذه الحالة ، لن يؤدي التخزين المؤقت إلا إلى تعقيد حل المشكلات ، ولكنه سيخفي مشكلات الأداء وقابلية التوسع: هل استعلامات قاعدة البيانات بطيئة؟ - نتائج التخزين المؤقت في التخزين السريع! هل مكالمات API بطيئة؟ - نتائج ذاكرة التخزين المؤقت على العميل! وذلك لأن تعقيد الكود الذي يدير التخزين المؤقت يزداد بشكل ملحوظ مع زيادة تعقيد منطق الأعمال.



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



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



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



الروابط:






All Articles