Cy Logic Insights

تسلسل داده‌ها در یکپارچه‌سازی سیستم‌ها با الگوی Outbox

چگونه در معماری‌های توزیع‌شده با استفاده از الگوی Outbox، تسلسل داده‌ها را بین انتشار صف پیام و تراکنش‌های پایگاه داده تضمین کنید؟

تسلسل داده‌ها در یکپارچه‌سازی سیستم‌ها با الگوی Outbox

تسلسل داده‌ها و چالش‌های آن در معماری‌های توزیع‌شده

در پروژه‌های نرم‌افزاری امروزی، کارکرد هماهنگ سرویس‌ها و ماژول‌های مختلف با یکدیگر یک نیاز حیاتی است. به‌ویژه در فرآیندهای یکپارچه‌سازی سیستم‌ها، فراهم کردن جریان داده‌ی مطمئن میان ERP، حسابداری، پرداخت، پیامک، ایمیل و سیستم‌های شخص ثالث امری ضروری است. با این حال، در ساختارهای معماری توزیع‌شده، ممکن است میان عملیات پایگاه داده محلی و مرحله‌ی ارسال رویداد به یک سیستم صف پیام، گسست‌های آنی رخ دهد.

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

منطق عملکرد الگوی Transactional Outbox

برای از بین بردن این تناقض‌ها، از الگوی Transactional Outbox استفاده می‌شود. اصل اساسی این الگوی طراحی این است که به جای اتصال مستقیم به سیستم [صف پیام] مقصد که پیام به آن ارسال خواهد شد، داده‌ها ابتدا درون یک جدول پایگاه داده مرتبط (جدول outbox) در همان تراکنش ذخیره می‌شوند.

  • منطق تجاری اجرا شده و جدول داده‌ی اصلی به‌روزرسانی می‌شود.
  • در همان محدوده‌ی تراکنش، داده‌های رویداد که باید تولید شوند در جدول outbox نوشته می‌شوند.
  • تراکنش پایگاه داده با موفقیت تأیید (commit) می‌شود.

به لطف این روش، داده‌های اصلی و داده‌های رویدادی که قرار است به دنیای خارج منتقل شوند، به صورت اتمیک در پایگاه‌های داده‌ی رابطه‌ای مانند [postgresql] ذخیره می‌شوند. اگر پایگاه داده به‌روزرسانی شده باشد، رکورد outbox قطعا وجود خواهد داشت.

پیاده‌سازی گام‌به‌گام با PostgreSQL و صف پیام

با استفاده از زیرساخت پایگاه داده‌ی [postgresql] می‌توان این فرآیند را به شکلی ایمن طراحی کرد. جدول outbox باید دارای ستون‌هایی باشد که شناسه، نوع، محتوا (payload) و وضعیت پردازش رویدادهایی که قرار است پردازش شوند را نگهداری کند.

  1. طراحی جدول: در جدول outbox فیلدهای id، aggregate_type، payload، created_at و processed تعریف می‌شوند.
  2. ثبت تراکنشی: هنگامی که تراکنش انجام می‌شود، عملیات نوشتن در جدول پایگاه داده‌ی اصلی و عملیات نوشتن در جدول outbox تحت یک تراکنش واحد اجرا می‌شوند.
  3. خواننده پس‌زمینه (Message Relay): یک فرآیند پس‌زمینه‌ی مجزا (با روش polling یا transaction log mining)، رکوردهای پردازش‌نشده در جدول outbox را به صورت دوره‌ای اسکن می‌کند.
  4. ارسال به صف: داده‌های خوانده‌شده به سیستم [صف پیام] خارجی منتقل می‌شوند و پس از تأیید ارسال، وضعیت رکورد مربوطه در جدول outbox به‌روزرسانی می‌شود.

نتیجه‌گیری

ساخت یکپارچه‌سازی‌های مطمئن در سیستم‌های توزیع‌شده مستلزم تاب‌آوری در برابر سناریوهای خطای احتمالی است. الگوی Outbox با جلوگیری از گماردن داده‌ها در فرآیندهای [یکپارچه‌سازی سیستم] شما، امکان کارکرد همگام و پایدار سیستم‌ها را فراهم می‌کند.

