سیستم‌های توزیع‌شده

طراحی Offline-first؛ همگام‌سازی امن با Outbox و Idempotency

راهنمای طراحی سیستم‌های Offline-first: ثبت محلی، Transactional Outbox، جلوگیری از رویداد تکراری، مدیریت تعارض و آزمون قطع شبکه.

در یک سامانهٔ شعبه‌ای، قطع اینترنت نباید به گم‌شدن سفارش یا توقف همهٔ کارهای روزمره تبدیل شود. معماری Offline-first از یک پرسش آغاز می‌شود: کدام عملیات باید در محل انجام شوند و کدام تصمیم‌ها به دادهٔ مرکزی وابسته‌اند؟ پاسخ این پرسش، مرز اختیار شعبه و قرارداد همگام‌سازی را مشخص می‌کند.

ابتدا مرز عملیات محلی را مشخص کنیم

ثبت سفارش، ذخیرهٔ پیش‌نویس و مشاهدهٔ اطلاعات کش‌شده می‌توانند مسیر محلی داشته باشند. تأیید پرداخت آنلاین یا اعمال یک سقف اعتباری سراسری ممکن است به ارتباط نیاز داشته باشد. رابط کاربری باید تفاوت «ثبت محلی»، «در انتظار ارسال» و «تأیید مرکزی» را نشان دهد. Offline-first به معنای تضمین انجام هر عملیات در حالت قطع ارتباط نیست.

Transactional Outbox چه مسئله‌ای را حل می‌کند؟

اگر تغییر کسب‌وکار در پایگاه داده ثبت شود ولی ارسال رویداد شکست بخورد، مرکز از تغییر خبر ندارد. یک راه، ثبت تغییر و رکورد خروجی در همان تراکنش محلی است. عامل همگام‌سازی بعداً رکوردهای خروجی را ارسال می‌کند. راهنمای AWS دربارهٔ Transactional Outbox این مسئلهٔ نوشتن دوگانه را شرح می‌دهد.

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

Idempotency؛ تکرار نباید نتیجه را عوض کند

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

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

تعارض داده‌ها یک سیاست کسب‌وکار است

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

صف، بازیابی و مشاهده‌پذیری

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

چک‌لیست آزمون قطع ارتباط

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

برای یک زمینهٔ کاربردی، بریف معماری کافه‌چی و عملیات شعبه را ببینید. اگر نرم‌افزار روی نودهای مستقل منتشر می‌شود، راهنمای GitOps و بازگشت نسخه مکمل این طراحی است.