СезонГотовим магазин к высокому сезону и Чёрной пятнице: скорость, нагрузка, акции

Управление остатками при высокой нагрузке: блокировки и резервы

Управление остатками и резервами товара под высокой нагрузкой на 1С-Битрикс: блокировки, транзакции, обмен с 1С

Распродажа, товар остался в одном экземпляре, и на него одновременно нажимают «купить» три человека. Все трое видели «в наличии», все трое оформили заказ. На складе — одна единица. Дальше начинается ручная разборка: кому-то придётся звонить и извиняться, кто-то оставит гневный отзыв, а склад останется в минусе. Это не редкость и не «сбой» — это закономерность любой системы, где остаток читают и списывают без защиты от гонок.

Эта статья — про инженерную сторону управления остатками на 1С-Битрикс под нагрузкой: почему возникают гонки при списании, чем резерв отличается от списания, как защитить остаток блокировками и атомарными операциями, как это уживается с обменом с 1С, веб-кластером и highload-блоками. Материал технический и связан с нашей работой по автоматизации продаж и склада на 1С.

Коротко

  • Перепродажа под нагрузкой — это гонка: два заказа списывают один остаток, потому что читают и пишут его отдельными операциями.
  • Резерв удерживает товар под заказ, не искажая физический остаток; списание — окончательное уменьшение при отгрузке.
  • Целостность обеспечивают атомарные операции и короткие блокировки строки товара, а не широкие блокировки таблиц.
  • Источник истины по остаткам — 1С; сайт оперативно резервирует, обмен CommerceML сверяет и подтверждает.

Проблема: перепродажа под нагрузкой

При низком трафике проблема остатков почти незаметна: заказы приходят по одному, между ними есть паузы, и система успевает корректно уменьшить остаток. Всё меняется на пике — распродажа, рекламный всплеск, дефицитный товар. Когда десятки запросов на один товар приходят почти одновременно, наивная логика «прочитали остаток, проверили, записали новый» ломается: между чтением и записью успевает вклиниться другой запрос.

Результат — перепродажа: продано больше, чем есть. Для бизнеса это дороже, чем кажется: отмены, недовольные клиенты, ручные компенсации, испорченная репутация в самый прибыльный момент. Поэтому управление остатками под нагрузкой — это не оптимизация «на потом», а базовое требование к торговой системе.

Гонки при списании остатка

Чтобы защититься, нужно понимать механику гонки. Классический сценарий выглядит так:

  1. Запрос A читает остаток. Видит «1 в наличии».
  2. Запрос B читает остаток. Тоже видит «1» — списание A ещё не произошло.
  3. Запрос A проверяет и списывает. «1 ≥ 1» — списывает, остаток становится 0.
  4. Запрос B проверяет и списывает. Он проверял против старого «1» — списывает тоже, остаток уходит в −1.

Ошибка не в коде проверки, а в том, что чтение, проверка и запись разнесены во времени и не защищены. Между шагами возможно вмешательство другого запроса. Лечится это тем, что операция «проверить и уменьшить» должна быть неделимой — атомарной — или выполняться под блокировкой, которая не даёт двум запросам одновременно менять один остаток.

Суть проблемы: опасно не само списание, а промежуток между «прочитали» и «записали». Устраните этот промежуток — атомарной операцией или блокировкой строки — и перепродажа исчезнет.
Слои кэширования ускоряют ответ БраузерзапросCDN / кэшготовый ответКомпозиткэш страницБазатолько при промахеБольшинство запросов отдаётся из кэша, до базы доходят единицы
Схема: между браузером и базой стоят слои кэша (CDN, композит). Большинство запросов отдаётся мгновенно из кэша, а до базы доходят единицы — сайт держит нагрузку.

Резерв против списания

Второй ключевой концепт — разделение резерва и списания. Их путают, и от этого возникают искажённые остатки.

АспектРезервСписание
Что делаетУдерживает товар под заказОкончательно уменьшает остаток
КогдаПри оформлении / оплатеПри отгрузке
Физический остатокНе меняется, но недоступен другимУменьшается фактически
ОбратимостьСнимается при отмене заказаОбычно окончательно

Резерв защищает от перепродажи, пока клиент оплачивает и заказ обрабатывается, но не искажает фактический остаток склада. Если резервы не снимать при отмене заказов, товар «зависнет» недоступным. Поэтому важна дисциплина: резерв ставится при оформлении, снимается при отмене или истечении срока, а списание происходит по факту отгрузки и сверяется с 1С.

Атомарность и блокировки строки

Технически целостность остатка обеспечивают на уровне СУБД двумя способами, которые часто комбинируют.

Важно, что блокируется именно строка нужного товара, а не вся таблица остатков — иначе под нагрузкой сайт встанет в очередь. Правильно спроектированные транзакции и работа с данными в современном Битрикс строятся на ORM. Как использовать транзакции и корректно работать с данными, мы разбираем в статье про D7 и ORM в Битрикс.

