Покупатель добавляет товар в корзину, доходит до оформления — и получает «извините, товара нет в наличии». Или видит на карточке одну цену, а в заказе другую. Почти всегда за этим стоит одно: цены и остатки в каталоге обновляются редко и рывками, потому что каждое обновление кладёт витрину на лопатки. В результате бизнес выбирает из двух зол — либо актуальные данные ценой тормозов, либо быстрый сайт ценой устаревших остатков.
На самом деле это ложная дилемма. Частые обновления цен и остатков по API можно организовать так, что каталог их даже не замечает: приём данных развязан с записью через очередь, запись идёт пакетами и без длинных блокировок, а кэш инвалидируется точечно. Ниже — практическая схема такого обновления в 1С-Битрикс: от архитектуры и модели данных до конкретных модулей, идемпотентности и мониторинга. Это выжимка из наших проектов по интеграции интернет-магазинов на 1С-Битрикс с учётными системами, складами и маркетплейсами.
Коротко
- Не пишите каждое изменение в базу синхронно — принимайте его в очередь, а в каталог записывайте отдельным воркером.
- Обновляйте пакетами в короткой транзакции: сотни строк за один проход вместо сотни отдельных запросов.
- Снабжайте сообщения версией/меткой времени — воркер применяет только свежие данные и идемпотентен к повторам.
- Инвалидируйте кэш точечно по тегам затронутых товаров, а не сбрасывайте весь каталог на каждое изменение остатка.
- Меряйте лаг очереди, скорость записи и число дедлоков — без метрик «часто обновлять» превращается в «часто ронять».
Зачем обновлять цены и остатки часто
Актуальность цен и остатков — это не про перфекционизм, а про деньги и репутацию. Расхождение между витриной и реальным складом бьёт сразу по нескольким направлениям, и чем крупнее ассортимент и оборот, тем дороже обходится каждый час задержки.
- Отменённые заказы. Покупатель оформил товар, которого физически нет, — менеджер звонит с извинениями, заказ разваливается, клиент уходит к конкуренту. На больших оборотах доля таких отмен напрямую съедает выручку.
- Ошибки в цене. Устаревшая цена — это либо продажа в убыток, либо потеря конверсии из-за завышенной суммы. Особенно болезненно на товарах с частой переоценкой: техника, сырьё, валютозависимые позиции.
- Проблемы с маркетплейсами и фидами. Если сайт — источник данных для Яндекс Маркета, фидов и партнёров, задержка обновления остатков ведёт к штрафам площадок и «фантомным» предложениям.
- Недоверие к витрине. Пользователи быстро запоминают, что «на этом сайте остаткам верить нельзя», и начинают звонить перед заказом — растёт нагрузка на колл-центр, падает доля самостоятельных покупок.
При этом «часто» для разных данных означает разное. Цена может обновляться раз в час или после каждой переоценки в учётной системе. Остаток популярного товара в высокий сезон стоит обновлять близко к реальному времени — каждые несколько минут или по событию продажи. Задача интеграции — дать возможность обновлять так часто, как требует бизнес, не упираясь в то, что каждое обновление стоит каталогу дорого.
Что именно мы обновляем и где это лежит
Прежде чем строить обмен, нужно чётко понимать, какие сущности мы трогаем и в каких таблицах Битрикса они живут. «Цена» и «остаток» на витрине — это на самом деле несколько связанных объектов, и путаница между ними — источник половины ошибок интеграции.
| Что обновляем | Где хранится в 1С-Битрикс | Нюансы |
|---|---|---|
| Цена товара | Модуль «Торговый каталог», таблица цен (тип цены + товар + валюта) | Цен может быть несколько типов: розница, опт, для B2B-клиентов. Обновлять нужно нужный тип. |
| Складской остаток | Модуль «Торговый каталог», количество товара; при многоскладности — остатки по складам | Есть общий доступный остаток и остатки в разрезе складов, их нельзя смешивать. |
| Доступность / наличие | Расчётное поле на основе остатка и настроек «показывать при нуле» | Флаг «в наличии» часто пересчитывается автоматически и его не нужно писать напрямую. |
| Цены торговых предложений (SKU) | Те же таблицы цен, но для элементов инфоблока предложений | У модели-родителя своей цены обычно нет — она на конкретных SKU. |
| Резервы | Модуль «Интернет-магазин» (sale), резервирование под заказы | Доступный остаток = физический минус резерв; важно, чтобы источник и сайт считали одинаково. |
Ключевой вывод из этой таблицы: обновление остатка — это не «записать число в поле товара». Это согласование физического остатка, резервов и правил отображения. Поэтому в интеграции всегда договариваются заранее: что считается «доступным остатком», кто владеет резервами (сайт или учётная система) и по какому типу цены идёт обновление. Если этого не сделать, витрина и склад будут показывать разные цифры даже при технически исправном обмене.
Архитектура: источник, очередь, приёмник
Хорошая интеграция обновления цен и остатков состоит из трёх слабо связанных частей. Их независимость и есть то, что позволяет обновляться часто, не роняя витрину.
- Источник данных. Учётная система (чаще всего 1С), складская программа, ERP, панель маркетплейса. Именно он знает «правду» о ценах и остатках и порождает события изменения.
- Транспорт и очередь. Прослойка, которая принимает изменения и складывает их в буфер. Это может быть таблица-очередь в базе, брокер сообщений или REST-эндпоинт, который только кладёт сообщение и сразу отвечает «принято».
- Приёмник (воркер). Фоновый процесс на стороне Битрикса, который забирает сообщения из очереди пачками и пишет их в каталог серверным API, отвечая за пакетность, порядок и идемпотентность.
Смысл разделения в том, что источник не ждёт, пока данные лягут в каталог. Он «выстреливает» изменением и освобождается, а тяжёлую работу по записи делает воркер в удобном ему темпе. Если поток данных вырос — очередь просто временно удлиняется, а не создаёт пиковую нагрузку на витрину. Если воркер упал — сообщения ждут в очереди и обработаются после перезапуска, ничего не теряется.
Отдельно стоит сказать про надёжность самого транспорта. Интеграция цен и остатков — это поток, в котором нельзя терять и нельзя дублировать данные без последствий. Как строить надёжную доставку через очереди, подтверждения и повторы, мы подробно разбирали в материале про API, очереди и надёжность интеграций в Битрикс — здесь же сфокусируемся именно на специфике цен и складских остатков.
Почему прямая синхронная запись убивает каталог
Соблазн велик: раз есть API, почему бы просто не дёргать его на каждое изменение остатка прямо из учётной системы? На маленьком каталоге это даже работает. Проблемы начинаются, когда обновлений становится много, и они почти всегда одинаковые.
Инициализация ядра на каждый вызов. Любой REST-запрос или хит скрипта поднимает значительную часть ядра Битрикса: модули, конфигурацию, соединение с базой. Для одного обновления это доли секунды, но при тысячах вызовов в минуту накладные расходы начинают доминировать над самой полезной работой.
Конкурентные блокировки. Когда несколько параллельных запросов пишут в одни и те же таблицы цен и остатков, СУБД вынуждена сериализовать доступ через блокировки строк. Запросы встают в очередь ожидания, растёт время отклика, а в худшем случае возникают взаимные блокировки (дедлоки), которые база разрывает откатом транзакций.
Лавина сброса кэша. Каждое изменение товара инвалидирует связанный кэш: карточку, списки разделов, счётчики фильтра. Если писать поштучно и часто, кэш не успевает «нагреться» — витрина постоянно пересобирает страницы, и живые посетители чувствуют это как тормоза именно в моменты активного обмена.
Вывод простой: прямая синхронная запись плохо масштабируется по частоте. Она приемлема для редких единичных правок, но как только речь заходит о «часто» — её нужно менять на буферизацию через очередь и пакетную запись. Именно это разрывает вредную связку «больше обновлений → медленнее каталог».
Очереди и воркеры: развязываем приём и запись
Очередь — это буфер между быстрым приёмом и более медленной, но эффективной записью. Приёмная сторона делает минимум: валидирует сообщение, кладёт его в очередь и мгновенно отвечает источнику. Вся тяжёлая работа переносится в фоновый воркер.
Что именно даёт такая развязка:
- Сглаживание пиков. Если источник вдруг прислал десять тысяч изменений разом (переоценка, инвентаризация), очередь примет их без просадки витрины, а воркер разберёт в своём темпе.
- Пакетирование. Воркер забирает не по одному сообщению, а пачками по несколько сотен, и пишет их в базу за одну транзакцию — это кратно дешевле поштучной записи.
- Устойчивость к сбоям. Упал воркер или база на техобслуживании — сообщения ждут в очереди. После восстановления обработка продолжается с того же места, ничего не теряется.
- Управляемая нагрузка. Можно ограничить число воркеров и размер пачки так, чтобы обмен никогда не «съедал» больше выделенной доли ресурсов сервера.
Очередь может быть реализована по-разному. Самый простой вариант — таблица в той же базе, куда приёмник вставляет строки, а воркер их вычитывает и помечает обработанными. Более зрелый — внешний брокер сообщений, который берёт на себя доставку, подтверждения и повторы. Для большинства магазинов на старте достаточно таблицы-очереди с запуском воркера по агенту или cron; к брокеру переходят, когда поток данных и требования к отказоустойчивости вырастают.
Пакетная запись вместо поштучной
Пакетирование — главный рычаг производительности при частых обновлениях. Разница между «сто отдельных запросов» и «один запрос на сто строк» — не косметическая, а в разы, потому что фиксированные накладные расходы (открытие транзакции, планирование запроса, сброс кэша, вызовы событий) платятся один раз на всю пачку, а не на каждую позицию.
Практические принципы пакетной записи:
- Собирайте пачку разумного размера. Ориентир — от 200 до 1000 позиций за проход. Слишком маленькая пачка не даёт выигрыша, слишком большая — держит блокировки дольше и рискует упереться в лимиты транзакции.
- Дедуплицируйте внутри пачки. Если в одной пачке пришло три изменения остатка по одному SKU, применяйте только последнее по версии. Это экономит записи и предотвращает лишние срабатывания событий.
- Разделяйте цены и остатки. Обновление цен и остатков затрагивает разные таблицы. Иногда выгоднее вести две пачки-потока, чтобы блокировки по ценам не пересекались с блокировками по количеству.
- Пишите в короткой транзакции. Внутри транзакции — только запись данных. Тяжёлые побочные действия (пересчёт, уведомления) выносите за её пределы, чтобы не удерживать блокировки дольше необходимого.
- Управляйте событиями осознанно. Массовые обработчики событий на изменение товара при пакетной записи могут кратно замедлять обмен. Часть из них имеет смысл отключать на время пакета и запускать отложенно.
Идемпотентность и порядок сообщений
Как только между источником и каталогом появляется очередь, приходит и её оборотная сторона: сообщения могут доставляться повторно и приходить не в том порядке, в котором были отправлены. Для остатков это критично — легко «откатить» свежее значение старым и показать покупателю несуществующий товар.
Защита строится на двух механизмах.
Идемпотентность. Обработка одного и того же сообщения дважды должна давать тот же результат, что и однократная. Достигается это тем, что воркер записывает не «прибавить/убавить», а «установить значение как в сообщении», и помечает уже применённые сообщения по уникальному идентификатору. Повторная доставка тогда либо игнорируется, либо перезаписывает данные тем же значением — без вреда.
Контроль порядка через версию. Каждое изменение снабжается монотонной версией или меткой времени источника. Воркер, прежде чем записать остаток, сравнивает версию сообщения с версией, уже сохранённой для этого товара, и применяет данные только если они свежее. Так даже переставленные местами сообщения не приведут к откату: устаревшее просто отбрасывается.
| Проблема очереди | Что произойдёт без защиты | Решение |
|---|---|---|
| Повторная доставка | Двойное применение изменения | Идемпотентность по ID сообщения |
| Перестановка порядка | Свежий остаток затирается старым | Версия/метка времени, применяем только более новое |
| Частичный сбой пачки | Часть данных записана, часть нет | Транзакция: либо вся пачка, либо ничего |
| Сообщение на неизвестный товар | Ошибка или бесконечные повторы | Dead-letter очередь для ручного разбора |
Отдельно про сопоставление товаров. Внешняя система знает товар по своему ключу — артикулу или коду номенклатуры. В Битриксе стабильным «мостом» служит внешний код элемента (XML_ID) или артикул. Никогда не сопоставляйте по названию или по внутреннему ID Битрикса, который источнику неизвестен: первое ломается при малейшем изменении названия, второе создаёт хрупкую зависимость. Один стабильный внешний ключ — основа надёжного обновления.
Блокировки, дедлоки и как их избежать
Даже с очередью и пакетами при высокой частоте обновлений можно столкнуться с блокировками базы. Понимание их природы помогает писать обмен так, чтобы дедлоки не возникали в принципе.
Взаимная блокировка (дедлок) возникает, когда две транзакции ждут ресурсы, захваченные друг другом: транзакция A держит строку товара 1 и хочет товар 2, а транзакция B держит товар 2 и хочет товар 1. База обнаруживает тупик и откатывает одну из транзакций с ошибкой. При частом параллельном обмене это не редкость, если не соблюдать дисциплину доступа.
Как снизить вероятность блокировок и дедлоков:
- Один писатель на поток данных. Проще всего избежать конкуренции, если остатки пишет ровно один воркер. Параллелить стоит по непересекающимся диапазонам товаров, а не «в лоб» несколькими процессами по одним и тем же строкам.
- Стабильный порядок записи. Внутри пачки сортируйте позиции по ключу (например, по ID товара) перед записью. Тогда все транзакции захватывают строки в одном и том же порядке, и классический дедлок «A ждёт B, B ждёт A» становится невозможным.
- Короткие транзакции. Чем меньше времени удерживается блокировка, тем ниже шанс, что в неё кто-то упрётся. Никаких сетевых вызовов и тяжёлых пересчётов внутри транзакции.
- Ретраи на дедлок. Дедлок — штатная, ожидаемая ситуация, а не фатальная ошибка. Воркер должен ловить её и повторять пачку (с небольшой случайной задержкой), а не падать.
- Разведение по времени с обменом 1С. Если параллельно идёт полный обмен с 1С, тяжёлые операции лучше не накладывать друг на друга. Как выстроить такой обмен без конфликтов, разбираем в статье про интеграцию магазина с 1С.
Реализация в 1С-Битрикс
Перейдём от принципов к конкретике платформы. За цены и остатки в 1С-Битрикс отвечают модули «Торговый каталог» (catalog) и «Интернет-магазин» (sale). Работать с ними можно на трёх уровнях, и для частого обновления важно выбрать правильный.
- Серверный API D7. Классы модуля каталога для работы с ценами и складскими данными, а также ORM-сущности. Это самый быстрый путь записи внутри процесса-воркера: без HTTP-обёртки, с прямым доступом к бизнес-логике модулей.
- REST-модуль. Методы каталога, доступные по HTTP с авторизацией и вебхуками. Удобен, когда источник внешний и не имеет доступа к серверу. Но каждый вызов — полный хит, поэтому для потока его используют как приёмник в очередь, а не как способ поштучной записи.
- Штатный обмен CommerceML с 1С. Файловый протокол выгрузки каталога и остатков. Хорош для планового полного/частичного обмена, но не рассчитан на «реальное время» — для частых точечных обновлений его дополняют API-каналом.
Рабочая связка для частого обновления выглядит так: внешний источник шлёт изменения на REST-эндпоинт или напрямую в таблицу-очередь; агент или демон-воркер на стороне Битрикса читает очередь пачками и пишет данные серверным API D7 в короткой транзакции; после пачки воркер точечно сбрасывает тегированный кэш затронутых товаров. Полный обмен с 1С при этом остаётся для номенклатуры, свойств и картинок, а «горячие» цены и остатки идут быстрым API-каналом.
- Определите ключ сопоставления. Зафиксируйте, что XML_ID или артикул — единый мост между источником и Битриксом, и что он не меняется при обновлениях.
- Поднимите приём в очередь. REST-эндпоинт или обработчик, который валидирует сообщение, кладёт его в таблицу-очередь с версией и сразу отвечает «принято».
- Напишите воркер. Агент/демон, забирающий пачку сообщений, дедуплицирующий их по SKU, применяющий только свежие версии и пишущий цены/остатки серверным API в одной транзакции.
- Настройте цены по типам. Убедитесь, что обновление идёт в нужный тип цены (розница, опт, B2B) и в правильной валюте; не перезаписывайте чужие типы цен.
- Согласуйте склады и резервы. Договоритесь, кто владелец резервов, и пишите доступный остаток единообразно с учётом многоскладности.
- Добавьте точечную инвалидацию кэша. После пачки сбрасывайте тегированный кэш только затронутых элементов и разделов, а не весь каталог.
- Включите dead-letter и логи. Сообщения на неизвестные товары и ошибки записи отправляйте в отдельную очередь с сохранением тела и причины.
Как это выглядит в админке и логах
Со стороны администратора частый API-обмен не должен выглядеть как «чёрный ящик». Полезно иметь в админке простую панель состояния очереди и журнал обработки, чтобы контент-менеджер и техподдержка видели, что данные идут. Схематично это выглядит так:
Такая панель снимает большинство вопросов «а обновляются ли остатки». Видно текущую длину очереди (сколько ещё не применено), лаг (насколько витрина отстаёт от источника прямо сейчас), скорость записи и наличие проблем. Если лаг растёт, а скорость упала — сигнал разбираться: воркер завис, база под нагрузкой или источник прислал аномальный объём.
Кэш и переиндексация после обновлений
Частое обновление данных и кэширование каталога кажутся противоречащими друг другу: одно требует свежести, другое — стабильности. На практике они прекрасно уживаются, если инвалидировать кэш точечно, а не тотально.
В 1С-Битрикс каталог опирается на тегированный (управляемый) кэш: выборки и страницы помечаются тегами инфоблока и конкретных элементов. Когда меняется товар, сбрасываются только записи кэша с его тегами, а не весь кэш каталога. Это и есть ключ к совместимости частых обновлений и скорости: обновили остаток одного SKU — «протухли» только его карточка и разделы, где он выводится, всё остальное осталось тёплым.
Что важно учитывать по кэшу и индексам при частом обмене:
- Не сбрасывайте кэш каталога целиком на каждое изменение. Полная очистка на каждый остаток превращает частый обмен в постоянную пересборку витрины — ровно то, чего мы избегаем.
- Инвалидируйте после пачки, а не после каждой позиции. Собрали затронутые ID за пачку — сбросили их теги одним заходом.
- Фасетный индекс не требует полного перестроения при смене цены/остатка. Обновляются связанные записи; полное перестроение нужно лишь при изменении набора умно-фильтруемых свойств. Подробнее про фасет — в статье про умный фильтр в этой же рубрике.
- Композитный кэш дружит с частым обменом. Статическая часть страницы отдаётся мгновенно, а «горячие» цена и остаток догружаются динамикой — пользователь всегда видит актуальное число без пересборки всей страницы.
REST, серверный API и файловый обмен — сравнение
Три основных канала обновления решают разные задачи. Выбор зависит от того, где живёт источник, какой нужен темп и кто отвечает за инфраструктуру. Сведём их в таблицу.
| Критерий | REST API | Серверный API (D7) | Файловый обмен (CommerceML) |
|---|---|---|---|
| Где источник | Внешний, по HTTP | На том же сервере / воркер | 1С по расписанию |
| Темп обновления | Близко к реальному времени | Максимальный для записи | Плановый, партиями |
| Накладные расходы | Высокие на вызов (полный хит) | Минимальные внутри процесса | Средние, но редко |
| Пригодность для потока | Как приём в очередь | Идеально для пакетной записи | Не для точечного реального времени |
| Авторизация «из коробки» | Да, вебхуки/OAuth | Не требуется (внутри) | Базовая, по протоколу |
| Типичная роль | Граница системы, приёмник | Двигатель записи в каталог | Полная синхронизация номенклатуры |
На практике эти каналы не конкурируют, а дополняют друг друга. Крупный магазин обычно комбинирует: CommerceML тянет из 1С номенклатуру, свойства и картинки по расписанию; REST принимает «горячие» изменения цен и остатков от учётной системы или складского сервиса в очередь; серверный API внутри воркера быстро пишет эти изменения в каталог пачками. Такой гибрид даёт и полноту данных, и близкую к реальному времени актуальность цен и остатков.
Если же вы обновляете каталог ещё и из плоских выгрузок — прайсов в Excel и CSV, — стоит выстроить единые правила сопоставления по артикулу, чтобы файловый импорт и API-обмен не конфликтовали. Об этом подробно — в материале про импорт каталога из Excel и CSV в 1С-Битрикс.
Дельта-обновления и вебхуки
Ещё один способ снизить нагрузку — передавать не всё подряд, а только изменения. Полная выгрузка «все цены и все остатки» проста, но расточительна: если из ста тысяч позиций поменялись десять, гонять сто тысяч бессмысленно. Дельта-обновление шлёт лишь то, что реально изменилось.
Дельту можно организовать двумя путями:
- Вебхуки по событию. Источник сам присылает изменение в момент, когда оно произошло: продали товар — прилетело новое количество, переоценили — прилетела новая цена. Самый «реальный» из режимов, но требует, чтобы источник умел отдавать события.
- Периодический опрос изменений. Воркер регулярно спрашивает источник «что поменялось с момента X» и получает только дельту. Проще в реализации, если источник не умеет пушить, но добавляет задержку в размер интервала опроса.
У дельты есть важная оговорка: механизм рано или поздно рассинхронизируется — потерянное событие, сбой сети, перезапуск. Поэтому дельту всегда подстраховывают периодической полной сверкой: раз в сутки (или чаще для критичных категорий) сравнивают полный срез остатков источника и сайта, находят расхождения и выравнивают. Дельта даёт скорость в моменте, полная сверка — гарантию, что накопленный дрейф не превратится в системную ошибку.
Мониторинг, метрики и алерты
Частый обмен нельзя оставлять без наблюдения: он работает «в тени», и о поломке легко узнать последним — от покупателя, которому продали отсутствующий товар. Поэтому мониторинг здесь не роскошь, а часть системы. Ключевые метрики, за которыми стоит следить:
| Метрика | Что показывает | Тревожный сигнал |
|---|---|---|
| Длина очереди | Сколько изменений ещё не применено | Растёт и не убывает — воркер не справляется |
| Лаг обработки | На сколько витрина отстаёт от источника | Превышает бизнес-порог (например, 5 минут) |
| Скорость записи | Позиций в секунду | Резко упала при той же нагрузке |
| Число дедлоков/ошибок | Стабильность записи | Всплеск откатов транзакций |
| Размер dead-letter | Сколько сообщений не удалось применить | Постоянный рост — проблема сопоставления |
| Расхождение при сверке | Дрейф между источником и сайтом | Растёт от сверки к сверке |
На основе этих метрик настраивают алерты: уведомление в мессенджер или на почту, когда лаг или очередь превышают порог, когда воркер не подавал признаков жизни N минут или когда dead-letter внезапно распух. Дешёвый, но эффективный приём — «сигнал живости»: воркер после каждой пачки обновляет метку времени последней успешной обработки, а отдельная проверка бьёт тревогу, если метка устарела. Это ловит зависший обмен раньше, чем его заметят покупатели.
Частые ошибки
- Пишут каждое изменение синхронно и поштучно прямо из источника — каталог тормозит ровно в часы активного обмена.
- Нет версии или метки времени у сообщений — переставленные в очереди данные откатывают свежий остаток на старый.
- Сопоставляют товары по названию или внутреннему ID Битрикса вместо стабильного артикула/XML_ID — обмен ломается при любом изменении.
- Сбрасывают весь кэш каталога на каждое обновление остатка — частый обмен превращается в постоянную пересборку витрины.
- Отключили обработчики событий ради скорости пачки и забыли явно обновить кэш и индексы — база свежая, а витрина показывает старьё.
- Не сделали пачки идемпотентными — повторная доставка сообщения применяет изменение дважды.
- Пишут остатки несколькими параллельными процессами по одним строкам — регулярные дедлоки и откаты.
- Полагаются только на дельту без периодической полной сверки — накопленный рассинхрон однажды «выстреливает» массой неверных остатков.
- Путают физический остаток, резерв и доступный остаток — сайт и склад показывают разные цифры при исправном обмене.
- Обновляют не тот тип цены (перезаписывают опт розницей) — покупатели видят неверные цены для своей группы.
Чек-лист внедрения
Сведём всё в практический список, по которому удобно принимать готовность обмена цен и остатков перед запуском:
- Определён ключ сопоставления. Товары матчатся по стабильному артикулу или XML_ID, а не по названию или внутреннему ID.
- Приём развязан с записью. Источник кладёт изменения в очередь и не ждёт их применения в каталоге.
- Запись пакетная. Воркер пишет пачками в короткой транзакции, дедуплицируя изменения по SKU.
- Обеспечена идемпотентность. Повторная доставка не применяет изменение дважды, есть контроль версий/меток времени.
- Порядок записи стабилен. Позиции в пачке сортируются по ключу, есть ретраи на дедлок.
- Кэш инвалидируется точечно. После пачки сбрасываются теги затронутых товаров, а не весь каталог.
- Согласованы цены и склады. Обновляется нужный тип цены и валюта, доступный остаток считается единообразно с резервами.
- Есть два контура. Быстрый (дельта/вебхуки) держит актуальность, медленный (полная сверка) чинит рассинхрон.
- Настроен мониторинг. Отслеживаются длина очереди, лаг, скорость записи, дедлоки и dead-letter; есть алерты и «сигнал живости».
- Есть dead-letter. Сообщения на неизвестные товары и ошибки записи сохраняются для разбора, а не теряются и не крутятся вечно.
Вывод
Частое обновление цен и остатков по API — это не вопрос «сколько запросов выдержит сайт», а вопрос архитектуры. Разорвите связку «больше обновлений → медленнее каталог»: принимайте изменения в очередь, пишите их пакетами без длинных блокировок, делайте обработку идемпотентной и инвалидируйте кэш точечно. Тогда витрина покажет актуальные цены и наличие в реальном времени и при этом останется быстрой даже в разгар обмена. Добавьте два контура (дельта плюс полная сверка) и мониторинг с алертами — и обновление данных перестанет быть источником отменённых заказов и станет незаметной, надёжной частью каталога.