Transactional Outbox Pattern
فرض کنید یه مولفهای دارید که باید توی دیتابیس یه سری رکورد رو تغییر بده و بعدش نتیجه رو بفرسته داخل یه بروکری مثل کافکا یا RabbitMQ. برامون مهمه که این فرایند کلا atomic باشه و ارسال پیام و آپدیت دیتابیس یا کلا انجام بشن یا انجام نشن. چون دوتا سیستم مختلف داریم(مثلا Postgres و RabbitMQ) استفاده از قابلیت تراکنش هر کدومشون به تنهایی کافی نیست و اینا باید باهم ترکیبی کار کنن تا واقعا تراکنشی که میخوایم اتفاق بیافته. توی این شرایط چی کار میشه کرد؟
یکی از راههایی که وجود داره استفاده از Outbox pattern هست. توی این روش میگه بیاین مولفه رو به دوتا پراسس بشکونید. پراسس اول کارهایی که لازمه رو انجام بده و به جای اینکه پیام رو مستقیما به بروکر بفرسته، به جاش توی یه جدولی به اسم outbox بیاد یه پیامی که باید فرستاده بشه رو insert کنید. اینطوری چون فقط یه دیتابیس دارید میتونید از قابلیت تراکنش اون سیستم به تنهایی استفاده کنید. پراسس دوم که ما بهش میگیم Message Relay کارش اینه که از جدول outbox پیامها رو بخونه و بفرسته به بروکر و بعد پاکشون کنه. اینطوری مشکل داشتن تراکنش بین دوتا سیستم مختلف حل میشه.
مشکلش چیه؟ مشکل اینه که Message Relay ممکنه فیل بشه یا وسط کار ریاستارت بشه و یه پیام رو دوبار بفرسته. برای همین مهمه که توی سمت گیرنده idempotent باشه و حواسش به پیامهای duplicate باشه. البته مستقل از این پترن، توی سیستمهای توزیع شده این idempotent بودن سمت کانسیومر رو خوبه کلا رعایت کنیم چون فرض Exactly Once معمولا خیلی سخته و بروکرها معمولا At least once delivery رو گارانتی میکنن که بازم نیاز به idempotent بودن کانسیومر داره.
به جز روش Outbox برای این مسئله روشهای دیگهای مثل پترن CDC یا two phase commit هم هست که اونا پیچیدهتر هستن و پیادهسازیشون دردسر بیشتری داره.
مطلب پایین این پترن رو به خوبی باز کرده و توضیح داده:
https://microservices.io/patterns/data/transactional-outbox.html
#pattern #microservices
✴️ @software_inside - مهندسینرمافزار
Post #24
1.16K