شعار زيفيرنت

القيام بالمزيد بموارد أقل: الانتقال من المعاملات إلى المعالجة المجمعة ذات الحالة

التاريخ:

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

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

في هذا المنشور ، نوضح لك كيف انتقلنا إلى نظام معالجة دُفعات ، مبني على AWS ، يستهلك مجموعات من الأحداث محدودة الوقت. لم يؤدي ذلك إلى خفض التكاليف بنسبة 90٪ تقريبًا ، بل أدى أيضًا إلى تحسين الرؤية في تدفق المعالجة الشامل لدينا. الرمز المستخدم لهذا المنشور متاح في GitHub جيثب:.

العمارة القديمة

تم استخدام العمارة القديمة لدينا في المقام الأول الأمازون الحوسبة المرنة السحابية (Amazon EC2) لتجميع الأحداث المالية ذات الصلة في أدوات معنية بالحالة. ومع ذلك ، يمكن أن تشير الأداة ذات الحالة إلى أي عنصر ثابت ، مثل إدخال قاعدة بيانات أو ملف خدمة تخزين أمازون البسيطة (Amazon S3).

وجدنا أن هذا النهج أدى إلى أوجه قصور في المجالات التالية:

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

الرسم البياني التالي يوضح العمارة القديمة لدينا.

بنية تراثية قائمة على المعاملات

التطور هو المفتاح

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

  • الانفصال عديمي الجنسية وذات الحالة
  • تصغير وقت الاستجابة من طرف إلى طرف
  • التدرجية

الانفصال عديمي الجنسية وذات الحالة

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

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

بعد ذلك ، ينضم المكون ذو الحالة إلى هذه القطع الأثرية عديمة الحالة مع القطع الأثرية الحالية لإنتاج قطعة أثرية محدثة.

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

تصور دفعة

تصغير وقت الاستجابة من طرف إلى طرف

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

التدرجية

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

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

قابلية التوسع دفعة

العمارة الحالية

لتلبية احتياجاتنا ، قمنا بدمج العديد من منتجات AWS:

  • وظائف خطوة AWS - تنسيق تدفقات العمل عديمة الجنسية وذات الحالة الخاصة بنا
  • أمازون EMR - عمليات Apache Spark على القطع الأثرية عديمة الجنسية وذات الدولة
  • AWS لامدا - فهرسة القطع الأثرية الدقيقة وإدارة الأعمال المتراكمة
  • أمازون ElastiCache - تحسين وقت استجابة طلبات Amazon S3
  • الأمازون S3 - تخزين قابل للتطوير من القطع الأثرية عديمة الجنسية وذات الحالة الخاصة بنا </ li>
  • الأمازون DynamoDB - فهرس القطع الأثرية عديمة الحالة وذات الحالة

يوضح الرسم البياني التالي هندستنا الحالية.

العمارة الحالية

يوضح الرسم التخطيطي التالي سير عملنا عديم الحالة وذات الحالة.

المخطط الانسيابي

تكوين سحابة AWS نموذج لتقديم هذه البنية ورمز Java المقابل متاح في ما يلي جيثب ريبو.

سير العمل عديم الحالة

استخدمنا تطبيق Apache Spark على مجموعة Amazon EMR طويلة الأمد لاستيعاب بيانات دفعة الإدخال في وقت واحد وإجراء عمليات مختصرة لإنتاج القطع الأثرية عديمة الحالة وملف فهرس مقابل لاستخدام المعالجة المصححة بالحالة.

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

سير عمل ذو حالة

ينفذ كل سير عمل محدد الحالة عمليات لإنشاء أو تحديث الملايين من القطع الأثرية ذات الحالة باستخدام العناصر عديمة الحالة. على غرار عمليات سير العمل عديمة الحالة ، يتم تخزين جميع القطع الأثرية ذات الحالة في Amazon S3 عبر مجموعة من ملفات جزء Apache Spark. أدى هذا وحده إلى خفض كبير في التكلفة ، لأننا قللنا بشكل كبير من عدد عمليات الكتابة في Amazon S3 (أثناء استخدام نفس القدر من سعة التخزين الإجمالية). على سبيل المثال ، سيكلف تخزين 10 ملايين قطعة أثرية فردية باستخدام البنية القديمة للمعاملات 50 دولارًا في طلبات PUT وحدها ، بينما تكلف 10 ملفات جزء من Apache Spark 0.00005 دولارًا فقط في طلبات PUT (بناءً على 0.005 دولار لكل 1,000 طلب).

