Нужен совет как считать много сущностей как можно чаще?
Задача следующая.
Есть набор сущностей - Задача.
Есть множество ролей пользователей.
Есть несколько счетчиков, которые считают определенную область задач.
Надо считать с наименьшим лагом.
Не могу использовать такие умные слова, как мемкеш, редис и пр.
php 5.4 - 5.6
Теперь подробнее.
есть 100500 пользователей. У них есть 100500 задач. У задач есть статусы и дедлайны.
есть несколько видов счетчиков - без дедлайна, просрочен, почти просрочен, не просмотрен, ждет контроля.
Надо как то это считать.
есть несколько мыслей.
1. на каждом хите пересчитывать все счетчики. Для большого кол-ва сущностей и пользователей это будет мягко сказать тяжело. Даже если буду кешировать это минут на 5.
2. при любом изменении определенных полей сущности пересчитывать от 2 до 11 счетчиков для каждого пользователя, участвующего в задаче. а там от 2 и более может быть. Тоже как то не особо просто получается.
3. инкрементный счет. в случае если что то пойдет не так, все счетчики рушатся и только полный сброс им поможет.
Счетчики можно разделить на две категории, статические и динамические (по отношению ко времени)
1. Статические - можно изменять по триггеру КРУД изменения сущности.
1.1. Не просмотрены
1.2. Просрочены
1.3. Почти просрочены
1.4. ждет контроля
1.5. без дедлайна
2. Динамические - нужно постоянно пересчитывать. как можно чаще.
2.1. просрочены
2.2. почти просрочены
Ко всему прочему, у нас есть еще Проекты, в которых находятся сущности.
Нам нужно собирать счетчики и в разрезе проекта.
не могу решить как сделать и по какому пути пойти.
были ли у вас похожие задачи?
Лично я, возможно остановился бы на инкрементном счёте с актуализацией раз в час - два. И, может быть даже отдельный микросервис для пересчёта сделал бы.
Смотрите, есть клиенты, у которых 2 тыс пользователей и порядка 100 тыс задач. 5 типов счетчиков.
+ возможность делать срез по группе задач.
итого представьте как мне пересчитывать каждый час два эти 100тыс задач и писать данные на 2 тыс пользователей.
вообще я понимаю, что пытаюсь из бутылки сделать ракету и улететь домой на марс... но все же надеюсь на какое то нестандартное решение.
Lander, раньше, до меня была инкрементная система. на удивление, оооочень часто случались моменты, когда рассинхрон происходил.
я переделал на пересобирать счетчики запросом на хите и кешировать
и опять идет какой то рассинхрон, хотя его можно раз в пару часов синхронизировать.
но в эту схему не ложится уже по группам. это +11 сложных запросов получается.
тут задача конечно нетривиальная, но и решение из области очевидных - вынос в отдельную таблицу, крон раз в минуту на обновление, это все лучше чем 100500 юзеров раз в 5 минут это все будут запрашивать. Тут уже нужен баланс типов счетчиков/ отдельных подсчетов. Тут вопрос не логики как сделать идеально, таких решений в принципе нет, просто тут нужен тонкий баланс между "все пропало" и "лучше не бывает".
ThunderCat, про вынос согласен. но и такие объемы в теории не есть хорошо переносить да и просто дублировать в отдельных таблицах. ибо все данные уже есть в одной общей. (в одном лишь счетчике считается с привлечением иннер джоина и лефтджоина)
в данный момент пришел к тому. что
1. пересчитываю все счетчики всех пользователей, которые участвуют в задаче
2. раз в 15 минут пересчет всех счетчиков, которые по дедлайну.
в теории не есть хорошо переносить да и просто дублировать в отдельных таблицах. ибо все данные уже есть в одной общей.
Вопрос нормализации/денормализации. В теории с нормальными формами все зашибись и красиво, на практике объемы выборки вносят свои коррективы. Денормализацию не от хорошей жизни используют, как раз случай как у вас, искусство построения хайлоад, в частности, найти что можно дешево денормализовать с минимальными потерями консистентности. Тот же редис и иже с ними - денормализация в чистом виде - дублирование и ускорение за счет консистентности хранимых данных. Так что - выносить без вопросов, счетчики же у вас не идут никуда в хранение - только промежуточно выносятся с каким-то интервалом в отдельную таблицу. Нарушения связей не происходит, только незначительное дублирование, это приемлемо.
2. при любом изменении определенных полей сущности пересчитывать от 2 до 11 счетчиков для каждого пользователя, участвующего в задаче. а там от 2 и более может быть. Тоже как то не особо просто получается.
Я бы делал именно так. Не просто? Да, в программировании бывает не просто.
Также в исходном вопросе и во многих комментариях высказывались опасения, что тот или иной подход будет тормозить - это звучит как "пальцем в небо".
Мы говорим о счётчиках "просрочен"/"не просрочен"/"без дедлайна" - это условия по полям с датами и выборка по user_id (int) - такие поля отлично индексируются! Попробуйте написать запрос, сделайте EXPLAIN, добавьте индексов, делайте EXPLAIN ещё раз.
Если оптимизировать индексы никак не выходит, показывайте запрос, обсудим конкретику.