Я ищу облачный сервис, который может выполнять расширенные статистические расчеты по большому количеству голосов, поданных пользователями, в «реальном времени».
В нашем приложении пользователи могут голосовать по разным темам, например, выбрать понравившееся, поставить оценку от 1 до 5, сказать да/нет и т. д.
Мы также хотим показать пользователю «живую» статистику, показывающую популярность человека и т. д. Это будет сгенерировано довольно сложным SQL, где мы вычисляем среднее количество раз, когда человек был выбран в качестве избранного, деленное на общее количество количество голосов и количество игр, в которых человек участвовал и т. д. И счет за последние X игр должен учитываться выше, чем общий балл за все игры. Это всего лишь пример, есть несколько других SQL-запросов с аналогичной сложностью.
Все наши презентабельные данные (включая расчетную статистику) подаются из документов Firestore, а голоса будут сохранены как документы Firestore.
В идеале серверная часть Firebase (функции, firestore и т. д.) не должна знать о логике запроса.
Чего я хочу, так это облачного сервиса с оплатой по мере использования, который делает следующее:
Есть ли подобный продукт на рынке? Или его можно построить, объединив доступные облачные сервисы? И какой официальный термин для такого продукта, если я должен искать его сам?
Я знаю, что, вероятно, смогу создать подобное решение самостоятельно и запустить его на сервере базы данных, размещенном в облаке, который может масштабироваться по мере роста наших потребностей, но я считаю, что я не первый разработчик, которому это нужно, поэтому я надеюсь, что кто-то решил это до меня :)
Вы можете использовать существующие облачные сервисы, доступные на Google Cloud Platform. Google BigQuery, Облачное хранилище Google Firestore, Сервер приложений Google (задания CRON), Облачные задачи Google
Услуги могут быть использованы для решения проблем, упомянутых выше:
1) Google BigQuery: здесь вы можете определить схему данных, для которых вы собираетесь выполнять SQL-запросы. BigQuery поддерживает стандартные и устаревшие запросы SQL.
2) Каждый голос может быть отправлен в определенные таблицы BigQuery с помощью службы потоковой вставки.
3) Каждое отправленное голосование может запускать службу пересчета, которая вычисляет статистику, выполняя определенные SQL-запросы, а результаты запросов могут быть сохранены в виде документов в коллекциях в Google Cloud Firestore.
4) Google Cloud Firestore: Здесь вы можете хранить оперативную статистику пользователя. Это база данных в режиме реального времени, поэтому вы сможете настроить прослушиватели для изменений в статистике и показать изменения, как только статистика будет пересчитана.
5) В том же сервисе, который вставляет каждый голос, создайте новую запись с «syncId» в другой таблице. Идея состоит в том, чтобы сгруппировать количество голосов, поданных за определенный интервал, по соответствующему syncId. К syncId может добавляться отметка времени. В соответствии с вашими требованиями может быть установлен определенный временной интервал, чтобы перерасчет мог быть запущен с помощью службы заданий CRON, которая вызывает службу пересчета в пределах интервала. После завершения пересчета, связанного с конкретным syncId, запись, соответствующая этому syncId, должна быть помечена как выполненная.
Мы используем вышеуказанные технологии для создания веб-приложения на Google Cloud Platform, где входные данные записываются в Google Firestore, а затем вставляются в Google BigQuery. Данные, хранящиеся в BigQuery, запрашиваются через 30 секунд после каждого обновления с использованием SQL-запросов, а результаты запросов сохраняются в Google Cloud Firestore для обслуживания информационных панелей, которые автоматически обновляются с помощью прослушивателей, настроенных для коллекции, в которой хранится информация о сводных панелях.
1) Результаты SQL-запроса могут храниться в виде представлений со сроком действия. Представления обрабатываются в BigQuery как табличные ресурсы, поэтому мы можем создать таблицу, используя результаты запроса, и установить время истечения срока действия, если представление следует удалить позже Создание представлений.
3) Служба пересчета в основном представляет собой Облачная задача Google с записью синхронизации со сгенерированным идентификатором синхронизации, который создается при сохранении первого голоса. Задачу можно запланировать на запуск через 30 секунд с момента ее создания. Задача создана и ждет 30 сек. Таким образом, все голоса, поданные в течение этого 30-секундного периода, должны быть отмечены этим идентификатором синхронизации. Когда задача начинает выполняться, запись синхронизации помечается как «В ВЫПОЛНЕНИИ», а все новые голоса помечаются другой новой записью синхронизации. Задача выполняет нужный запрос и обновляет статистику в Cloud Firestore.
5) Идентификаторы синхронизации соответствуют каждому пересчету. Чтобы гарантировать, что данные запрашиваются через 30 секунд, мы используем запланированные задачи в Cloud Tasks, где мы можем установить время задержки 30 секунд. Задания CRON являются вариантом, но в период, когда голоса не подаются, CRON все равно будет работать, поэтому он не является предпочтительным. Поскольку задача будет создана только при сохранении новых голосов, мы выберем все голоса по их последней записи в таблице BigQuery. Сколько голосов выбрать, зависит от вашей логики и того, как вы разрабатываете схему для своей таблицы BigQuery.
По моему опыту работы с BigQuery, я смог вставить более 200 строк данных, содержащих более 100 столбцов, и почти сразу же запросить вставленные данные, а данные были доступны в 99,999% случаев. Предполагая, что ваш пересчет выполняется каждые 30 секунд или около того, это не будет проблемой. Плата за BigQuery также взимается в соответствии с запрошенными данными. Поэтому я бы полностью рекомендовал его для обработки огромного количества данных.
Спасибо! Думаю, теперь у меня есть представление о том, как собрать установку :) Еще несколько вопросов:
1) Я создал несколько представлений, чтобы упростить свои запросы. Но я вижу, что BQ не поддерживает материализованные представления, и запросы к представлению выполняются каждый раз, когда представление используется в запросе. Альтернативное предложение состоит в том, чтобы создать временную таблицу на основе выбора, прежде чем выполнять фактические запросы. Поэтому я подумал о том, чтобы составить список всех необходимых запросов (на основе голосов) за определенный период (скажем, 1 час), а затем, прежде чем выполнять запросы, я бы создал временные таблицы, на которые я ссылаюсь в запросах.
Однако для этого, вероятно, потребуется, чтобы БД сканировала все голоса и GROUP BY id
и COUNT()
их. Допустим, в БД 1 млн голосов, а за последний час сохранено всего 100 голосов. Тогда было бы дешевле просто иметь подзапрос и ПРИСОЕДИНИТЬСЯ, чем создавать новую таблицу?
2) Я думал о коллекции jobs
, чтобы голоса влияли на статистику с интервалом в 1 час, я бы создал документ в jobs
с запланированным временем начала следующего часа. А затем воспользуйтесь сервисом Cloud Task. Затем для каждого нового голосования я создавал документ в jobs/{jobId}/tasks/{taskId}
, и в этом документе у меня были ссылки на статистику, которую мне нужно было обновить. Вся статистика сохраняется в документах firestore, таких как users/{uid}/statistics/votes
. И когда задание выполняется, я просто читаю все документы в jobs/{jobId}/tasks
, делаю запросы и сохраняю результаты.
Тем не менее, я вижу, что у вас есть syncID
s (которые, я считаю, похожи на jobID
s, которые я упоминаю) в таблице BQ. Так я предполагаю, что вы выбираете все идентификаторы синхронизации при выполнении задачи, а затем в запросах? В чем преимущество хранения этого в BQ вместо запланированного документа о задании с подколлекцией отдельных задач для этого задания, как я предлагаю?
3) Вы упоминаете App Engine. Для чего вы его используете, чего нельзя сделать в Cloud Functions? Моя идея заключалась в следующем: когда голос сохраняется в Firestore, активируйте облачную функцию, которая вставляет его в BQ, а затем определяете на основе содержания голосования, какая статистика для каких пользователей нуждается в обновлении. Найдите следующее запланированное задание и добавьте в него ссылку на затронутую статистику. Если следующего задания нет, создайте его и создайте задачу со ссылкой на идентификатор задания и запланированное время на следующие 00 минут. Затем задача должна вызвать облачную функцию HTTPS, которая будет выполнять запросы и получать данные из BQ.
@EsbenvonBuchwald Привет! Рад узнать, что могу быть чем-то полезен. Вот что я думаю о вопросах. 1) Вы можете создать временную таблицу при первом запуске запросов и установить режим записи ПЕРЕЗАПИСЬ, чтобы данные обновлялись при каждом запросе. Вы также можете использовать подход подзапроса. В конечном итоге это зависит от объема данных, которые вы ожидаете, и сложности подзапроса. Если есть сложные агрегаты или пользовательские функции для большого набора данных, лучше создать таблицу, выполнив сложный запрос.
2) Да. jobId
и SyncID
одинаковы. Сохранение jobId
в BQ дает преимущество использования его для объединения с таблицей голосов в BQ для запросов. Это особенно полезно, если вам нужно выполнить все запросы, связанные с несколькими заданиями, и объединить их в окончательный запрос. Будет удобно, если вы сможете отмечать голоса по вакансиям с помощью jobId
. Поэтому я рекомендую сохранять jobId
в Firestore, а также в BQ.
3) App Engine лучше подходит для приложений, которые имеют многочисленные части функциональности, которые ведут себя различными взаимосвязанными (или даже несвязанными) способами, в то время как облачные функции — это более конкретно одноцелевые функции, которые реагируют на какое-то событие и выполняют какое-то конкретное действие. Вы можете легко реплицировать облачные функции в App Engine, но репликация крупномасштабного приложения App Engine с использованием набора отдельных облачных функций будет сложной. В конечном счете, оба они работают на аналогичной базовой инфраструктуре Google, и вам решать, какой из них подходит для выполнения поставленной задачи.
Спасибо за ваш ответ. Несколько вопросов: 1) Сохраняете ли вы SQL-запросы в BigQuery как представления и т. д.? 3) Что это за услуга пересчета? Какая-то облачная функция, которую вы написали сами? 5) Что вы делаете для обработки этих идентификаторов синхронизации? У вас есть (псевдо) пример кода? Как вы гарантируете, что данные запрашиваются через 30 секунд? У вас есть задание cron * * * * * * / 30 ? Сколько вы выбираете, чтобы определить, нужно ли обрабатывать новые данные? Одна из моих проблем с BigQuery, SlicingDice и другими асинхронными облачными сервисами заключается в том, что данные недоступны сразу после вставки.