Понимание запросов в реальном времени в любом масштабе

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

Cloud Firestore и мобильные/веб-SDK Firebase предоставляют мощную модель для разработки бессерверных приложений, в которых клиентский код напрямую обращается к базе данных. SDK позволяют клиентам прослушивать обновления данных в режиме реального времени. Вы можете использовать обновления в реальном времени для создания адаптивных приложений, не требующих серверной инфраструктуры. Хотя запустить что-то очень легко, это помогает понять ограничения в системах, составляющих Cloud Firestore , чтобы ваше бессерверное приложение масштабировалось и хорошо работало при увеличении трафика.

В следующих разделах приведены советы по масштабированию вашего приложения.

Выберите расположение базы данных рядом с вашими пользователями.

На следующей диаграмме показана архитектура приложения реального времени:

Пример архитектуры приложения реального времени

Когда приложение, запущенное на устройстве пользователя (мобильном или веб-сайте), устанавливает соединение с Cloud Firestore , соединение направляется на внешний сервер Cloud Firestore в том же регионе , где находится ваша база данных. Например, если ваша база данных находится в us-east1 , соединение также идет к интерфейсу Cloud Firestore также в us-east1 . Эти соединения долговечны и остаются открытыми до тех пор, пока приложение явно не закроет их. Интерфейс считывает данные из базовых систем хранения Cloud Firestore .

Расстояние между физическим местоположением пользователя и местоположением базы данных Cloud Firestore влияет на задержку, с которой сталкивается пользователь. Например, пользователь из Индии, чье приложение взаимодействует с базой данных в регионе Google Cloud в Северной Америке, может обнаружить, что работа работает медленнее, а приложение менее быстрое, чем если бы база данных была расположена ближе, например, в Индии или в другой части Азии. .

Дизайн для надежности

Следующие темы улучшают или влияют на надежность вашего приложения:

Включить автономный режим

Пакеты Firebase SDK обеспечивают сохранение данных в автономном режиме. Если приложение на устройстве пользователя не может подключиться к Cloud Firestore , оно остается работоспособным, работая с локально кэшированными данными. Это гарантирует доступ к данным, даже если у пользователей наблюдается нестабильное подключение к Интернету или они полностью теряют доступ на несколько часов или дней. Дополнительные сведения об автономном режиме см. в разделе Включение автономных данных .

Общие сведения об автоматических повторных попытках

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

Выбирайте между региональными и мультирегиональными локациями

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

Понимание системы запросов в реальном времени

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

Представьте себе двух пользователей, которые подключаются к Cloud Firestore через приложение для обмена сообщениями, созданное с использованием одного из мобильных SDK.

Клиент А записывает в базу данных информацию о добавлении и обновлении документов в коллекции под названием chatroom :

collection chatroom:
    document message1:
      from: 'Sparky'
      message: 'Welcome to Cloud Firestore!'

    document message2:
      from: 'Santa'
      message: 'Presents are coming'

Клиент Б прослушивает обновления в той же коллекции, используя прослушиватель снимков. Клиент Б получает немедленное уведомление всякий раз, когда кто-то создает новое сообщение. На следующей диаграмме показана архитектура прослушивателя снимков:

Архитектура подключения прослушивателя снимков

Следующая последовательность событий происходит, когда клиент B подключает прослушиватель снимков к базе данных:

  1. Клиент Б открывает соединение с Cloud Firestore и регистрирует прослушиватель, вызвав onSnapshot(collection("chatroom")) через Firebase SDK. Этот слушатель может оставаться активным часами.
  2. Интерфейс Cloud Firestore запрашивает базовую систему хранения для загрузки набора данных. Он загружает весь набор результатов совпадающих документов. Мы называем это опросным запросом . Затем система оценивает правила безопасности Firebase базы данных, чтобы убедиться, что пользователь может получить доступ к этим данным. Если пользователь авторизован, база данных возвращает данные пользователю.
  3. Затем запрос клиента B переходит в режим прослушивания . Прослушиватель регистрируется в обработчике подписки и ожидает обновлений данных.
  4. Клиент А теперь отправляет операцию записи для изменения документа.
  5. База данных фиксирует изменение документа в своей системе хранения.
  6. Транзакционно система фиксирует одно и то же обновление во внутреннем журнале изменений. Журнал изменений устанавливает строгий порядок внесения изменений по мере их возникновения.
  7. Журнал изменений, в свою очередь, распределяет обновленные данные по пулу обработчиков подписок.
  8. Сопоставитель обратного запроса выполняется, чтобы проверить, соответствует ли обновленный документ каким-либо зарегистрированным в настоящее время прослушивателям снимков. В этом примере документ соответствует прослушивателю снимков клиента B. Как следует из названия, вы можете думать об обратном сопоставлении запросов как об обычном запросе к базе данных, но выполняемом в обратном порядке. Вместо поиска документов в поисках тех, которые соответствуют запросу, он эффективно просматривает запросы, чтобы найти те, которые соответствуют входящему документу. При обнаружении совпадения система пересылает рассматриваемый документ прослушивателям снимков. Затем система оценивает правила безопасности Firebase базы данных, чтобы гарантировать, что данные получают только авторизованные пользователи.
  9. Система пересылает обновление документа в SDK на устройстве клиента B, и срабатывает обратный вызов onSnapshot . Если локальное сохранение включено, SDK также применяет обновление к локальному кэшу.