ومع ذلك ، ما زلنا بحاجة إلى طريقة لاسترداد القطع الأثرية الفردية ، لأنه يمكن تحديث أي قطعة أثرية ذات حالة في أي وقت في المستقبل. للقيام بذلك ، لجأنا إلى DynamoDB. DynamoDB عبارة عن قاعدة بيانات وثيقة ومُدارة بالكامل وقابلة للتطوير. إنه مثالي لنمط الوصول الخاص بنا لأننا أردنا فهرسة موقع كل قطعة أثرية ذات حالة في ملف الإخراج ذي الحالة باستخدام معرفه الفريد كمفتاح أساسي. استخدمنا DynamoDB لفهرسة موقع كل قطعة أثرية ذات حالة ضمن ملف الإخراج ذي الحالة. على سبيل المثال ، إذا كانت طلباتنا تمثل الطلبات ، فسنستخدم معرف الطلب (الذي يحتوي على عدد كبير من العناصر) كمفتاح القسم ، ونخزن موقع الملف ، وإزاحة البايت ، وطول البايت لكل طلب كسمات منفصلة. عن طريق تمرير نطاق البايت في طلبات Amazon S3 GET، يمكننا الآن جلب القطع الأثرية الفردية ذات الحالة كما لو تم تخزينها بشكل مستقل. كنا أقل قلقًا بشأن تحسين عدد طلبات Amazon S3 GET لأن طلبات GET أرخص بعشر مرات من طلبات PUT.

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

الجلب المسبق

يوضح الرسم البياني التالي المكون الفرعي للجلب المسبق.

هندسة الجلب المسبق

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

تطلب كل عملية إحضار بحث DynamoDB وطلب Amazon S3 GET جزئيًا لنطاق البايت. نظرًا للعدد الكبير من المكالمات الخارجية ، تمت موازاة عمليات الجلب بشكل كبير باستخدام تجمع مؤشرات الترابط الموجود في عملية Apache Spark flatMap. تم دمج القطع الأثرية التي تم جلبها مسبقًا في ملف إخراج تم استخدامه لاحقًا كمدخلات إلى محرك المعالجة ذي الحالة.

محرك معالجة الدولة

يوضح الرسم التخطيطي التالي محرك المعالجة ذي الحالة.

بنية المعالج ذات الحالة

ينضم المكون الفرعي لمحرك المعالجة عالي الحالة إلى القطع الأثرية مسبقة الجلب مع القطع الأثرية عديمة الحالة لإنتاج أدوات محدثة الحالة بعد تطبيق منطق عمل مخصص. تتم كتابة القطع الأثرية المحدثة عبر عدة ملفات جزء من Apache Spark.

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

استخدمنا Amazon EMR هنا مرة أخرى للاستفادة من عمليات Apache Spark المطلوبة للانضمام إلى القطع الأثرية عديمة الجنسية وذات الحالة.

مفهرس الدولة

يوضح الرسم البياني التالي مفهرس الحالة.

بنية مفهرس الدولة

يسجل هذا المكون الفرعي المستند إلى Lambda موقع كل قطعة أثرية ذات حالة داخل ملف الجزء ذي الحالة في DynamoDB. يقوم مفهرس الحالة أيضًا بتخزين القطع الأثرية ذات الحالة في ملف Amazon ElastiCache لـ Redis الكتلة لتوفير تعزيز الأداء في طلبات Amazon S3 GET التي يتم إجراؤها بواسطة الجلب المسبق.

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

يقوم كل عامل في Lambda بعد ذلك بتنفيذ ElastiCache و DynamoDB يكتب لجميع القطع الأثرية ذات الحالة داخل كل ملف جزئي معين بطريقة متعددة الخيوط. تراقب وظيفة المنسق صحة كل عامل في Lambda وتعيد تشغيل العمال حسب الحاجة.

توزيع هندسة لامدا

تزامن

استخدمنا وظائف الخطوة لتنسيق كل من مهام سير العمل عديمة الحالة وذات الحالة ، كما هو موضح في الرسم التخطيطي التالي.

خطوة وظيفة سير العمل

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

