Справочная информация о применении. Это иллюстративная архитектура и контрольный список объёма работ, а не проверенный проект клиента и не результат измеренного внедрения. Технологии, объём интеграции и состав поставки согласовываются для конкретного технического задания.
Сценарий и ограничения
Розничный бренд продаёт товары через мини-программу WeChat и одновременно управляет физическими магазинами. Ключевое требование заключается в том, чтобы остатки оставались корректными во всех каналах во время акций: независимо обновляемые остатки каналов могут привести к риску перепродажи, если не определить правила резервирования, синхронизации и сверки. Баллы участников программы и купоны также должны обрабатываться согласованно, поскольку повторное применение скидки приводит к прямым финансовым потерям.
Архитектура
Слои и зоны ответственности
| Слой | Технология | Зона ответственности |
|---|---|---|
| Клиент | UniApp (WeChat + Douyin из одной кодовой базы) | Просмотр каталога, корзина, оформление заказа, центр участника. Бизнес-правила здесь не считаются доверенными; клиент только отображает состояние, подтверждённое сервером. |
| API | Go + Gin, без состояния за балансировщиком нагрузки | Проверка запросов, аутентификация, бизнес-правила, границы транзакций. Горизонтальное масштабирование возможно, поскольку состояние сеанса не хранится в процессе. |
| Кэш | Redis | Горячие данные каталога, счётчики остатков для флеш-распродаж, распределённые блокировки, ключи идемпотентности для платёжных обратных вызовов. |
| Хранилище | MySQL с репликой для чтения | Достоверные данные. Записи направляются в первичную базу; чтение каталога и отчётов можно направлять на реплику, когда нагрузка на чтение оправдает это. |
| Администрирование | Vue 3 + Element Plus | Управление каталогом, заказами, запасами, акциями и магазинами с разрешениями, принудительно применяемыми серверной частью. |
| Асинхронная обработка | Воркеры очереди | Сверка платежей, отправка сообщений, агрегация отчётов, освобождение запасов по истечении времени заказа — всё, что не должно блокировать запрос оформления заказа. |
Модель данных
В таблицах ниже зафиксированы правила, от которых зависит всё остальное. Ошибки здесь превращают работающий демонстрационный образец в систему, которую невозможно расширять.
Основные сущности
| Сущность | Ключевые поля, связи и правила |
|---|---|
| product / sku | Один товар связан со многими SKU по комбинации атрибутов. Цена и остаток относятся к SKU, а не к товару, иначе расширение ценообразования для нескольких вариантов станет невозможным. |
| inventory | Строки с ключом (sku_id, location_id), содержащие on_hand и reserved. Доступный остаток вычисляется как on_hand минус reserved; транзакции и сверку всё равно необходимо тестировать для выявления расхождений. |
| inventory_txn | Журнал, доступный только для добавления, каждой операции движения запасов с кодом причины и исходным заказом. Текущий остаток всегда должен быть воспроизводим повторным проигрыванием этого журнала — благодаря этому расхождения поддаются аудиту, а не становятся предметом споров. |
| order / order_item | Заказ содержит конечный автомат состояний и итоги; позиции сохраняют название SKU, спецификацию и цену за единицу на момент покупки, поэтому последующие изменения каталога не могут переписать историю заказа. |
| payment_txn | Идентификатор транзакции шлюза, сумма, статус и необработанные данные обратного вызова. Уникальность по идентификатору шлюза не позволяет применить повторный обратный вызов WeChat Pay дважды. |
| member / point_txn / coupon | Баланс и баллы участника вычисляются из журнала транзакций, доступного только для добавления. Строки купонов содержат область действия, порог, приоритет совмещения и отметку used_at, используемую для обеспечения однократного применения. |
Ключевые интерфейсы
Конечные точки, содержащие бизнес-правила
| Конечная точка | Назначение и замечания по конкурентному доступу |
|---|---|
| POST /api/v1/orders | Создаёт заказ и резервирует запас в рамках одной транзакции базы данных. При нагрузке флеш-распродажи резервирование сначала выполняется посредством атомарного уменьшения значения в Redis, а MySQL используется как система фиксации расчётов; клиент передаёт ключ идемпотентности, поэтому повторное нажатие не создаёт два заказа. |
| POST /api/v1/payments/callback | Обратный вызов платёжного шлюза. Идемпотентен по идентификатору транзакции шлюза, проверяет подпись и переводит заказ в следующее состояние. Успех возвращается только после фиксации изменения состояния, иначе шлюз продолжает повторять запрос. |
| POST /api/v1/orders/{id}/cancel | Освобождает зарезервированный запас и откатывает использование купона и списание баллов в той же транзакции, которая закрывает заказ. |
| GET /api/v1/skus/{id}/availability | Читает доступный остаток через кэш с коротким TTL. Отображаемая доступность намеренно может отставать; только транзакция заказа является источником истины. |
| POST /api/v1/admin/inventory/adjust | Записывает inventory_txn с кодом причины и идентификатором оператора, а не изменяет число запасов напрямую. Каждая ручная корректировка остаётся отслеживаемой. |
Технические решения
- UniApp вместо отдельных нативных мини-программ. WeChat и Douyin используют большую часть общего коммерческого процесса, поэтому одна кодовая база устраняет дублирование сопровождения. Платформенные платежи и вход в систему изолируются за слоем адаптеров, а не распределяются по страницам.
- Резервирование запаса при размещении заказа, а не при оплате. Резервирование во время оплаты означает, что клиент может заплатить за уже проданный товар. Компромисс заключается в том, что неоплаченные заказы удерживают запас, поэтому срок действия резервов истекает по таймеру, после чего воркер освобождает их.
- Доступность вычисляется, а не хранится. Кэшированное значение available_qty создаёт ещё один путь синхронизации. Вычисляемая доступность может уменьшить это дублирование; для фактической нагрузки следует сравнить производительность чтения и поведение сверки.
- Журналы, доступные только для добавления, для запасов, баллов и баланса. Любой показатель, который клиенты могут оспорить, должен быть восстанавливаемым из журнала, иначе службе поддержки нечем объяснить расхождение.
- Go для слоя API. Нагрузка состоит из множества коротких параллельных запросов к базе данных, чему соответствует модель конкурентности Go, а один статический бинарный файл упрощает развёртывание и откат.
Гипотетические целевые показатели проектирования
Приведённые ниже значения являются гипотетическими примерами для планирования ёмкости, а не измеренными результатами клиента, подтверждённой рекомендацией по расчёту ресурсов или SLA. Установите проектные целевые показатели приёмки после определения нагрузки, устройств, данных, оборудования и зависимостей от сторонних систем; проверьте их посредством пилотного проекта и нагрузочных тестов до принятия производственной цели.
Целевые показатели ёмкости и производительности
| Показатель | Значение и допущение |
|---|---|
| Задержка чтения каталога | p95 менее 150 ms на API при условии, что горячие данные находятся в Redis, а база данных — в той же частной сети. |
| Создание заказа | p95 менее 400 ms, включая резервирование запаса, для одной первичной базы данных с индексами таблиц заказов по (site_id, status, created_at). |
| Всплеск при флеш-распродаже | Путь заказа рассчитан на несколько тысяч запросов в минуту для каждого SKU посредством атомарного уменьшения значения в Redis до фиксации расчётов в MySQL. При превышении этого уровня добавляется очередь для допуска — порог подтверждается нагрузочным тестированием на вашем фактическом объёме данных. |
| Обратный вызов платежа | Обрабатывается идемпотентно в пределах окна повторных попыток шлюза; дублирующиеся обратные вызовы отклоняются по уникальному идентификатору транзакции шлюза. |
Что входит в поставку
- Исходный код мини-программы, серверной части на Go и административной части на Vue в вашем репозитории
- Схема базы данных с миграциями, обоснованием индексов и документированными таблицами журналов
- Документация API с описанием аутентификации, кодов ошибок и требований к идемпотентности
- Инструкции по развёртыванию для Linux, Docker и Nginx, а также процедура резервного копирования и восстановления
- Поддержка интеграции платёжной системы и аккаунта сообщений; результат проверки платформой остаётся на стороне WeChat или Douyin
Планирование для вашего бизнеса
Описанные выше модули — отправная точка, а не фиксированный пакет. Обычно первый выпуск ограничивается одним основным процессом и одним административным процессом, после чего расширяется, когда реальное использование показывает, где фактически находятся нагрузка и нестандартные случаи. Отправьте описание объёма работ, и мы сопоставим его с этой архитектурой и сообщим, какие части пока не нужны.