Резервирование в заказе Битрикс

В 1С-Битрикс резервирование — штатная возможность модуля «Интернет-магазин». Товар резервируется под заказ по заданным правилам: при создании заказа, при оплате или по статусу. У резерва есть срок и логика снятия. Настраивается это в параметрах каталога и заказа, но под нагрузкой важны не столько галочки, сколько согласованность.

Тонкость в том, что резерв на сайте и резерв в 1С — это две системы, которые нужно синхронизировать, иначе доступное количество разойдётся.

Обмен остатками с 1С

Физические остатки ведутся в 1С и приходят на сайт обменом по протоколу CommerceML. Учётная система — источник истины по факту, но в момент продажи сайт должен управлять доступностью оперативно, не дожидаясь следующей выгрузки. Отсюда типовая архитектура:

  1. 1С отдаёт остатки. Регулярный обмен обновляет физические остатки в каталоге сайта.
  2. Сайт резервирует оперативно. В момент заказа сайт удерживает товар, не дожидаясь следующего обмена.
  3. Обмен сверяет. Следующая выгрузка согласует резервы и фактические остатки, подтверждает списания.
  4. Конфликты разрешаются по правилам. Если данные разошлись, приоритет и логика слияния заданы заранее.

Главная причина перепродаж на практике — редкий обмен и рассинхрон резервов. Если сайт узнаёт об изменении остатка раз в час, а продажи идут каждую минуту, окно ошибки велико. Частота и надёжность обмена — вопрос архитектуры интеграции, который мы решаем услугой автоматизации на 1С.

Веб-кластер и общая база

Когда трафик растёт, сайт масштабируют — в том числе штатным веб-кластером Битрикс: несколько веб-нод, репликация базы, распределённые сессии и кэш. Здесь важно не питать иллюзий: кластер увеличивает пропускную способность, но не решает проблему гонок за остаток сам по себе.

Наоборот, в кластере из нескольких нод корректная блокировка становится критичнее: одновременные запросы приходят с разных серверов к общей СУБД. Если целостность остатка держалась на предположении «всё в одном процессе», в кластере она рассыплется. Правило простое: пропускную способность масштабирует кластер, а целостность остатка обеспечивают транзакции и блокировки на уровне общей базы, которую видят все ноды. Как устроена инфраструктура под нагрузку, мы разбираем в статье про хостинг и инфраструктуру BitrixVM.

Highload-блоки и хранение данных

Highload-блоки в 1С-Битрикс — инструмент для больших справочников с быстрым доступом. Возникает соблазн хранить в них и остатки, но здесь нужна осторожность. Остаток — часто меняющаяся величина, тесно связанная с торговым каталогом и заказами, и штатные механизмы каталога и заказа уже умеют его резервировать и списывать.

Ключевой критерий — где проще и надёжнее обеспечить атомарность изменения при вашей нагрузке. Иногда это штатный каталог, иногда — отдельная структура с продуманными блокировками. Это архитектурное решение, а не вопрос моды на инструмент.

Короткие блокировки и дедлоки

Блокировки спасают от гонок, но неаккуратные блокировки сами становятся проблемой: под нагрузкой возникают долгие ожидания и дедлоки, когда два процесса ждут друг друга. Принципы, которые держат систему живой:

Плохо спроектированные блокировки под пиком превращают быстрый сайт в очередь ожидающих запросов. Поэтому область и длительность блокировки важнее, чем сам факт её наличия.

Обработка нехватки на оформлении

Даже с идеальными блокировками бывает, что товара действительно не хватило — он кончился между добавлением в корзину и подтверждением заказа. Здесь важен UX-контракт: честный и мгновенный отказ по позиции лучше, чем оформленный заказ, который потом отменят.

Частые ошибки

Чек-лист

  1. Списание атомарно. Проверка и уменьшение остатка — неделимая операция или блокировка строки.
  2. Резерв отделён от списания. Удержание под заказ и фактическое списание разведены по логике и времени.
  3. Резервы снимаются. Отмена, истечение срока и объединение заказов освобождают товар.
  4. Обмен с 1С частый и надёжный. Остатки и резервы согласуются, окно рассинхрона мало.
  5. Блокировки узкие и короткие. Строка товара, минимальная транзакция, повтор при конфликте.
  6. Кластер и база согласованы. Целостность держится на общей СУБД, а не на «одном процессе».
  7. Нехватка обрабатывается честно. Точечный отказ на оформлении вместо минусов и тихих отмен.

Вывод

Управление остатками под нагрузкой — это про целостность в момент, когда на один товар претендуют многие. Перепродажа рождается не из «плохого сервера», а из гонки между чтением и записью остатка. Лечится она атомарными операциями и короткими блокировками строки товара, разделением резерва и списания и частым, согласованным обменом с 1С как источником истины.

