شاپیفای رزرو موجودی رو از Redis برد روی MySQL
خلاصهٔ کاملتر
نویسنده توضیح میده موقع تکمیل خرید باید مطمئن بشن کالا هنوز موجوده؛ خطا در یه جهت یعنی فروش بیشازحد و کنسلشدن سفارش، در جهت دیگه یعنی فروشی که از دست میره. تو بلکفرایدی ۲۰۲۵ فروش پلتفرم در اوج به ۵.۱ میلیون دلار در دقیقه رسید. سیستم قبلی روی Redis بود و رزرو با DECR انجام میشد، ولی چون رزروها و دفتر کل موجودی توی دو سیستم جدا بودن، مرحلهٔ claim رو نمیشد اتمیک کرد و بسته به ترتیب، یا فروش بیشازحد پیش میاومد یا کمفروشی.
طراحی جدید بهجای یه ردیف با ستون تعداد، برای هر واحد فروشپذیر یه ردیف میسازه؛ رزرو سه واحد یعنی جابهجاکردن سه ردیف توی یه تراکنش. SKIP LOCKED باعث میشه اگه تراکنش دیگهای چند ردیف رو قفل کرده باشه، MySQL ازشون رد شه و ردیفهای آزاد رو برگردونه. چون یه ردیف بهازای هر واحد برای کالای پرتعداد منفجر میشه، یه استخر محدود حداکثر ۱۰۰۰ ردیفی بهازای هر ترکیب کالا/انبار نگه میدارن که یه فرایند جداگانه دوباره پرش میکنه.
سه تصمیم فنی مهم بودن: کلید اصلی ترکیبی روی همون ستونهایی که فیلتر میشن، تا InnoDB بهجای دو قفل روی هر ردیف فقط یکی بگیره؛ سطح ایزولیشن READ COMMITTED بهجای REPEATABLE READ تا gap lockها جلوی درج ردیفهای تازه رو نگیرن؛ و ترتیب یکسان قفلگیری بین مسیر reserve و claim تا بنبست پیش نیاد. کوئریهای سبدهای چند قلمی هم با UNION ALL توی یه رفتوبرگشت جمع میشن.
جالبترین بخش پست همینجاست: با اینکه تأخیر و CPU مشکلی نداشتن، توی پروداکشن به سقفی خیلی پایینتر از هدف خوردن. تیم هر کوئری رو با یه کامنت برچسب زد که میگفت کدوم فرایند کسبوکار صداش کرده، و توی لایهٔ ProxySQL مدت نگهداشتن کانکشن رو به تفکیک همون برچسب اندازه گرفت. معلوم شد بخشهای دیگهٔ مسیر چکاوت کانکشنها رو طولانی نگه میداشتن. تمیزکاری اون مسیر ۵۰٪ خوندنها و ۳۳٪ تراکنشهای دیتابیس اصلی رو حذف کرد.
مهاجرت هم یکشبه نبود: مدتی هر رزرو همزمان توی Redis و MySQL نوشته میشد و Redis منبع حقیقت موند تا درستی و کارایی روی ترافیک واقعی سنجیده شه، بعد پاد به پاد سوئیچ کردن. جمعبندی نویسنده اینه که تصمیمهای قدیمی رو باید دوباره سنجید — چیزی که پنج سال پیش شدنی نبود امروز شدنیه — و وقتی عددها با هم نمیخونن، باید کل مسیر رو ابزارگذاری کرد، نه فقط موتور رو.
نکات کلیدی:
- SKIP LOCKED در MySQL 8 اجازه داد بهجای یه ردیف با ستون تعداد، برای هر واحد کالا یه ردیف نگه دارن
- استخر محدود ۱۰۰۰ ردیفی بهازای هر کالا/انبار، جدول رو کوچیک و اسکن رو سریع نگه میداره
- کلید اصلی ترکیبی تعداد قفل هر رزرو رو از دو تا به یکی رسوند
- READ COMMITTED جلوی gap lockهایی رو گرفت که درج ردیف تازه رو بلاک میکردن
- گلوگاه واقعی کانکشنهای دیتابیس بود، نه CPU یا کوئریها




