Лучший способ разработать масштабируемую систему просмотров / аналитики?
Вопрос
Компания, в которой я работаю, создает приложения для платформы Blackberry.
Мы работаем над собственной "системой аналитики", которая позволяет нам встраивать код в наши приложения и заставлять приложения сообщать некоторую статистику нашим центральным серверам при каждом запуске.В настоящее время система работает нормально;однако это только в бета-версии со 100-200 посещениями в час."Обращения" отправляются на серверы без проблем.Мы создали очень надежный API для обработки приема и хранения обращений (в базе данных MySQL).Мы протестировали загрузку, и мы должны быть в состоянии без проблем обрабатывать сотни тысяч обращений в час.На самом деле это не проблема.
Проблема в том, чтобы показывать статистику.Мы создали панель отображения, похожую на Mint (haveamint.com), она показывает хиты за каждый час, прошедшие дни, месяцы, недели, годы ... и т.д.Первая версия выполняла прямые запросы, извлекая данные из таблицы обращений и интерпретируя их "на лету".Это работало не очень долго.Наше текущее решение заключается в том, что обращения ставятся в "очередь" для обработки, и каждые 5 минут у нас появляется cron, который собирает обращения и сортирует их по "кэшам" для каждого часа, дня, недели, месяца, года ... и т.д.Это работает потрясающе и невероятно масштабируемо;однако это работает только для 1 часового пояса.Поскольку доступ к этому есть у всей компании, мы имеем дело с несколькими сотнями пользователей в разных часовых поясах.То, что я определяю как "Сегодня" в Сан-Хосе, СИЛЬНО отличается от того, что мой коллега в Лондоне определяет как "Сегодня".Поскольку текущее решение кэшируется только в 1 часовом поясе, это кошмар для всех, кто проверяет данные за пределами нашего часового пояса.
Наш текущий план по исправлению этого заключается в создании кэшей для каждого часового пояса (всего 40).;однако это означало бы, что мы умножаем объем данных на 40 ... для меня это ужасно, и, учитывая, что кэши могут быть очень большими, умножение просто звучит как плохая идея;кроме того, когда мы перейдем к обработке очереди, потребуется намного больше процессорного времени, чтобы поместить их в 40 различных кэшей.
У кого-нибудь еще есть лучшее представление о том, как решить эту проблему?
(Извините за такой длинный question..it не совсем легко объяснить.Спасибо всем!)
Решение
Решение, которое вы предлагаете, имеет слишком много избыточности.Я бы посоветовал вам хранить данные как минимум в 30-минутных сегментах вместо почасовых, а часовой пояс нормализовать к UTC.
С помощью 30-минутных сегментов, если пользователь запрашивает почасовые данные за 1-2 часа дня с -4.5 UTC, вы можете извлечь данные за 5:30 - 6:30 вечера из вашей системы и показать это.Если вы храните данные с шагом в один час, вы не сможете обслуживать запросы пользователей в часовых поясах с разницей N + 0,5 часа.
Для ежедневных номеров вам потребуется объединить 48 получасовых интервалов.Выбор слотов будет определяться часовым поясом пользователя.
Это становится интересным, когда вы переходите к годовым данным, потому что в конечном итоге вам приходится агрегировать 17 520 получасовых сегментов.Чтобы упростить это вычисление, я бы посоветовал вам получить предварительно агрегированные годовые данные по времени UTC и вычесть агрегированные данные за первые 4,5 часа года и добавить агрегированные данные за первые 4,5 часа следующего года.Это, по сути, сдвинет весь год на 4,5 часа, а работы не так уж много.Работая отсюда, вы можете дополнительно настроить систему.
Редактировать:Оказывается, в Катманду + 5.45 по Гринвичу, поэтому вам нужно будет хранить данные в 15-минутных пакетах вместо 30-минутных.
ПРАВКА 2:Еще одно простое улучшение связано с ежегодным агрегированием, поэтому вам не нужно каждый раз добавлять 17 520 корзин и не требуется использовать один агрегат для каждой страны.Объедините годовые данные за период с 02 января по 30 декабря.Поскольку максимальная разница в часовых поясах между любыми двумя странами составляет 23 часа, это означает, что вы можете взять годовые данные (02 января - 30 декабря) и при необходимости добавить несколько сегментов до и после.Например, для часового пояса -5 UTC вы бы добавили все сегменты 01 января после 05.00, все сегменты 31 декабря и 01 января следующего года до 05.00 часов.
Другие советы
При разработке программного обеспечения, которое затрагивает несколько часовых поясов, я бы посоветовал всегда сохранять вашу дату / время в UTC с другим полем для исходного часового пояса и имеют функцию, которая принимает время и преобразует его в UTC / часовой пояс и обратно.Вы избавите себя от множества хлопот, связанных с различными случаями перехода на летнее время, людьми, просматривающими статистику из страны с другой стороны земли, и так далее....
В вашем случае наличие кэшей в UTC и простая настройка запросов для преобразования в UTC должны помочь.Не сохраняйте статистику как "сегодняшнюю", сохраняйте ее с 00:00:00 по Гринвичу до 23:59: 59 по Гринвичу, и когда кто-нибудь запросит статистику за сегодняшний день в Нью-Йорке, выполните преобразование.
Насколько я могу судить, вы ищете здесь часть хранилища системы хранилища данных (ваши отчеты будут внешним интерфейсом).
На самом деле, способ, которым коммерческие системы делают это, - это кэш, который вы описали:Предварительно сгруппируйте свои таблицы и создайте из них кэши.Единственный способ ускорить ваши запросы - это заставить систему баз данных делать для них меньше.Это означает меньше данных, что, в свою очередь, означает меньше времени, затрачиваемого на повторение данных, или меньше данных в индексах.
Тем не менее, я бы либо предложил "решение для кэша 40" (действительно ли существует более 24 часовых поясов).Вы должны быть в состоянии тривиально распараллелить очередь сортировки, создав копии данных.
Другим способом сделать это было бы кэшировать с детализацией по часам, а затем объединить часы в дни (или 30 минут, если этого требуют ваши часовые пояса).Это означает, что вы кэшируете с более высокой степенью детализации, чем ваш ежедневный кэш, но с более грубой детализацией, чем исходные данные.
такого рода данные обычно хранятся с использованием циклических баз данных.проверьте это http://www.shinguz.ch/MySQL/mysql_20070223.html и это http://techblog.tilllate.com/2008/06/22/round-robin-data-storage-in-mysql/ чтобы знать, как они работают и как это реализовать под MySQL