Веб-кластер и highload-блоки помогают масштабировать нагрузку, но не заменяют корректную работу с транзакциями. Спроектируйте списание как неделимую операцию, держите резервы дисциплинированно и обрабатывайте нехватку честно — и распродажа перестанет превращаться в разбор перепроданных заказов.

Частые вопросы

Что такое гонка при списании остатка и чем она опасна?

Гонка (race condition) возникает, когда два и более покупателя одновременно заказывают последнюю единицу товара. Оба видят «в наличии 1», оба проходят оформление, и без защиты система спишет остаток дважды — получится продажа того, чего нет. Опасность прямая: перепроданный товар, отмена заказа, разочарованный клиент и ручная разборка. Под нагрузкой такие ситуации случаются часто, поэтому списание остатка должно быть защищено блокировкой или атомарной операцией на уровне базы.

Чем резерв отличается от списания остатка?

Резерв — это временное удержание товара под конкретный заказ: единица ещё физически на складе, но уже недоступна другим покупателям. Списание — окончательное уменьшение остатка, обычно при отгрузке. Разделение важно: резерв защищает от перепродажи, пока клиент оплачивает и заказ обрабатывается, но не искажает фактические остатки склада. В 1С-Битрикс резервирование настраивается в модуле «Интернет-магазин», а фактические остатки синхронизируются с 1С.

Как 1С-Битрикс защищает остаток от одновременных заказов?

Ключ — не читать и записывать остаток в две отдельные операции, между которыми возможна гонка, а менять его атомарно и под блокировкой. На уровне СУБД это транзакция с блокировкой строки товара или условное обновление, которое уменьшает остаток только если его хватает. Тогда из двух одновременных заказов на последнюю единицу успешно пройдёт только один, а второй корректно получит отказ «нет в наличии», а не фантомную продажу.

Как остатки синхронизируются с 1С и где источник истины?

Физические остатки ведутся в 1С, а на сайт приходят обменом (CommerceML) и обновляют каталог. Источник истины по факту — учётная система, но в момент продажи сайт должен управлять резервами оперативно, не дожидаясь следующего обмена. Правильная схема: сайт резервирует товар под заказ сразу, а обмен с 1С сверяет и подтверждает остатки. Рассинхрон возникает, когда обмен редкий или резервы сайта и 1С не согласованы — это частая причина перепродаж.

Нужен ли веб-кластер для управления остатками под нагрузкой?

Веб-кластер Битрикс помогает держать нагрузку в целом: несколько веб-нод, репликация базы, распределение сессий и кэша. Но сам по себе он не решает проблему гонок за остаток — наоборот, в кластере из нескольких нод корректная блокировка становится ещё важнее, потому что одновременные запросы идут с разных серверов к общей базе. Кластер масштабирует пропускную способность, а целостность остатка обеспечивают транзакции и блокировки на уровне общей СУБД.

Стоит ли хранить остатки в highload-блоках?

Highload-блоки хороши для больших справочников с быстрым доступом, но остаток товара — это часто меняющаяся величина, тесно связанная с торговым каталогом и заказами. Обычно остатки ведутся штатными средствами каталога и заказа, а highload-блоки применяют для смежных больших данных: расширенных характеристик, справочников складов, истории. Выбор хранилища зависит от нагрузки и модели данных, и его стоит проектировать осознанно, а не по инерции.

Как не заблокировать весь сайт из-за блокировок остатка?

Блокировки должны быть узкими и короткими: держите блокировку только на строку конкретного товара и только на время атомарного изменения остатка, а не на всю таблицу и не на всю транзакцию заказа. Длинные и широкие блокировки под нагрузкой приводят к ожиданиям и дедлокам, и сайт «встаёт». Правильная стратегия — минимальная область блокировки, короткие транзакции, повтор операции при конфликте и отказ клиенту вместо бесконечного ожидания.

Что показывать покупателю, если товар кончился в момент оформления?

Честный и мгновенный отказ по конкретной позиции лучше, чем оформленный заказ, который потом отменят. Если в момент подтверждения остатка не хватило, покажите это на позиции: «товар закончился, осталось N», предложите убрать или уменьшить количество. Молчаливое списание в минус или отмена всего заказа после оплаты — худший сценарий. Корректная обработка нехватки в момент оформления сохраняет доверие даже тогда, когда товар действительно кончился.

Поделиться:

Перепродаёте товар на пиках нагрузки?

Защитим списание от гонок, настроим резервирование и обмен остатками с 1С, подготовим каталог к распродажам. Проведём аудит и предложим решение под вашу нагрузку.

Игорь Воскресенский

Команда B2Bsite. С 2014 года разрабатываем интернет-магазины и порталы на 1С-Битрикс: настраиваем резервирование, списание остатков под нагрузкой и обмен с 1С для среднего и крупного бизнеса.

← Все статьи блога