سناریوی فرضی: فرآیند سفارش تجارت الکترونیک و یکپارچه‌سازی پرداخت

بیایید فرآیند ایجاد سفارش توسط یک مشتری در پلتفرم تجارت الکترونیک خود را در نظر بگیریم. در حالی که سفارش در پایگاه داده ثبت می‌شود، لازم است پرداخت از طریق سرویس‌های خارجی انجام شده و موجودی انبارها کسر گردد. منطق تجاری در حالی که جدول سفارش را به‌روزرسانی می‌کند، رویداد ایجاد سفارش را در همان محدوده‌ی تراکنش در جدول outbox می‌نویسد. فرض کنیم به محض اینکه پایگاه داده در این سناریو commit می‌شود، قطعی شبکه رخ دهد. در رویکردهای سنتی، اعلان به صف پیام نمی‌رسید و موجودی‌ها به‌روزرسانی نمی‌شدند. اما به لطف الگوی Outbox، مؤلفه‌ی خواننده‌ی پیام در پس‌زمینه هنگامی که سیستم دوباره بالا می‌آید، رکورد پردازش‌نشده در جدول outbox را شناسایی می‌کند. این رکورد را به صورت ایمن به صف پیام خارجی منتقل کرده و پس از ارسال موفقیت‌آمیز، رکورد را به‌روزرسانی می‌کند.

بزرگ‌ترین مبادله‌ی تجاری که در این مرحله با آن مواجه می‌شویم، میان کارایی و تسلسل است. در حالی که خواننده‌های مبتنی بر Polling بار اضافی بر پایگاه داده وارد می‌کنند، رویکردهای Transactional Log Mining پیچیدگی را افزایش می‌دهند. در مدیریت خطا، پردازش idempotent (تکرارپذیر) پیام‌ها از اهمیت حیاتی برخوردار است؛ زیرا به دلیل انقضای زمان شبکه ممکن است یک رویداد دو بار به صف داده شود. این که سرویس‌های مصرف‌کننده بتوانند این وضعیت را مدیریت کنند با استفاده از کلیدهای منحصربه‌فرد، پایداری سیستم را افزایش می‌دهد.

پیاده‌سازی گام‌به‌گام و چک‌لیست

هنگام انتقال الگوی Outbox به محیط عملیاتی، مراحل فنی که برای اطمینان از عملکرد مطمئن سرتاسری سیستم باید به آن‌ها توجه شود عبارتند از:

  • تأیید عملیات اتمیک: تست کنید که عملیات پایگاه داده اصلی و رکوردهای outbox قطعا در داخل یک بلوک تراکنش پایگاه داده‌ی واحد انجام می‌شوند.
  • ایندکس‌گذاری جدول: با افزودن ایندکس‌های مناسب به فیلدهای وضعیت پردازش و زمان ایجاد در جدول outbox، کارایی خواننده‌ی پس‌زمینه را بهینه‌سازی کنید.
  • پشتیبانی از Idempotency: با فرض اینکه سرویس‌های مصرف‌کننده‌ی صف پیام ممکن است یک رویداد را بیش از یک بار دریافت کنند، طراحی معماری idempotent را انجام دهید.
  • مدیریت خطا و تلاش مجدد: برای جلوگیری از قفل شدن سیستم در صورت عدم موفقیت در ارسال به صف، مکانیزم‌های انتظار افزایشی نمایی (exponential backoff) را راه‌اندازی کنید.
  • صف نامه مرده: برای رکوردهای خطاداری که از تعداد مشخصی تلاش فراتر رفته و پردازش نمی‌شوند، یک مکانیزم Dead Letter Queue (DLQ) تعریف کنید.
  • قابلیت ردیابی: زیرساخت‌های لاگ‌برداری و جمع‌آوری متریک را برای پیگیری چرخه‌ی حیات رکوردهای outbox یکپارچه‌سازی کنید.

منابع