الگوی Transactional Outbox: انتشار مطمئن رویدادها در معماری مایکروسرویس
در معماریهای مدرن مبتنی بر رویداد (Event-Driven Architecture)، سرویسها بهصورت مداوم رویدادهایی مانند OrderCreated یا PaymentProcessed را منتشر میکنند تا تغییرات وضعیت را بهصورت مستقل اطلاعرسانی کنند.
اما چالش اصلی این است: چگونه تضمین کنیم که بهروزرسانی پایگاهداده و انتشار رویداد یا هر دو با هم موفق میشوند یا هر دو لغو میگردند؟
اگر یک مایکروسرویس پایگاهداده محلی خود (مانند PostgreSQL یا MySQL) را بهروز کند و سپس سعی کند پیامی را از طریق شبکه به پیامرسان (مانند Apache Kafka یا RabbitMQ) ارسال کند، قطعی شبکه میتواند منجر به ناهماهنگی دادهها شود.
الگوی Transactional Outbox برای حل بنیادین این مشکل طراحی شده است.
مشکل اصلی: مسئله نوشتن دوگانه (Dual-Write Problem)
هنگامی که یک سرویس دو عملیات نوشتن جداگانه انجام میدهد:
- ذخیره دادههای کسبوکار در پایگاهداده محلی.
- ارسال رویداد به Kafka.
اگر ثبت در پایگاهداده موفق باشد اما ارسال پیام به دلیل خطای شبکه شکست بخورد، داده در پایگاهداده ذخیره شده اما سرویسهای دیگر آگاه نمیشوند. نتیجه: عدم ناهمخوانی دادهها.
الگوی Transactional Outbox چیست؟
این الگو از قابلیت تراکنشهای ACID محلی پایگاههای داده رابطهای استفاده میکند.
به جای ارسال مستقیم پیام از طریق شبکه، سرویس رویداد را در یک جدول اختصاصی به نام Outbox Table و در همان تراکنش محلی ذخیره میکند.
با توجه به ویژگیهای ACID: یا هر دو ذخیرهسازی با هم ثبت میشوند یا هر دو لغو میگردند.
سپس یک فرآیند پسزمینه (Message Relay) جدول Outbox را خوانده و پیامها را به پیامرسان منتقل میکند.
استراتژیهای انتقال پیام: Polling Publisher در برابر CDC (Debezium)
۱. روش پیمایش (Polling Publisher)
یک وظیفه زمانبندیشده بهصورت دورهای رکوردهای پردازشنشده را استعلام کرده، به Kafka ارسال کرده و وضعیت را بهروز میکند.
- مزایا: پیادهسازی ساده بدون نیاز به زیرساخت اضافی.
- معایب: تاخیر در ارسال و بار اضافه بر پایگاهداده.
۲. ردیابی تغییرات داده (CDC با Debezium)
Debezium مستقیماً لاگهای تراکنش (PostgreSQL WAL) را ردیابی کرده و تغییرات را بهصورت زنده به Kafka میفرستد.
- مزایا: تاخیر نزدیک به صفر و بدون بار بر برنامه.
- معایب: نیاز به راهاندازی Kafka Connect.
نتیجهگیری
الگوی Transactional Outbox الگویی حیاتی برای تضمین همگامسازی نهایی دادهها در سیستمهای توزیعشده است.