اخترنا Step Functions لتكاملها الأصلي مع العديد من خدمات AWS (بما في ذلك التشغيل بواسطة ملف الأمازون CloudWatch حكم الحدث المقرر و إضافة خطوات Amazon EMR) ودعمها المضمن لعمليات إعادة محاولات التراجع ومنطق آلة الحالة المعقدة. على سبيل المثال ، قمنا بتعريف معدلات إعادة محاولة التراجع المختلفة بناءً على نوع الخطأ.

وفي الختام

ساعدتنا البنية القائمة على الدُفعات في التغلب على قيود معالجة المعاملات التي وضعناها في الأصل لحلها:

  • تكلفة منخفضة - لقد تمكنا من توسيع نطاق عمليات سير العمل ومئات الملايين من الأحداث يوميًا باستخدام ثلاث أو أربع عقد أساسية فقط لكل مجموعة EMR. أدى ذلك إلى تقليل استخدام Amazon EC2 لدينا بأكثر من 90٪ مقارنة بنظام معاملات مماثل. بالإضافة إلى ذلك ، أدى كتابة الدُفعات بدلاً من المعاملات الفردية إلى تقليل عدد طلبات Amazon S3 PUT بأكثر من 99.8٪.
  • ضمانات اكتمال البيانات - نظرًا لأن كل دفعة إدخال مرتبطة بفاصل زمني ، فعند انتهاء معالجة الدُفعة ، نعلم أن جميع الأحداث في تلك الفترة الزمنية قد اكتملت.
  • آليات إعادة المحاولة المبسطة - تعني معالجة الدُفعات حدوث حالات فشل على مستوى الدُفعة ويمكن إعادة المحاولة مباشرةً من خلال سير العمل. نظرًا لوجود دفعات أقل بكثير من المعاملات ، فإن عمليات إعادة المحاولة المجمعة تكون أكثر قابلية للإدارة. على سبيل المثال ، في خدمتنا ، تحتوي الدفعة النموذجية على حوالي مليوني إدخال. أثناء انقطاع الخدمة ، يلزم إعادة محاولة دفعة واحدة فقط ، مقابل مليوني إدخال فردي في البنية القديمة.
  • قابلية عالية - لقد تأثرنا بمدى سهولة توسيع نطاق مجموعات السجلات الطبية الإلكترونية أثناء التنقل إذا اكتشفنا زيادة في حركة المرور. استخدام أساطيل مثيلات Amazon EMR يساعدنا أيضًا في اختيار أكثر الحالات فعالية من حيث التكلفة تلقائيًا عبر مناطق توافر الخدمات المختلفة. نحب أيضًا الأداء الذي حققه مفهرس الحالة القائم على Lambda. هذا المكون الفرعي لا يتوسع ديناميكيًا دون تدخل بشري فحسب ، بل كان أيضًا فعالاً من حيث التكلفة بشكل مدهش. وقع جزء كبير من استخدامنا ضمن الطبقة المجانية.
  • التفوق التشغيلي - أتاح لنا استبدال المضيفين التقليديين بمكونات بدون خادم مثل Lambda قضاء وقت أقل في تذاكر الامتثال والتركيز أكثر على تقديم الميزات لعملائنا.

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

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

ابحث عن الكود المستخدم لهذا المنصب فيما يلي مستودع جيثب.

شكر خاص لفريق التطوير: ريان شوارتز ، أبهيشيك ساهي ، سيسيليا تشو ، جودو بيان ، سام لام ، جان كريستوف ليبرشت ، ونيكولاس ليونج.


حول المؤلف

توم جين هو مهندس برمجيات أول للتكامل المالي للتجارة الإلكترونية (eCFI) في أمازون. تشمل اهتماماته بناء أنظمة واسعة النطاق وتطبيق التعلم الآلي على تطبيقات الرعاية الصحية. يقيم في فانكوفر بكندا وهو من محبي الحفاظ على المحيطات.
Karthik Odapally هو مهندس حلول أول في AWS يدعم عملاء الألعاب لدينا. يحب التقديم في مؤتمرات خارجية مثل AWS Re: Invent ، ومساعدة العملاء على التعرف على AWS. شغفه خارج العمل هو خبز البسكويت والخبز للعائلة والأصدقاء هنا في PNW. في أوقات فراغه ، يلعب دور Legend of Zelda (Link's Awakening) مع ابنته البالغة من العمر 4 سنوات.

بقعة_صورة

أحدث المعلومات الاستخباراتية

بقعة_صورة