صف پیام: چرا سیستم شما به آن نیاز دارد

سناریویی که تقریباً هر تیمی یک بار تجربهاش کرده: سامانهٔ انبار برای نیم ساعت بالا نمیآید و در همان نیم ساعت، هر سفارشی که ثبت میشود با خطا مواجه میشود. مشتری نمیتواند خرید کند، چون یک سامانهٔ داخلی که اصلاً نباید جلوی خرید را بگیرد، خوابیده.
صف پیام دقیقاً برای همین وضعیت ساخته شده.
چه کاری میکند
بهجای اینکه سامانهٔ فروش مستقیم به انبار زنگ بزند و منتظر بماند، پیام را در یک صف میگذارد و کارش را ادامه میدهد. انبار هر وقت توانست پیام را برمیدارد و پردازش میکند.
نتیجهاش این است که خرابی موقت انبار، فروش را متوقف نمیکند. پیامها در صف میمانند و وقتی برگشت، پردازش میشوند.
کجا واقعاً جواب میدهد
کاری که میتواند دیرتر انجام شود. ارسال پیامک، ثبت سند مالی، بهروزرسانی گزارش، ارسال سفارش به انبار. هیچکدام لازم نیست در همان ثانیهٔ کلیک مشتری انجام شوند.
کاری که طول میکشد. تولید فایل اکسل از صد هزار ردیف، پردازش تصویر، ارسال ایمیل به ده هزار نفر. کاربر نباید منتظر بماند.
بار ناگهانی. در کمپین فروش، هزار سفارش در دقیقه میآید و سامانهٔ انبار ظرفیت پردازش صد تا را دارد. صف نقش ضربهگیر را بازی میکند: پیامها جمع میشوند و با سرعت قابل تحمل پردازش میشوند.
چند گیرنده برای یک اتفاق. ثبت سفارش باید به انبار برود، به مالی برود، و پیامکی هم برای مشتری برود. با صف، سامانهٔ فروش فقط یک بار اعلام میکند.
کجا اشتباه است
اگر جواب را همین حالا لازم دارید، صف کمکی نمیکند. استعلام ماندهٔ اعتبار پیش از ثبت سفارش، تماس مستقیم میخواهد.
و اگر یک برنامه دارید و همهچیز در همان یک فرایند انجام میشود، افزودن صف یعنی خریدن پیچیدگی توزیعشده بدون داشتن مسئلهٔ توزیعشده.
سه مسئلهای که با صف میآیند
اینجا جایی است که تیمها معمولاً غافلگیر میشوند.
پیام ممکن است دو بار برسد. بیشتر صفها تحویل «دستکم یک بار» را تضمین میکنند، نه «دقیقاً یک بار». یعنی گیرنده باید بتواند تشخیص دهد این پیام را قبلاً دیده.
راهش: هر پیام یک شناسهٔ یکتا دارد و گیرنده شناسههای پردازششده را نگه میدارد. ساده است، و اگر از ابتدا نباشد بعداً پیدا کردن باگش سخت است چون فقط گاهی اتفاق میافتد.
ترتیب تضمینی نیست. «سفارش لغو شد» ممکن است قبل از «سفارش ثبت شد» برسد. اگر ترتیب مهم است، یا از صفی استفاده کنید که ترتیب را در یک کلید تضمین میکند، یا شمارهٔ ترتیب در پیام بگذارید و گیرنده پیام زودرس را کنار بگذارد تا نوبتش برسد.
پیامی که همیشه شکست میخورد. پیام معیوبی که هر بار پردازش میشود، خطا میدهد، برمیگردد به صف، و دوباره. حلقهای که صف را میبندد و منابع را میخورد.
راهش صف مردگان است: بعد از چند تلاش ناموفق، پیام به صف جداگانهای میرود تا آدمی نگاهش کند. این صف باید پایش شود. صف مردگانی که کسی نمیبیندش، همان گمشدن پیام است با مراحل بیشتر.
چیزهایی که باید ببینید
سه عدد که برای هر صف باید در دسترس باشند:
طول صف. اگر مدام رشد میکند، گیرنده از فرستنده عقب افتاده و دیر یا زود منفجر میشود.
سن قدیمیترین پیام. مستقیم میگوید چقدر عقبید.
و تعداد پیام در صف مردگان، با هشدار روی هر ورودی جدید.
بدون این سه، صف تبدیل به جایی میشود که پیامها در آن ناپدید میشوند و کسی نمیفهمد.
تجربهٔ کاربر عوض میشود
نکتهای که فنی نیست و بیشتر از بقیه اثر دارد: وقتی کاری ناهمگام شد، کاربر دیگر نتیجه را فوری نمیبیند.
مشتری سفارش میدهد و انبار هنوز پردازشش نکرده. اگر رابط کاربری بگوید «ثبت شد» و بعد پنج دقیقه بعد وضعیت عوض شود، مشتری گیج میشود.
راهش صادق بودن دربارهٔ وضعیت است: «سفارش شما ثبت شد و در انتظار تأیید انبار است». همان چیزی که در چرخهٔ سفارش تا وصول هم گفتیم — وضعیتهای میانی باید برای کاربر دیده شوند، نه پنهان.
از کجا شروع کنید
لازم نیست از روز اول زیرساخت پیامرسانی کامل بیاورید. اگر یک یا دو جریان ناهمگام دارید، جدولی در همان پایگاه دادهٔ فعلی بهعنوان صف کاملاً کار میکند و هیچ سرویس جدیدی نمیخواهد.
سراغ صف اختصاصی وقتی بروید که حجم بالا رفت، چند گیرنده پیدا شد، یا نیاز به تضمینهایی داشتید که با یک جدول ساده نمیشود داد.
و در هر دو حالت، آن سه مسئله — تکرار، ترتیب، و شکست مکرر — از روز اول باید جواب داشته باشند. اضافهکردنشان بعد از اینکه سامانه در تولید است، بهمراتب سختتر است.