+− THE DAILY DIFFdev & AI news
SHIP IT

Shopify перемістив резервування запасів у MySQL

Shopify перемістив свою систему резервування запасів з Redis до бази даних MySQL, яка вже містила реєстр запасів.

Shopify перемістив свою систему резервування запасів з Redis до бази даних MySQL, яка вже містила реєстр запасів. Обмежений пул окремих рядків одиниць, що блокуються, дозволяє одночасним оформленням замовлень використовувати SKIP LOCKED для вибору різних відповідних одиниць. Дизайн також залежить від меж транзакцій, макету первинного ключа, правил поповнення та спостереження за часом утримання з'єднання під час оформлення замовлення.

Читати письмову версію (англійською) ↗

Що охоплює це відео

  • Стара модель лічильника кількості Redis обробляла паралелізм, але очищення резервування та оновлення реєстру MySQL не могли розділити одну локальну атомарну транзакцію.
  • Заміна використовує один рядок на доступну одиницю в пулі, обмеженому 1000 одиниць на комбінацію товару/місця. Порожній пул може викликати вбудоване поповнення з одночасними запитами, що очікують за блокуванням поповнення.
  • Композитний первинний ключ: (shop_id, inventory_item_id, inventory_group_id, id). Shopify зменшив накладні витрати на блокування у своєму прототипі та використовував READ COMMITTED, щоб уникнути блокувань проміжків, які блокували поповнення.
  • Резерв видаляє рядки пулу перед вставкою записів резервування. Фіксація звільняє блокування бази даних, тоді як збережене утримання зберігається під час оплати; успішна оплата заявляє про реєстр і видаляє резервування в пізнішій атомарній транзакції.
  • Документи MySQL SKIP LOCKED як непослідовний вигляд, який пропускає заблоковані рядки. Він не встановлює повного підрахунку запасів або справедливого чергування, застосовується лише до блокувань на рівні рядків і небезпечний для реплікації на основі операторів.
  • Приклад джерела містить expires_at, але Shopify не документує алгоритм очищення терміну дії MySQL. Гілка випуску/терміну дії відео є пояснювальною вимогою життєвого циклу.
  • Час утримання з'єднання в іншому коді оформлення замовлення був останнім вузьким місцем пропускної здатності. Shopify тінню записував обидві системи, порівнював результати та поступово переходив з резервним вимикачем Redis.

Перекладена стенограма

Перекладено з оригінальної англійської розповіді. Доступне аудіо та субтитри контролюються YouTube.

Навіщо переміщувати резервування в MySQL?

0:00 Оформлення замовлення потребує Redis, щоб залишатися швидким. Shopify перемістив резервування запасів у MySQL, використовуючи один рядок на одиницю в обмеженому пулі. Чому вибрати MySQL? Як безпечно пропускати блокування? Це The Daily Diff, під капотом. І чому швидкі запити все ще досягали стелі? Shopify — це комерційна платформа для продажу онлайн та особисто. Redis — це сховище даних у пам'яті.

0:21 MySQL — це реляційна база даних, і Shopify вже зберігав свій реєстр запасів там. Резервування короткочасно утримує товар, поки покупець платить.

Чому два магазини були ризикованими?

0:29 Їхня модель Redis зменшувала лічильник товарів. Заявка на оплачене замовлення означала оновлення реєстру MySQL та очищення Redis. Ці окремі записи могли призвести до того, що товар продавався двічі або був недоступним, коли він повинен бути продаваним. Стара модель також не мала обізнаності про місцезнаходження. Заміна повинна вибрати товар з місця, яке може виконати замовлення. Склад на неправильному континенті робить чудовий запис у базі даних і жахливу обіцянку доставки. жахливу обіцянку доставки. Раніше спроби MySQL використовували рядок кількості, тому конкуруючі оформлення замовлень ставали в чергу до того ж

Що стає одиницею, що блокується?

0:56 блокування. Уявіть оксамитовий мотузок навколо комірки електронної таблиці. Додавання більшої кількості працівників лише подовжує чергу. Shopify змінив об'єкт, що блокується. Кожна доступна одиниця отримує свій власний рядок. Блокуюче читання пропускає одиниці, які утримує інша транзакція, і вибирає інші відповідні одиниці. Різні працівники можуть отримувати різні рядки, тоді як гарячий лічильник залишається поза їхнім шляхом.

Що відбувається, коли пул спустошується?

1:15 Цей пул обмежений тисячею рядків на товар та місцезнаходження. Поповнення відбувається з реєстру. Якщо він спустошується, резервний шлях поповнюється вбудовано, з конкуруючими запитами, що очікують за блокуванням поповнення. Порожній пул не означає порожній склад. Резерв видаляє вибрані рядки пулу, потім вставляє записи резервування в транзакцію. Фіксація знімає блокування бази даних.

1:35 Відкат скасовує зміни. Резервування зберігається після обробки платежу як збережений стан. Успішна оплата заявляє про реєстр і атомарно видаляє резервування. Блокуванням бази даних ніколи не потрібно стежити за платіжною формою. Їхній композитний первинний ключ починається з магазину, товару, групи, потім ідентифікатора одиниці. Відповідність пошуку зменшила блокування індексу в їхньому прототипі. Вони також використовують read committed, щоб уникнути блокувань проміжків, які блокували поповнення пулу,

1:57 та послідовний порядок таблиць, щоб запобігти циклічним очікуванням. Опублікований приклад записує час закінчення терміну дії. Покинуті платежі потребують звільнення товару зрештою, інакше кошик для покупок стає орендодавцем. Повідомлення Shopify залишає цей алгоритм очищення невизначеним, тому ця діаграма показує вимогу життєвого циклу. Ось у чому заковика.

Що пропускає SKIP LOCKED?

2:14 Skip locked виключає заблоковані рядки, тому в посібнику його результат називається непослідовним переглядом. Він не забезпечує ні повного підрахунку запасів, ні справедливого чергування. Зберігайте рішення про доступність та правила поповнення навколо нього.

Де була справжня стеля?

2:26 А та стеля? Інший код оформлення замовлення занадто довго утримував з'єднання з базою даних. Shopify позначив абонентів та виміряв час утримання з'єднання, потім очистив шлях оформлення замовлення та переглянув паралелізм потоків. Швидкі запити все ще можуть стояти в черзі поза запитом.

Чому я б відправив цей дизайн?

2:38 Вони тінню записували обидві системи з авторизацією Redis, порівнювали результати, потім поступово переходили з вимикачем. Мій вердикт — SHIP IT. Я б відправив спільну межу транзакції та той відкочуваний розгортання, з усім інструментарієм шляху оформлення замовлення. Маєте питання щодо цього? Залиште їх у коментарях. І це на сьогоднішній день.

2:54 Я Ніко з Axrisi. Зливайте відповідально.

Джерела

  1. We replaced Redis with MySQL for inventory reservations—and it scaledShopify Engineering — Emilie Noel
  2. Simplified reservation SQL embedded in Shopify's articleShopify Engineering / CourtneySymons on GitHub Gist
  3. MySQL 8.0 — Locking ReadsOracle / MySQL Reference Manual
  4. MySQL 8.0 — Transaction Isolation LevelsOracle / MySQL Reference Manual
  5. What Is Shopify and How Does It Work?Shopify
  6. Redis quick startsRedis documentation
  7. What is MySQL?Oracle / MySQL Reference Manual

Пов'язані відео