← Назад к вопросам
Кому нужен был планировщик в проекте IKEA
1.3 Junior🔥 51 комментариев
#Soft Skills и карьера
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Планировщик в проекте IKEA
В проекте IKEA планировщик был необходим для автоматизации процессов управления поставками и синхронизацией данных между несколькими системами, работающими 24/7 в разных часовых поясах.
Контекст проекта
IKEA — многомилионная торговая сеть с сотнями складов и магазинов. Для каждого из них критично:
- Синхронизация каталога товаров между центральной системой и локальными кешами
- Управление уровнями товара на складах в реальном времени
- Расчёт оптимальных сроков доставки покупателей
- Генерация отчётов по продажам для разных подразделений
- Очистка устаревших данных из кешей
Проблема без планировщика
// ❌ Без планировщика: ручное управление
public class ProductCatalogService {
public void updateCatalog() {
// Нужно вызывать вручную
// Когда? Как часто? Что если система упадёт?
List<Product> products = fetchProductsFromMainSystem();
synchronizeWithLocalCache(products);
notifyWarehouses(products);
}
}
// Кто-то из разработчиков должен помнить вызвать это в нужное время
// Ненадёжно, подвержено ошибкам
Решение: Планировщик (Scheduler)
// ✅ С планировщиком: автоматизированное выполнение
import org.springframework.scheduling.annotation.Scheduled;
import java.util.concurrent.ScheduledExecutorService;
public class ProductSyncScheduler {
private final ProductService productService;
private final NotificationService notificationService;
@Scheduled(cron = "0 0 */4 * * *") // Каждые 4 часа
public void syncProductCatalog() {
try {
log.info("[IKEA] Starting catalog synchronization");
// Синхронизируем данные
List<Product> products = productService.fetchFromMainSystem();
productService.updateLocalCache(products);
// Уведомляем все склады
notificationService.notifyAllWarehouses(products);
log.info("[IKEA] Catalog synced successfully");
} catch (Exception e) {
log.error("[IKEA] Catalog sync failed", e);
alertOncall(); // Уведомляем oncall инженера
}
}
@Scheduled(cron = "0 30 2 * * *") // Каждый день в 02:30
public void generateDailyReports() {
// Генерируем отчёты по продажам
List<SalesReport> reports = productService.generateReports();
reportService.distributeToManagers(reports);
}
@Scheduled(cron = "0 0 3 * * 0") // Каждое воскресенье в 03:00
public void cleanupExpiredCache() {
// Удаляем устаревшие данные
cacheService.removeExpiredEntries();
}
}
Задачи планировщика в проекте
1. Синхронизация товаров (Каждые 4 часа)
- Загружаем обновлённый каталог из главной системы
- Обновляем данные в локальных кешах магазинов
- Нормализуем цены по валютам разных регионов
- Применяем локальные скидки и промоции
@Scheduled(cron = "0 0 */4 * * *")
public void syncWarehouseInventory() {
// Для каждого склада в каждой стране
for (Warehouse warehouse : warehouseService.getAllWarehouses()) {
try {
InventoryData inventory = mainSystem.getInventory(warehouse.getId());
warehouseCache.update(warehouse.getId(), inventory);
metricsService.recordSuccess(warehouse.getId());
} catch (Exception e) {
metricsService.recordFailure(warehouse.getId());
alertTeam(warehouse, e);
}
}
}
2. Расчёт сроков доставки (Каждый час)
- Берём данные о текущем трафике
- Берём информацию о наличии товара на складах
- Рассчитываем оптимальный срок доставки для каждого региона
- Сохраняем результаты для использования в checkout
@Scheduled(fixedDelay = 3600000) // Каждый час
public void updateDeliveryEstimates() {
Map<String, DeliveryEstimate> estimates = new HashMap<>();
for (Region region : regionService.getAllRegions()) {
int baseDeliveryDays = calculateBaseDelivery(region);
int trafficDelay = getTrafficDelay(region);
int totalDays = baseDeliveryDays + trafficDelay;
estimates.put(region.getCode(),
new DeliveryEstimate(totalDays, LocalDateTime.now()));
}
deliveryCache.updateAll(estimates);
}
3. Генерация отчётов (Каждый день в 02:30)
- Агрегируем данные о продажах за день
- Рассчитываем KPI для каждого магазина и региона
- Отправляем отчёты менеджерам по email
- Обновляем дашборды в BI системе
@Scheduled(cron = "0 30 2 * * *")
public void generateDailyReports() {
LocalDate yesterday = LocalDate.now().minusDays(1);
for (Region region : regionService.getAllRegions()) {
SalesReport report = analyticsService.generateReport(region, yesterday);
emailService.sendToManagers(
region.getManagerEmails(),
"Daily Sales Report - " + yesterday,
report.formatAsHtml()
);
biService.pushToDataWarehouse(report);
}
}
4. Очистка кешей (Еженедельно в 03:00)
- Удаляем устаревшие данные товаров
- Очищаем истёкшие сессии пользователей
- Архивируем старые логи
- Перестраиваем индексы БД
@Scheduled(cron = "0 0 3 * * 0")
public void maintenanceCleanup() {
log.info("Starting maintenance cleanup");
// Очищаем устаревшие кеши
cacheService.removeOlderThan(Duration.ofDays(7));
// Архивируем логи
logService.archiveOlderThan(Duration.ofDays(30));
// Перестраиваем индексы для оптимизации
databaseService.rebuildIndices();
log.info("Maintenance cleanup completed");
}
Почему именно планировщик был нужен
- Надёжность: Выполнится автоматически, даже если разработчик забыл
- Консистентность: Синхронизируется по расписанию, а не в случайное время
- Масштабируемость: Обновить 1000 магазинов одновременно
- Мониторинг: Можем отслеживать успех/неудачу синхронизации
- Оптимизация нагрузки: Запускаем тяжёлые операции в ночь, не мешая пользователям
- Восстановление: При сбое автоматически переполнимся после перезагрузки
Инструменты, которые мы использовали
// Spring Scheduler
@EnableScheduling // В конфиге приложения
// Quartz для более сложных сценариев
@Configuration
public class QuartzConfig {
// Для IKEA использовали Quartz для хранения расписаний в БД
// Можно менять расписание без перезагрузки приложения
}
// Redis для синхронизации между несколькими инстансами
// (чтобы синхронизация не запустилась на всех серверах одновременно)
Итог
Планировщик в проекте IKEA был критической компонентой инфраструктуры, обеспечивающей:
- Автоматическую синхронизацию каталога 1000+ магазинов
- Генерацию отчётов в нужное время
- Оптимизацию нагрузки на системы
- Уведомление команды об ошибках
Без планировщика система была бы зависима от ручных действий и была бы ненадёжна.