Ключевая часть масштабируемости Cloud Firestore зависит от разветвления журнала изменений на обработчики подписок и внешние серверы. Разветвление позволяет эффективно распространять одно изменение данных для обслуживания миллионов запросов в реальном времени и подключенных пользователей. Запуская множество реплик всех этих компонентов в нескольких зонах (или нескольких регионах в случае развертывания в нескольких регионах), Cloud Firestore обеспечивает высокую доступность и масштабируемость.

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

Примените лучшие практики для масштабирования запросов в реальном времени.

Примените следующие рекомендации для разработки масштабируемых запросов в реальном времени.

Понимание высокого трафика записи в системе

Этот раздел поможет вам понять, как система реагирует на увеличение количества запросов на запись.

Журналы изменений Cloud Firestore , которые управляют запросами в реальном времени, автоматически масштабируются горизонтально по мере увеличения трафика записи. Поскольку скорость записи в базу данных превышает возможности одного сервера, журнал изменений разделяется на несколько серверов, и обработка запросов начинает использовать данные от нескольких обработчиков подписки вместо одного. С точки зрения клиента и SDK все это прозрачно, и в случае разделения никаких действий со стороны приложения не требуется. На следующей диаграмме показано, как масштабируются запросы в реальном времени.

Архитектура разветвления журнала изменений

Автоматическое масштабирование позволяет без ограничений увеличивать трафик записи, но по мере увеличения трафика системе может потребоваться некоторое время для ответа. Следуйте рекомендациям правила 5-5-5 , чтобы избежать создания горячей точки записи. Key Visualizer — полезный инструмент для анализа горячих точек записи.

Многие приложения имеют предсказуемый органический рост, который Cloud Firestore может обеспечить без каких-либо мер предосторожности. Однако пакетные рабочие нагрузки, такие как импорт большого набора данных, могут привести к слишком быстрому увеличению количества операций записи. При разработке приложения следите за тем, откуда поступает трафик записи.

Понять, как взаимодействуют запись и чтение

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

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

Сохраняйте документы и операции записи небольшими

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

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

Используйте эффективные слушатели

По мере увеличения скорости записи в вашей базе данных Cloud Firestore разделяет обработку данных на множество серверов. Алгоритм сегментирования Cloud Firestore пытается разместить данные из одной и той же коллекции или группы коллекций на одном сервере журнала изменений. Система пытается максимизировать возможную пропускную способность записи, сохраняя при этом как можно меньшее количество серверов, участвующих в обработке запроса.

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

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

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

Делайте запросы опросов быстрыми

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

При некоторых обстоятельствах слушатель также может вернуться из состояния прослушивания в состояние опроса. Это происходит автоматически и прозрачно для SDK и вашего приложения. Следующие условия могут вызвать состояние опроса:

  • Система повторно балансирует журнал изменений в связи с изменениями нагрузки.
  • Горячие точки вызывают сбои или задержку записи в базу данных.
  • Временные перезапуски сервера временно влияют на прослушиватели.

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

Отдавайте предпочтение слушателям-долгожителям

Открытие и поддержание прослушивателей как можно дольше часто является наиболее экономичным способом создания приложения, использующего Cloud Firestore . При использовании Cloud Firestore вам выставляется счет за документы, возвращенные в ваше приложение, а не за поддержание открытого соединения. Долгоживущий прослушиватель снимков считывает только те данные, которые ему необходимы для обслуживания запроса на протяжении всего его существования. Это включает в себя первоначальную операцию опроса, за которой следуют уведомления, когда данные действительно изменяются. С другой стороны, однократные запросы повторно считывают данные, которые, возможно, не изменились с момента последнего выполнения запроса приложением.

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

Что дальше