Два клиента почти одновременно оформили последнюю единицу товара. Оба получили «Спасибо за заказ». А на складе — одна штука. Кому-то придётся звонить, извиняться и отменять оплаченный заказ. Это овербукинг, и на популярных позициях, распродажах и в опте он случается регулярно, если резервирование настроено небрежно. Каждый такой случай — удар по доверию и репутации магазина.
Эта статья — о том, как настроить резервирование товара и побороть овербукинг в магазине на 1С-Битрикс: когда резервировать, как работает штатный механизм модуля продаж, что делать с гонками и блокировками, как освобождать просроченные резервы и согласовывать остатки с 1С. Тема бэкендовая и требует аккуратной архитектуры — такие задачи мы закрываем в рамках автоматизации продаж и склада на 1С.
Коротко
- Овербукинг — продажа большего количества, чем есть; его причина в отсутствии или гонках резерва.
- Момент резерва — компромисс между защитой от овербукинга и «заморозкой» товара.
- Проверка остатка и списание в резерв должны быть атомарными — под блокировкой или в транзакции.
- Просроченные резервы обязательно освобождать по тайм-ауту агентом, иначе появляется ложный дефицит.
Что такое овербукинг и чем он опасен
Овербукинг — это когда магазин пообещал товар большему числу покупателей, чем может отгрузить. Формально заказы оформлены и даже оплачены, но физически товара на всех не хватает. В отличие от честного «нет в наличии», овербукинг возникает уже после подтверждения заказа, и разгребать его приходится вручную.
Цена овербукинга не только в отменах. Это испорченное впечатление, негативные отзывы, возвраты денег, потерянное доверие и время менеджеров. В опте последствия тяжелее: сорванный резерв под спецификацию может остановить производство клиента. Поэтому резервирование — не «приятная опция», а часть надёжности магазина, особенно если товар дефицитный или идут распродажи.
Когда резервировать: корзина, заказ, оплата
Ключевое проектное решение — в какой момент «замораживать» товар за покупателем. Это всегда компромисс между защитой от овербукинга и эффективным использованием остатка.
| Момент резерва | Плюсы | Минусы |
|---|---|---|
| При добавлении в корзину | Максимальная защита от овербукинга | Товар «мёрзнет» за теми, кто не купит; нужны тайм-ауты |
| При оформлении заказа | Баланс защиты и экономии остатка | Небольшое окно гонки до создания заказа |
| При оплате | Резерв только под реальные деньги | Широкое окно гонки; на дефиците рискованно |
Частая рабочая схема — резерв при создании заказа с коротким тайм-аутом на оплату, а для дефицитных и распродажных позиций резерв делают раньше, вплоть до корзины. Универсального ответа нет: выбор зависит от оборачиваемости, доли брошенных корзин и того, насколько болезненна для вас «заморозка» товара.
Механизм резерва в модуле продаж
Модуль «Интернет-магазин» в 1С-Битрикс умеет резервировать товар под заказ штатно. При создании или оплате заказа заданное количество уходит в резерв и вычитается из доступного остатка, а сам резерв виден в заказе. В настройках определяется, резервировать ли автоматически и в какой момент это происходит.
Штатного механизма достаточно для простых сценариев: один склад, резерв под заказ, ручное управление. Но как только появляются тонкие требования — резерв в корзине, короткие тайм-ауты на оплату, несколько складов, высокая конкуренция за дефицит — штатной логики не хватает, и её дорабатывают поверх. Делать это нужно на современном API, а не правками ядра: подходы мы разбирали в статье про D7 и ORM в 1С-Битрикс.
Резерв и остатки при обмене с 1С
В большинстве магазинов «источник истины» по остаткам — это 1С, а сайт получает доступные остатки обменом (CommerceML) и передаёт обратно заказы и резервы. Здесь важно чётко договориться, кто чем управляет: обычно 1С владеет физическим остатком, а сайт создаёт резервы под заказы, которые затем учитываются в 1С.
Главная опасность — рассинхронизация между выгрузками. Если обмен идёт раз в час, между обменами сайт и 1С видят остаток по-разному, и на дефицитной позиции это создаёт окно для овербукинга. Отсюда правила: на критичных товарах резерв на сайте должен быть строгим, а обмен остатками — достаточно частым. Про инфраструктуру, которая тянет частый обмен и нагрузку, мы писали в материале про хостинг и инфраструктуру BitrixVM.
Гонки и конкурентный доступ
Технический корень овербукинга — гонка (race condition). Два запроса почти одновременно читают остаток «1 штука», оба считают, что товар есть, и оба создают заказ. Ни один не знает о другом, потому что между чтением остатка и его уменьшением есть зазор, в который «проскакивает» второй запрос.
Иллюстрация проблемы по шагам:
- Запрос A читает остаток. Видит «1 штука доступна».
- Запрос B читает остаток. Тоже видит «1 штука» — A ещё не списал.
- A создаёт резерв. Остаток должен стать 0.
- B создаёт резерв. B действовал по устаревшему чтению — итог −1, овербукинг.
Чем выше конкуренция за товар (распродажа, дефицит, опт по спецификации), тем чаще срабатывает гонка. Поэтому надёжный резерв — это в первую очередь защита операции от одновременного доступа, а не просто «вычесть единицу».
Блокировки и транзакции
Гонка закрывается тем, что проверка остатка и списание в резерв делаются атомарно. Есть два основных инструмента: транзакция базы данных и блокировка записи товара. Идея одна — пока один запрос проверяет и уменьшает остаток, второй ждёт и потом видит уже обновлённое значение, а не устаревшее.
На практике это блокировка на уровне строки товара или продуманная транзакция с проверкой актуального остатка внутри неё. Важно держать блокировку максимально короткой, чтобы не создать очередь и не уронить производительность. Это тонкий баланс между корректностью и скоростью, который и отличает грамотно спроектированный резерв.
Тайм-аут резерва и его освобождение
Резерв под неоплаченный заказ не может жить вечно, иначе брошенные корзины навсегда «съедят» склад. Появляется ложный дефицит: физически товар есть, но он заморожен за заказами, которые никто не оплатит. Решение — тайм-аут резерва и фоновое освобождение просроченных.
- Срок жизни резерва. Например, время, отведённое на оплату заказа.
- Фоновая задача. Агент или крон периодически ищет просроченные резервы.
- Возврат в остаток. Освобождённое количество снова становится доступным.
- Уведомление. При необходимости — оповестить клиента, что резерв истёк.
В 1С-Битрикс такую фоновую логику удобно вешать на агенты или на крон-задачи. Важно, чтобы освобождение резерва тоже было атомарным и не конфликтовало с одновременным оформлением новых заказов — здесь снова работают транзакции и блокировки.
Предзаказ и товары под заказ
Не всё продаётся из наличия. Для товаров под заказ и предзаказов логика резерва другая: физического остатка может не быть, но обязательство перед клиентом есть. Здесь важно не смешивать «резерв из наличия» и «заказ поставки под клиента» — это разные состояния, и путать их опасно.
Практически для таких позиций вводят отдельный статус: товар не резервируется из склада, а помечается как заказанный под клиента с ожидаемым сроком поставки. Тогда покупатель видит честный срок, а не ложное «в наличии», и овербукинг из наличия не возникает, потому что этот товар вообще не претендует на складской остаток.
Многоскладской резерв
Как только складов становится больше одного, резерв усложняется. Теперь важно не «есть на остатках вообще», а «есть на складе, с которого отгрузим этому клиенту». Резерв должен уменьшать доступное количество конкретного склада, а для этого нужно выбрать склад отгрузки ещё на этапе оформления.
Это порождает дополнительные вопросы: что делать, если на ближайшем складе не хватает, а на дальнем есть; можно ли собирать заказ с нескольких складов; как это отражается в 1С. Многоскладской резерв почти всегда требует доработки поверх штатного механизма и особенно тесной сверки с учётной системой, потому что цена ошибки — сорванная отгрузка. Проектировать такую логику лучше как отдельный аккуратный модуль — подходы описаны в статье про разработку своего модуля для 1С-Битрикс.
Нагрузка и highload
Резервирование проверяется на прочность именно под нагрузкой — в момент распродажи или запуска дефицитного товара, когда сотни покупателей бьются за один остаток. Здесь важно, чтобы механизм оставался и корректным, и быстрым:
- Короткие блокировки. Держать запись товара заблокированной минимально, чтобы не собирать очередь.
- Атомарные операции на уровне БД. Проверка и списание одной командой, где это возможно.
- Готовая инфраструктура. Сервер и база должны выдержать пиковый конкурентный доступ.
- Продуманный кэш остатков. Витрина может показывать остаток из кэша, но списание всегда сверяется с актуальным значением под блокировкой.
Ошибка кэширования особенно коварна: показывать доступность из кэша можно, но принимать решение о резерве по кэшу — нельзя. Итоговое списание всегда идёт по актуальному остатку, иначе кэш сам становится источником овербукинга.
Мониторинг и расхождения
Даже хорошо спроектированный резерв нужно наблюдать. Расхождения между остатком на сайте, резервами и данными 1С неизбежно накапливаются, и лучше находить их мониторингом, чем по жалобам клиентов. Полезно регулярно сверять доступный остаток, сумму активных резервов и физический остаток из 1С.
Признаки проблем, которые стоит ловить: отрицательные доступные остатки, «вечные» резервы без освобождения, систематические отмены из-за нехватки товара. Каждый из них указывает на конкретный дефект — гонку, неработающий тайм-аут или редкий обмен. Мониторинг превращает борьбу с овербукингом из авралов в управляемый процесс.
Частые ошибки
- Проверка и списание не атомарны. Между ними вклинивается второй запрос — овербукинг под нагрузкой.
- Нет тайм-аута резерва. Брошенные корзины навсегда замораживают склад, появляется ложный дефицит.
- Решение о резерве по кэшу. Списание идёт по устаревшему кэшированному остатку.
- Редкий обмен с 1С. Между выгрузками сайт и 1С видят остаток по-разному.
- Длинные блокировки. Запись товара держится заблокированной слишком долго, растёт очередь.
- Смешение наличия и предзаказа. Товар под заказ резервируют из склада, которого нет.
- Нет мониторинга. Расхождения находят клиенты, а не команда.
Чек-лист внедрения
- Момент резерва выбран. Определён шаг резервирования под вашу оборачиваемость и дефицит.
- Операция атомарна. Проверка остатка и списание в резерв защищены транзакцией или блокировкой.
- Тайм-ауты работают. Просроченные резервы освобождаются агентом или кроном.
- Обмен с 1С настроен. Остатки и резервы синхронизируются достаточно часто, роли разграничены.
- Кэш безопасен. Витрина может кэшировать доступность, но списание идёт по актуальному остатку.
- Многосклад учтён. Если складов несколько — резерв ведётся в разрезе склада отгрузки.
- Предзаказ отделён. Товары под заказ помечаются статусом, а не резервируются из наличия.
- Мониторинг стоит. Регулярная сверка остатков, резервов и данных 1С, ловля аномалий.
Вывод
Овербукинг — не случайность, а следствие небрежного резервирования: гонок при конкурентном доступе, решений по кэшу и редкого обмена с 1С. Побеждается он архитектурой: выбором момента резерва, атомарными операциями под блокировкой или в транзакции, тайм-аутами с фоновым освобождением и частым согласованием остатков с учётной системой.
Штатного механизма модуля продаж хватает для простых магазинов, но дефицит, распродажи, тайм-ауты и несколько складов требуют аккуратной доработки поверх него — на современном API и с мониторингом. Настройте резерв правильно, и последняя единица товара уйдёт ровно одному покупателю, а не двоим с последующими извинениями.