→ بازگشت به نقشه‌های معماری

هزینه واقعی قفل‌های همگام API در سوئیچ‌های پرداخت با ترافیک بالا

۷ مهر ۱۴۰۵

[معماری سیستم][راهبرد محصول]

سازوکار رقابت بر سر قفل

سوئیچ‌های پرداخت با ترافیک بالا، ده‌ها هزار درخواست در ثانیه پردازش می‌کنند. تیم‌های مهندسی اغلب با قفل توزیع‌شده همگام از مانده دفتر کل محافظت می‌کنند. کاربر پرداخت را آغاز می‌کند؛ درگاه از Redis قفل توزیع‌شده می‌گیرد یا ردیف پایگاه داده رابطه‌ای را قفل می‌کند؛ سپس میزبان بانکی بالادست را از طریق HTTPS یا ISO 8583 فراخوانی می‌کند.

این الگو روی کاغذ ایمن به نظر می‌رسد. با ترتیبی‌کردن دسترسی به رکورد حساب، از خرج‌کردن دوباره جلوگیری می‌کند. اما در هم‌زمانی بالا، دسترس‌پذیری را به خطر می‌اندازد. نگه‌داشتن قفل هنگام انتظار برای شبکه بیرونی، منابع پردازشی را به تأخیر آن شبکه وابسته می‌کند. وقتی سوئیچ بانکی بالادست کند شود، کل لایه ورودی از کار می‌افتد.

کمبود رشته اجرایی و انتشار زنجیره‌ای تأخیر

قفل‌های همگام، تأخیر شبکه بیرونی را به اتمام منابع داخلی تبدیل می‌کنند. یک سرور برنامه با ۲۰۰ رشته کاری را در نظر بگیرید:

  • در شرایط عادی، سوئیچ بانکی بالادست هر تراکنش را در ۵۰ میلی‌ثانیه پردازش می‌کند.
  • هر رشته کاری، ۲۰ تراکنش در ثانیه پردازش می‌کند.
  • گره برنامه بدون انباشت صف، ۴٬۰۰۰ تراکنش در ثانیه را پاسخ می‌دهد.
  • در اوج پرداخت قبض یا نوسان تأخیر شبکه اپراتور، تأخیر بالادست به ۵۰۰ میلی‌ثانیه می‌رسد.
  • ظرفیت هر رشته به ۲ تراکنش در ثانیه افت می‌کند.
  • ظرفیت کل گره از ۴٬۰۰۰ به ۴۰۰ تراکنش در ثانیه کاهش می‌یابد.

اگر ترافیک ورودی روی ۲٬۰۰۰ تراکنش در ثانیه بماند، صف اتصال‌های ورودی ظرف ۲۰۰ میلی‌ثانیه پر می‌شود. بافرهای سوکت، داده‌های خوانده‌نشده را نگه می‌دارند و مصرف حافظه بالا می‌رود. آزمون‌های سلامت شکست می‌خورند، چون حلقه رویداد HTTP نمی‌تواند منابع اجرا تخصیص دهد. متعادل‌کننده بار، نمونه را از مدار خارج می‌کند و ترافیک را به گره‌های باقی‌مانده می‌فرستد. آن گره‌ها هم بلافاصله اشباع می‌شوند و از کار می‌افتند. خرابی ظرف چند ثانیه در کل خوشه منتشر می‌شود.

بازه خطر تسویه تکراری

قفل همگام در شرایط پایان مهلت پاسخ، کفایت نمی‌کند. وقتی میزبان بانکی بالادست برای پاسخ به درخواست مجوز پرداخت ۱۰ ثانیه زمان می‌گیرد، مهلت خواندن پاسخ در درگاه ورودی تمام می‌شود. درگاه، قفل توزیع‌شده محلی را آزاد می‌کند و خطای HTTP 504 Gateway Timeout را به پذیرنده برمی‌گرداند.

بانک بالادست ممکن است با وجود پایان مهلت محلی، تراکنش را تکمیل کند. کاربر دوباره دکمه پرداخت را می‌زند. درگاه قفل تازه‌ای می‌گیرد، کلید Idempotency جدیدی تخصیص می‌دهد و درخواست مجوز دوم را ارسال می‌کند. شبکه کارت هر دو برداشت را پردازش می‌کند. دفتر کل پذیرنده مغایرتی ثبت می‌کند که تطبیق خودکار آن ممکن نیست. رفع این اختلاف مانده به اصلاح دستی پایگاه داده، صف مغایرت‌گیری عملیات و پرداخت جریمه برگشت وجه ناشی از اعتراض نیاز دارد.

مهاجرت به دفتر کل رویداد با ثبت صرفاً افزایشی

حذف قفل‌های همگام API به جداسازی وضعیت تغییرپذیر درخواست از واقعیت‌های تغییرناپذیر تسویه نیاز دارد. سوئیچ‌های مالی عملیاتی سه قاعده مشخص را اجرا می‌کنند:

  • پردازشگر ورودی، رویداد قصد انجام تراکنش را در لاگ صرفاً افزایشی ثبت می‌کند و بلافاصله توکن پذیرش برمی‌گرداند.
  • مجموعه پردازشگرهای کاری، فراخوانی‌های خروجی پایاپای را ناهمگام اجرا می‌کند. صف‌ها ظرفیت محدود دارند و فاصله تلاش‌های مجدد به‌صورت نمایی افزایش می‌یابد.
  • مانده حساب فقط از بازپخش قطعی لاگ رویداد محاسبه می‌شود؛ به‌روزرسانی مستقیم ردیف پایگاه داده مبنای محاسبه نیست.

عملیات اتمیک Redis همچنان کاربرد دارد. کلیدهای کوتاه‌عمر دارای TTL، درخواست‌های تکراری را در لبه حذف می‌کنند. این قفل‌ها نباید هنگام انتظار برای ورودی‌وخروجی شبکه طرف ثالث باز بمانند. سامانه، قصد انجام درخواست را در پایگاه داده ثبت می‌کند، رشته را آزاد می‌کند و هماهنگی سوکت را به پردازشگرهای ناهمگام اختصاصی می‌سپارد.

سامانه‌های مبتنی بر الگوی Outbox ناهمگام، جهش ترافیک را بدون اتمام ظرفیت رشته‌های کاری پردازش می‌کنند. اگر تأخیر سوئیچ بانکی بالادست ۸۰۰ میلی‌ثانیه افزایش یابد، عمق صف بالا می‌رود، اما APIهای ورودی همچنان درخواست می‌پذیرند و اتصال‌های سوکت را قطع نمی‌کنند. کنارگذاشتن قفل‌های توزیع‌شده همگام، دسترس‌پذیری پلتفرم و تعهدات SLA را حفظ می‌کند و از مغایرت دفتر کل زیر بار عملیاتی جلوگیری می‌کند.