
Shopify перевів резервування запасів із Redis на MySQL — і система витримала
Shopify перенесла захист від надпродажів з Redis на MySQL, побудувавши резервування на SKIP LOCKED і одному рядку на одиницю товару. Головний урок: вузьким місцем виявилися з'єднання, а не CPU.
Shopify замінила систему захисту від надпродажів на базі Redis рішенням, побудованим на функції SKIP LOCKED у MySQL 8, і, за словами компанії, досягла цільової пропускної здатності під час пікового навантаження 2025 року.
Чому стара схема перестала працювати
Захист від надпродажів складається з двох операцій: резервування — короткого утримання, яке виникає на старті оплати, — і підтвердження, яке після успішної оплати остаточно списує одиницю з реєстру запасів. Раніше резервування зберігалися в Redis: зарезервувати означало зменшити ключ, а звільнити — збільшити його. Redis добре працював із конкурентністю, але резервування й реєстр жили в різних системах, тож на етапі підтвердження доводилося оновлювати MySQL і прибирати запис у Redis, а об'єднати ці дії в один атомарний крок було неможливо. Залежно від порядку це могло призводити до надпродажу або недопродажу, а модель не враховувала запаси в кількох локаціях.
Один рядок на одиницю, в обмеженому пулі
Нова схема зберігає один рядок на кожну одиницю товару, а не один рядок на товар із колонкою кількості: товар із десятьма одиницями має десять рядків, і резервування може жити з реєстром в одній ACID-транзакції. Команда тримає обмежений пул доступних рядків — максимум 1000 на пару «товар-локація» — який поповнює процес наповнення з реєстру. Якщо флеш-розпродаж спорожнить пул, наповнення запускається на місці під замком, тож паралельні резервування чекають, а не змагаються за вставку рядків.
Налаштування блокувань і справжня межа
Кілька деталей виявилися важливими. Складений первинний ключ за колонками фільтрації зменшив блокування рядків із двох до одного на кожне резервування. Перехід транзакцій на рівень ізоляції READ COMMITTED прибрав gap-блокування, які блокували наповнення. Уніфікований порядок блокувань ліквідував дедлоки між резервуванням і підтвердженням, а групування через UNION ALL скоротило кількість звернень до бази для кошиків із кількома позиціями.
Очікуваного вузького місця не з'явилося. CPU був далекий від насичення, запити вже оптимізовані, але команда все одно вперлася в стелю: з'єднання вичерпували інші частини шляху оформлення замовлення. Позначення кожного SQL-запиту бізнес-процесом і агрегація часу утримання з'єднань на рівні ProxySQL показали, хто саме споживає найбільше часу. Прибирання на шляху оформлення зняло 50% читань і 33% транзакцій із головного вузла, а перегляд давнього налаштування паралельності потоків InnoDB зняв ще одну межу.
Перемикання та результати
Redis і MySQL працювали паралельно в «тіньовому режимі», де джерелом істини залишався Redis; згодом Shopify перевела джерело істини на MySQL, зберігши аварійний вимикач, і розгортала зміну pod за podом. На Black Friday 2025 року продавці на платформі досягли рекордних 5,1 млн доларів продажів за хвилину на піку.
SiTech — веброзробка з підтримкою AI
Створюємо швидкі та сучасні сайти й інтегруємо AI у бізнес-процеси. Маєте проєкт чи запитання? Із задоволенням допоможемо.