LINUX.ORG.RU

Фоновая обработка задач. Внештатные ситуации.


0

1

Есть n миллионов записей (лог) раз в минуту нужно собирать статистику за прошедший час (~10 записей). Нельзя просто where `time` > 'час назад'. Потому что сервис может: а) упасть и про**ать статистику, б) захлебнуться и про**ать статистику.

Для решения проблемы я обращаюсь к дате из последней записи статистики, дёргаю час логов, идущий после указанного в статистике. Всё просто? Нет. Сервер мог лежать или ещё что, потому часов может быть два. Какой выход? Првоерить несколько часов подряд пока не случится «текущее время».

Проверка выполняется отложенно: собралась статистика в 10:20, через 5 минут запускается проверка на «не наступило ли время собирать статистику». Из-за такого увеличения времени может получиться что шедулер назначится на 59 минут 50 секунд и я случайно «перепрыгну» в следующий час. И про**у час статистики!

Архитектра кривая. Написал костыль чтоб такого не было. А как надо было, чёрт?..


Ответ на: комментарий от zz

Логи тут читаются. Мне нужно содрать сн их статистику после того, как час кончится.

daris
() автор топика

ничего не понял. Ну запускай каждый час по треду и считай свою статистику за прошедший час.

nokachi
()

если log тестовый

man tail

anonymous
()

Архитектра кривая. Написал костыль чтоб такого не было. А как надо было, чёрт?..

log >> mysql

drBatty ★★
()

да, если тебя не прёт СУБД, то запоминай номер последней прочитанной строки, и читай лог командой tail --lines=+12345

Здесь 12345 номер посл. строки +1.

drBatty ★★
()

Я делал проще вешал процесс на чтение лога ежесекундно со смещение по размеру файла + поиск последней обработанной строки на основании времени из лог-файла. Вообще выбор как часто выбирается от скорости парсера, т.к. чем быстрее парсер обрабатывает, тем лучше. Конечно, усложнится архитектура расчета статистики, придется где-то складировать куски, но зато ничего не потеряется.

gh0stwizard ★★★★★
()
Ответ на: комментарий от daris

Так, я вообще перестал понимать задачу. Почему не подходит просто брать из логов записи новее последней записи в статистике? Зачем запускать проверку на то, нужно ли собирать статистику раз в 5 минут?

Tark ★★
()

ты бы лучше сначала внятно написал задачу, а потом уже свои мутные рассуждения, так чтобы задача от твоих мыслей была явно отделена.

qnikst ★★★★★
()

запоминать айдишник последней обработанной записи? и потом селектать начиная с этого айдишника и до конца.

stevejobs ★★★★☆
()
Ответ на: комментарий от Tark

{10:00, 10:59, 11:00, 11:59, 12:00, 12:59, 13:00} - массив логов с временными метками.

Последняя статистика в 9:20. Маловероятно, но так бывает. Берём статистику, смотри что там 9 часов, прибавляем час, получаем период 10:00-10:59. Собираем для него статистику.

Что дальше? Если бы всё было идеально, мы бы запустили проверку для текущего часа (так как мы считаем для 10 часов, то логично что сейчас 11) в 12 часов и 5 минут.

Но у нас уже 13 часов и запускать код в прошлом мы не можем.

daris
() автор топика
Ответ на: комментарий от qnikst

В два ночи было трудно :)

Задача: для каждого часа собирать статистику. В таблице с логами есть логи и время их записи, соответственно. Таблица огромная, нагрузка большая, потому нужно делать это в минимум ходов.

daris
() автор топика
Ответ на: комментарий от daris

я всё равно не понял, основная проблема в том, что статистика по часу может собирается дольше часа?

вставляем в крон на 1 раз в час скрипт, который делает следующее:

выясняет какой сейчас час. проверяет работает ли аналог текущего скрипта (проверяет наличие /run/stat/pid.lock) если он есть, то создаёт файл (/var/lib/stat/schedule/<YYYY-MM-DD HH:MM в POSIX>) и выходит.

Иначе:

1). создаёт файл /run/stat/pid.lock

2). считает статистику за час и сохраняет куд надо

3). убирает файл /run/stat/pid.lock

4). ищет наличие файлов в /var/stat/schedule и выбирает первый файл. и далее на 1 пункт.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

на самом деле можно проще и надёжнее, но тут вопрос, как у вас хранятся результаты. :)

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

У меня есть 1 000 хостов, логи которых пишутся. Пусть с каждого хоста по 100 000 записей логов в бд. 100 000 000 строк. Нужно в течении часа сделать 1 000 запросов, то есть на запрос есть 3.6 секунды.

Я поставлю алтарь каким-то там богам если это на mysql возможно. Бд менять не буду, потому что разница между ними минимальна и в первую очедь нужно оптимизировать запросы.

Пока что я надеюсь что время выполнения будет меньше. Первые несколько месяцев. А дальше - кластер бд, если понадобится. Но сперва нужно оптимизировать алгоритм.

Запросы выполняются асинхронно.Не могу ж я 1 000 запросов ставить в очередь и ждать, верно? Так и нагрузка будет адовая (хост ляжет на 10 минут даже если вы делается быстро) и очередь может выполниться на за 3 600 секунд, а за 3 800 секунд и время уползёт (на 3 минуты).

Поэтому у меня 1 000 обращений запускаются не скопом, а частями, размазывая нагрузку равномерно и, к тому же, отслеживая чтобы всё выполнилось.

Если запрос на вычисление статистики для 11:00-11:59 не был запущен с 12:00 до 12:59 (не успелось, бывает), нужно чтобы при следующем запуске код посчитал статистику и для 11:00-11:59 и для 12:00-12:59.

