Amirali Yaghoutiمهندس ارشد نرم‌افزار

مطالعه موردی مهندسی

محافظ طوفان Transient

دو افزونه روی فروشگاه به ازای هر بازدید محصول یک ترنزینت می‌نویسند: محصولات مرتبط ووکامرس و بازدیدهای اخیر YITH. روی کاتالوگی به این اندازه، این یعنی ده‌ها هزار ردیف در wp_options و هر بار بوت‌شدن وردپرس هزینه‌اش را می‌دهد.

مسئله تجاری

جدول wp_options ده‌ها هزار ردیف _transient_wc_related_ و _transient_yith_wrvp_ را حمل می‌کرد. توصیه‌ی رایج یک کرون پاک‌سازی شبانه است، اما DELETE JOIN روی جدولی با این حجم آن‌قدر جدول را نگه می‌دارد که اثرش در فرانت حس می‌شود. چیزی می‌خواستم که فقط وقتی واقعاً طوفانی هست فعال شود و هیچ‌وقت جدول options را طولانی قفل نکند.

آنچه تحویل دادم

  • mu-transient-storm-guard.php، یک افزونه‌ی MU صد و دو خطی که یک رویداد روزانه دارد و در یک روز سالم اصلاً کاری نمی‌کند.
  • آستانه‌ی جدا برای هر خانواده به‌جای یک آستانه‌ی سراسری: wc_related بالای ۴٬۰۰۰ ردیف پاک می‌شود و yith_wrvp بالای ۲٬۰۰۰، چون نرخ رشدشان یکی نیست.
  • یک جاروی تکه‌ای برای ترنزینت‌های منقضی که هر بار ۲۰۰ ردیف timeout را حذف می‌کند، نه آن DELETE JOIN که اغلب اسنیپت‌ها سراغش می‌روند.
  • یک گارد که در حین جاب‌های WP All Import کل اجرا را رد می‌کند، تا ایمپورت کاتالوگ هیچ‌وقت با پاک‌سازی سر یک جدول رقابت نکند.

رویکرد فنی

  • اول شمردن، بعد حذف. هر خانواده با یک COUNT(*) اندازه‌گیری می‌شود و فقط اگر از آستانه‌ی خودش رد شده باشد پاک می‌شود؛ همین باعث می‌شود افزونه بیشتر روزها هیچ کاری نکند.
  • حذف‌ها سقف ۲٬۰۰۰ ردیف دارند و همیشه ردیف مقدار را همراه ردیف _timeout_ متناظرش برمی‌دارند، تا هیچ timeout یتیمی نماند که فردا دوباره شمرده شود.
  • رویداد روزانه ۳۰۰ ثانیه بعد از init زمان‌بندی می‌شود نه بلافاصله، تا از لحظه‌ای که سایت خودش درگیر بوت‌شدن است فاصله بگیرد.
  • مالتی‌سایت پاس جداگانه‌ی خودش را با فلگ شبکه می‌گیرد.

نتیجه و شواهد

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

اهمیت برای کارفرما

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

خلاصه-اجرایی-پروژه

خلاصه اجرایی خوانا

خلاصه_اجرایی {
  پروژه: "Transient Storm Guard"
  فایل: "mu-plugins/mu-transient-storm-guard.php (۱۰۲ خط)"
  ماشه: "کرون روزانه، ۳۰۰ ثانیه پس از init"
  آستانه‌ها: "wc_related > ۴۰۰۰ ردیف، yith_wrvp > ۲۰۰۰ ردیف"
  پاک‌سازی: "سقف ۲۰۰۰ در هر خانواده، ردیف مقدار + timeout"
  جارو: "۲۰۰ ترنزینت منقضی در هر اجرا، بدون DELETE JOIN"
  رد_می‌کند: "درخواست‌های WP All Import، برای پرهیز از رقابت"
}

ارزش حرفه‌ای این پروژه

چیزی که اینجا ارزش دیدن دارد آستانه است نه خود حذف. نوشتن یک کرون پاک‌سازی از هرکسی برمی‌آید؛ ریسک این است که خود پاک‌سازی روی یک جدول پرترافیک تبدیل به مسئله شود.

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