В ходе работы с многочисленными проектами электронной коммерции мы часто сталкиваемся с ситуацией, когда сайт и бэк-офис представляют собой разные информационные системы, требующие постоянного обмена данными. При этом традиционные подходы к синхронизации данных часто оказываются недостаточно эффективными. Вероятно Вы уже сталкивались с таким и у Вас уже есть готовое решение. Но я очень часто встречаю системы, с подобными проблемами и может быть кому-то при написании своего обмена эта статья немного облегчит жизнь.
Будет круто, если в комментариях Вы поделитесь своими кейсами.
Основные проблемы существующих решений:
-
Задержка актуальности данных — в крупных системах с множеством офлайн‑магазинов и онлайн‑площадок информация о наличии товаров может устаревать уже через несколько часов
-
Избыточный трафик — при периодической выгрузке передаются все данные, включая не изменившиеся
-
Потеря данных — при использовании простого флага синхронизации возможны пропуски изменений
-
Низкая производительность — обработка больших объемов данных занимает значительное время
-
Сложность масштабирования — при росте количества товаров и точек продаж проблема только усугубляется
Например, в системах с 1 млн товаров и 60 офлайн-магазинами передача данных об остатках в интернет-магазин может занимать более суток. За это время информация успевает устареть, что приводит к:
-
Продажам отсутствующих товаров
-
Некорректным данным о наличии
-
Снижению доверия клиентов
-
Увеличению возвратов
Основная концепция
Предложенный подход к обмену данными базируется на использовании единой таблицы синхронизации (sync), которая позволяет управлять синхронизацией всех объектов системы. Таблица содержит три ключевых поля:
-
object_type — тип объекта (позволяет использовать одну таблицу для всех сущностей системы)
-
id — идентификатор объекта
-
sync_updated — строка, содержащая маркер последней успешной синхронизации (может быть временной меткой, хешем или версией)
Механизм работы
Процесс синхронизации осуществляется следующим образом:
-
Формирование выгрузки происходит путем объединения основной таблицы с таблицей sync. В выгрузку попадают записи, удовлетворяющие одному из условий:
-
sync_updated = null (объект никогда не синхронизировался)
-
sync_updated ≠ updated (объект был изменен после последней синхронизации)
-
-
Каждый пакет данных содержит информацию о времени изменения объекта, что позволяет точно отслеживать актуальность данных.
-
После успешной обработки на стороне сервера в ответ возвращается информация о:
-
Успешно обработанных объектах (id, updated)
-
Ошибках синхронизации для каждого элемента (id, updated, error_message)
-
-
При получении ответа система обновляет поле sync_updated в таблице синхронизации значениями поля updated, которые пришли в ответе сервера. Это гарантирует, что в случае изменения объекта во время обработки на сервере, запись снова попадет в очередь синхронизации при следующем цикле.
Преимущества подхода
-
Оптимизация трафика - передаются только измененные данные
-
Надежность синхронизации - система не пропускает изменения даже при одновременной обработке
-
Универсальность - не требует модификации существующих таблиц данных (при условии, что там уже есть время изменения в любом формате)
-
Минимализм - достаточно одной таблицы для синхронизации всех объектов системы
-
Гибкость - в качестве маркера версии может использоваться:
-
Временная метка
-
Версия объекта
-
Хеш значимых полей
-
Любое другое подходящее значение
-
Обработка ошибок
При возникновении ошибок синхронизации система получает детальный отчет по каждому объекту, что позволяет:
-
Корректно обработать исключительные ситуации
-
Провести повторный обмен только для проблемных записей
-
Сохранить целостность данных при частичном успехе операции
Заключение
Предложенный механизм синхронизации обеспечивает надежный и эффективный обмен данными между системами, минимизируя нагрузку на сеть и исключая потерю информации. Благодаря использованию единой таблицы синхронизации и версионного контроля, подход остается универсальным и легко интегрируемым в существующие системы, не требуя создания отдельных таблиц для каждой сущности.
Практический пример показывает, что внедрение такого подхода позволяет:
-
Сократить время синхронизации данных
-
Обеспечить актуальность информации в режиме реального времени
-
Снизить нагрузку на сеть
-
Повысить точность данных о наличии товаров
-
Улучшить клиентский опыт
Технические детали реализации
Структура таблицы sync:
CREATE TABLE sync (
id INT PRIMARY KEY,
object_type VARCHAR(255),
sync_updated VARCHAR(255),
UNIQUE (id, object_type)
);
Запрос для формирования выгрузки:
SELECT t.*
FROM main_table t
LEFT JOIN sync s ON t.id = s.id AND s.object_type = 'main_table',
WHERE s.sync_updated IS NULL OR s.sync_updated <> t.updated;
Пример ответа сервера:
{
"success": {
"id": 123,
"updated": "2025-06-17T19:33:50"
},
"errors": {
"id": 456,
"updated": "2025-06-17T19:33:50",
"error_message": "Ошибка обработки данных"
}
}
Пример обработки ответа
// с использованием INSERT... ON DUPLICATE KEY UPDATE
foreach ($response['success'] as $item) {
$sql = "INSERT INTO sync (id, object_type, sync_updated)
VALUES (:id, :object_type, :updated)
ON DUPLICATE KEY UPDATE sync_updated = :updated";
$stmt = $db->prepare($sql);
$stmt->execute([
':id' => $item['id'],
':object_type' => 'main_table', // тип объекта
':updated' => $item['updated']
]);
}
// Обработка ошибок
foreach ($response['errors'] as $error) {
logError($error['error_message']);
scheduleRetry($error['id']);
}
Дополнительно
Надо учесть, что если записи с ошибкой никак не обрабатывать, то они будут бесконечно переотправляться, поэтому стоит продумать механизм обработки ошибки, например в той же таблице sync можно добавить флаг деактивации записи по ошибке и отправке отчета об этом ответственному специалисту.
Автор: antirius