daris
() автор топика
Ответ на: комментарий от daris

Пока что работает так:

1) При запуске берётся час после последней записи статистики.

2) Проверятся что час прошёл.

3) Статистика для прошедшего часа считается.

4) Цикл повторяется.

а) Если 2 истинно, то в 4 повтор через 5 минут.

б) Если 2 ложно, то в 4 повтор назначается на начало следующего часа.

А) позволяет отловить пропущенные часа. С б) проблема в том, что не ясно начало какого часа брать. Кажется, нашлось решение...

daris
() автор топика
Ответ на: комментарий от daris

У меня есть 1 000 хостов, логи которых пишутся. Пусть с каждого хоста по 100 000 записей логов в бд. 100 000 000 строк. Нужно в течении часа сделать 1 000 запросов, то есть на запрос есть 3.6 секунды.

ок. 100 000 000 строк. ок, на какой-то запрос (наверное, несколько запросов или вызов prepared statement) 3.6 секунды, пока ничего ужасного

Я поставлю алтарь каким-то там богам если это на mysql возможно. Бд менять не буду, потому что разница между ними минимальна и в первую очедь нужно оптимизировать запросы.

ненужная информация

Пока что я надеюсь что время выполнения будет меньше. Первые несколько месяцев. А дальше - кластер бд, если понадобится. Но сперва нужно оптимизировать алгоритм.

алогитм чего? если сбора статистики, то вся остальная информация лишняя, если того, как этот сбор вызывать, то это лишнее.

Запросы выполняются асинхронно.Не могу ж я 1 000 запросов ставить в очередь и ждать, верно?

откуда я знаю? вполне вероятно, что можете и поставить, во всяком случае ничего плохого в этом нет, и очень вероятно, что в итоге отработает даже быстрее. Это нужно смотреть на реальной базе, а не гадать на кофейной гуще.

Так и нагрузка будет адовая (хост ляжет на 10 минут даже если вы делается быстро) и очередь может выполниться на за 3 600 секунд, а за 3 800 секунд и время уползёт (на 3 минуты).

и что? откуда какие-то проблемы?

Поэтому у меня 1 000 обращений запускаются не скопом, а частями, размазывая нагрузку равномерно и, к тому же, отслеживая чтобы всё выполнилось.

ну хорошо...

Если запрос на вычисление статистики для 11:00-11:59 не был запущен с 12:00 до 12:59 (не успелось, бывает), нужно чтобы при следующем запуске код посчитал статистику и для 11:00-11:59 и для 12:00-12:59.

и? где проблема то? Вышеописанный алгоритм враппера для запросов позволяет всё сделать, причём со всеми гарантиями запуска, причём даже на чистом баше. Хотя можно сделать на используемом вами ЯП + кроне.

Если вопрос про сами запросы, которые нужно оптимизировать это совсем другой разговор, но тогда вся эта чепуха не нужна, нужно описание схемы и что требуется собрать.

Если стоит вопрос, как успеть индексировать данные, которые поступают с огромной скоростью, то это третий вопрос, который правда решается опять же банальным способом.

qnikst ★★★★★
()
Ответ на: комментарий от daris

ожидание внутри программы не нужно и вредно.

Вот зачем создавать себе проблемы: 1 раз в час по крону запускается скрипт, который проверяет, работает ли уже инстанс этого скрипта, если работает — значит задачи не разгребли и тогда он записывает, отсек времени, который надо обработать в TODO. Если не работает можно приступать к работе, и обрабатывать известный час, после завершения работы проверять наличие задач в TODO, если есть делать, если нету - дохнуть. Всё. Остаются некоторые вопросы, связанные с тем, что делать если скрипт подох при сборе статистики.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

Вопрос был в том, как без лишних запросов и промежуточных страниц опредлять время запуска и период, который нужно обработать.

На бумаге у меня тоже всё офигенно ;)

Вопрос решён, я просто не до конца по первости продумал каким образос период опредляется. Вроде, исправил. Через пару часов узнаем.

Спасибо за чтение монолога, оч приятно :)

daris
() автор топика
Ответ на: комментарий от daris

У меня есть 1 000 хостов, логи которых пишутся. Пусть с каждого хоста по 100 000 записей логов в бд.

В бд писать логи? Шит, но делается в связке syslog + mysql/postgresql. Вообще мускл держит 20к инсертов в секунду (сейчас может и больше) на оптимизированных БД. Нетюненгованный (бесплатный syslog) держит 500 записей в секунду в файл. Если 100к капает в день, то разговор ни о чем :)

gh0stwizard ★★★★★
()
Ответ на: комментарий от daris

Нужно в течении часа сделать 1 000 запросов …

Зачем 1000 запросов? Что мешает получить статистику для всех хостов одним запросом с группировкой?

anonymous
()
Ответ на: комментарий от daris

Мда, запутал ты людей, как путана :) Теперь осталось понять как связаны 1000 хостов с твоей задачей, у них у каждого своя бд что ли? Если да, то какой смысл делать к ним запросы, когда это они сами должны формировать отчеты и слать в централизованное место. Вот если не пришел отчет, то это авария, такие-то действия...

gh0stwizard ★★★★★
()
Ответ на: комментарий от gh0stwizard

Всё работает :) Вчера был в запарке после третьего дня проектирования «быстрой» версии этой херни...

daris
() автор топика
Ответ на: комментарий от daris

я бы сделал агрегатор, т.е тупо, до того как данные попадут в базу, суммировать(или что там нужно) данные в в течение промежутка времени, при наступлении следующего периода просто сбрасываем счетчики и начинаем по новой. Плюсы: статистика в реалтайме. 100 000 000 запросов в час = около 30 000 в секунду - не такая уж и нагрузка.

buzzi555
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.