Roda, Sequel, Sidekiq 7, Redis. В 2:00 крон запускает импорт прайсов от поставщиков, он ставит по джобе на каждый товар, выходит около 60 тысяч. Всё в одну очередь default. К семи утра там ещё 40 тысяч, и письма с подтверждением регистрации, которые тоже в default, уходят людям через час. Пока ехал утром с Гражданки, поддержка уже переслала три жалобы. Конфиг сейчас:
:concurrency: 10
:queues:
- default
Сервер один, 4 ядра. Что разумнее: добавить потоков или делить очереди?
Сначала делить. Письма и всё, чего ждёт человек, в отдельную очередь, импорт в свою с низким весом. Веса в Sidekiq работают так, что низкая очередь не голодает, но и не мешает:
:concurrency: 10
:queues:
- [critical, 6]
- [default, 3]
- [import, 1]
Ещё лучше отдельный процесс Sidekiq только под import со своим concurrency, тогда импорт вообще не занимает потоки писем. И посмотрите, во что упирается импорт: если в базу, лишние потоки сделают только хуже.
60 тысяч джоб на 60 тысяч товаров тоже перебор. Бейте на пачки по 500 и пишите одним upsert на пачку, будет 120 джоб
Сделал оба совета. Импорт кладёт джобы пачками по 500 товаров в очередь import, у неё отдельный процесс Sidekiq с concurrency 3. Письма в critical. Запись одним запросом на пачку:
DB[:products]
.insert_conflict(
target: :sku,
update: { price: Sequel[:excluded][:price], updated_at: Sequel::CURRENT_TIMESTAMP }
)
.multi_insert(rows)
Итог первой ночи: импорт закончился в 3:10, раньше тянулся до девяти утра, очередь писем ни разу не поднималась выше 20. Утром впервые за месяц никто не написал в поддержку, что письмо не пришло.
И повесьте алерт не только на размер очереди, но и на возраст самой старой джобы. Sidekiq это отдаёт: Sidekiq::Queue.new("critical").latency. Если latency писем больше минуты, пусть кто-то узнаёт об этом раньше пользователей.