Понимание операций чтения и записи в масштабе

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

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

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

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

Понимание компонентов высокого уровня

На следующей диаграмме показаны компоненты высокого уровня, участвующие в запросе API Cloud Firestore .

Компоненты высокого уровня

Cloud Firestore SDK и клиентские библиотеки

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

Интерфейс Google (GFE)

Это инфраструктурный сервис, общий для всех облачных сервисов Google. GFE принимает входящие запросы и перенаправляет их в соответствующую службу Google (в данном контексте службу Cloud Firestore ). Он также предоставляет другие важные функции, включая защиту от атак типа «отказ в обслуживании».

Cloud Firestore

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

Уровень хранения Cloud Firestore

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

Ключевые диапазоны и разделения

Cloud Firestore — это документально-ориентированная база данных NoSQL. Данные хранятся в документах , которые организованы в иерархии коллекций . Иерархия коллекции и идентификатор документа преобразуются в один ключ для каждого документа. Документы логически хранятся и лексикографически упорядочиваются по этому единственному ключу. Мы используем термин «диапазон ключей» для обозначения лексикографически непрерывного диапазона ключей.

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

Синхронная репликация

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

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

Расположение данных

Cloud Firestore — это бессхемная база данных документов. Однако внутри он размещает данные в основном в двух таблицах в стиле реляционной базы данных на уровне хранения следующим образом:

  • Таблица документов : В этой таблице хранятся документы.
  • Таблица индексов : в этой таблице хранятся записи индекса, которые позволяют эффективно получать результаты и сортировать их по значению индекса.

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

Расположение данных

Один регион против нескольких регионов

При создании базы данных необходимо выбрать регион или несколько регионов .

Единственное региональное местоположение — это определенное географическое местоположение, например us-west1 . Разделения данных базы данных Cloud Firestore имеют реплики в разных зонах выбранного региона, как объяснялось ранее.

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

Дополнительную информацию о местонахождении региона см. в разделе «Местоположения Cloud Firestore .

Один регион против нескольких регионов

Понимание жизни записи в Cloud Firestore

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

Для всех видов записи Cloud Firestore предоставляет свойства ACID (атомарность, согласованность, изоляция и надежность) реляционных баз данных. Cloud Firestore также обеспечивает сериализуемость , что означает, что все транзакции отображаются так, как если бы они выполнялись в последовательном порядке.

Шаги высокого уровня в транзакции записи

Когда клиент Cloud Firestore выполняет запись или фиксирует транзакцию, используя любой из упомянутых ранее методов, внутри это выполняется как транзакция чтения-записи базы данных на уровне хранения. Транзакция позволяет Cloud Firestore предоставлять свойства ACID, упомянутые ранее.

На первом этапе транзакции Cloud Firestore считывает существующий документ и определяет изменения, которые необходимо внести в данные в таблице «Документы».

Это также включает внесение необходимых обновлений в таблицу индексов следующим образом:

  • Поля, добавляемые в документы, требуют соответствующих вставок в таблицу «Индексы».
  • Поля, удаляемые из документов, требуют соответствующего удаления в таблице «Индексы».
  • Поля, которые изменяются в документах, требуют как удаления (для старых значений), так и вставки (для новых значений) в таблицу индексов.

Чтобы вычислить упомянутые ранее мутации, Cloud Firestore считывает конфигурацию индексирования проекта. Конфигурация индексирования хранит информацию об индексах проекта. Cloud Firestore использует два типа индексов: однополевые и составные. Подробное описание индексов, созданных в Cloud Firestore , см. в разделе Типы индексов в Cloud Firestore .

После расчета мутаций Cloud Firestore собирает их внутри транзакции, а затем фиксирует ее.

Понимание транзакции записи на уровне хранения

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

На следующей диаграмме база данных Cloud Firestore имеет восемь разделений (отмечено 1–8), размещенных на трех разных серверах хранения в одной зоне, и каждое разделение реплицируется в 3 (или более) разных зонах. У каждого раскола есть лидер Паксоса, который может находиться в разных зонах для разных расколов.

<класс диапазона= Разделение базы данных Cloud Firestore">

Рассмотрим базу данных Cloud Firestore , содержащую коллекцию Restaurants , следующим образом:

Коллекция ресторанов

Клиент Cloud Firestore запрашивает следующее изменение документа в коллекции Restaurant , обновляя значение поля priceCategory .

Перейти к документу в коллекции

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

  1. Создайте транзакцию чтения-записи.
  2. Прочтите документ restaurant1 в коллекции Restaurants из таблицы Documents на уровне хранения.
  3. Прочтите индексы документа из таблицы Индексы .
  4. Вычислите мутации, которые необходимо внести в данные. В данном случае имеется пять мутаций:
    • M1: обновите строку restaurant1 в таблице «Документы» , чтобы отразить изменение значения поля priceCategory .
    • M2 и M3: удалите строки для старого значения priceCategory в таблице индексов для нисходящих и возрастающих индексов.
    • M4 и M5: вставьте строки для нового значения priceCategory в таблицу индексов для нисходящих и возрастающих индексов.
  5. Совершите эти мутации.

Клиент хранилища в сервисе Cloud Firestore ищет разделения, которым принадлежат ключи строк, которые необходимо изменить. Давайте рассмотрим случай, когда Split 3 обслуживает M1, а Split 6 обслуживает M2-M5. Существует распределенная транзакция, в которой в качестве участников участвуют все эти разделения. Разделения участников могут также включать любое другое разделение, из которого данные были считаны ранее в рамках транзакции чтения-записи.

Следующие шаги описывают, что происходит в рамках фиксации:

  1. Клиент хранилища выдает фиксацию. Коммит содержит мутации M1-M5.
  2. Сплиты 3 и 6 являются участниками этой транзакции. Один из участников выбирается в качестве координатора , например Split 3. Задача координатора — обеспечить, чтобы транзакция либо фиксировалась, либо прерывалась атомарно для всех участников.
    • Реплики-лидеры этих сплитов несут ответственность за работу, проделанную участниками и координаторами.
  3. Каждый участник и координатор запускает алгоритм Paxos со своими соответствующими репликами.
    • Лидер запускает алгоритм Paxos с репликами. Кворум достигается, если большинство реплик ответят « ok to commit ответа лидеру.
    • Затем каждый участник уведомляет координатора о своей готовности (первая фаза двухфазной фиксации). Если какой-либо участник не может подтвердить транзакцию, вся транзакция aborts .
  4. Как только координатор узнает, что все участники, включая его самого, готовы, он сообщает результат accept транзакции всем участникам (вторая фаза двухфазной фиксации). На этом этапе каждый участник записывает решение о фиксации в стабильное хранилище, и транзакция фиксируется.
  5. Координатор отвечает клиенту хранилища в Cloud Firestore , что транзакция зафиксирована. Параллельно координатор и все участники применяют мутации к данным.

Жизненный цикл фиксации

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

Пишет в мультирегионе

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

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

Каждая запись в Cloud Firestore также предполагает некоторое взаимодействие с механизмом реального времени в Cloud Firestore . Дополнительные сведения о запросах реального времени см. в разделе Понимание запросов реального времени в масштабе .

Поймите жизнь чтения в Cloud Firestore

В этом разделе рассматриваются автономные операции чтения не в реальном времени в Cloud Firestore . Внутренне сервер Cloud Firestore обрабатывает большинство этих запросов в два основных этапа:

  1. Одно сканирование диапазона по таблице индексов .
  2. Точечные поиски в таблице «Документы» на основе результатов предыдущего сканирования.
В Cloud Firestore могут быть определенные запросы, требующие меньше или больше обработки (например, запросы IN).

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

Понимание транзакции чтения на уровне хранения

В этом разделе описаны типы операций чтения и способы их обработки на уровне хранения в Cloud Firestore .

Сильное чтение

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

Чтение с одним разделением

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

На этом этапе в зависимости от выбранной реплики могут произойти следующие случаи:

  • Запрос на чтение поступает к реплике-лидеру (зона A).
    • Поскольку лидер всегда в курсе событий, чтение может быть продолжено напрямую.
  • Запрос на чтение отправляется на реплику, не являющуюся ведущей (например, зону B).
    • Разделение 3 может знать по своему внутреннему состоянию, что у него достаточно информации для обслуживания чтения, и разделение делает это.
    • Группа Split 3 не уверена, получила ли она последние данные. Он отправляет сообщение лидеру с просьбой указать временную метку последней транзакции, которую необходимо применить для обслуживания чтения. Как только эта транзакция будет применена, чтение может продолжиться.

Cloud Firestore затем возвращает ответ своему клиенту.

Мультираздельное чтение

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

устаревшее чтение

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

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

Избегайте горячих точек

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

Разделение хранилища и нагрузки требует времени, а слишком быстрое увеличение трафика может привести к ошибкам с высокой задержкой или превышением крайнего срока, обычно называемым «горячими точками» , пока служба адаптируется. Лучше всего распределить операции по диапазону ключей, одновременно увеличивая трафик коллекции в базе данных до 500 операций в секунду. После постепенного увеличения трафика увеличивайте его на 50 % каждые пять минут. Этот процесс называется правилом 500/50/5 и обеспечивает оптимальное масштабирование базы данных в соответствии с вашей рабочей нагрузкой.

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

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

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

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

Поиск неисправностей

Cloud Firestore предоставляет Key Visualizer в качестве диагностического инструмента, предназначенного для анализа моделей использования и устранения проблем с горячими точками.

Что дальше

,

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

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

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

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

Понимание компонентов высокого уровня

На следующей диаграмме показаны компоненты высокого уровня, участвующие в запросе API Cloud Firestore .

Компоненты высокого уровня

Cloud Firestore SDK и клиентские библиотеки

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

Интерфейс Google (GFE)

Это инфраструктурный сервис, общий для всех облачных сервисов Google. GFE принимает входящие запросы и перенаправляет их в соответствующую службу Google (в данном контексте службу Cloud Firestore ). Он также предоставляет другие важные функции, включая защиту от атак типа «отказ в обслуживании».

Cloud Firestore

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

Уровень хранения Cloud Firestore

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

Ключевые диапазоны и разделения

Cloud Firestore — это документально-ориентированная база данных NoSQL. Данные хранятся в документах , которые организованы в иерархии коллекций . Иерархия коллекции и идентификатор документа преобразуются в один ключ для каждого документа. Документы логически хранятся и лексикографически упорядочиваются по этому единственному ключу. Мы используем термин «диапазон ключей» для обозначения лексикографически непрерывного диапазона ключей.

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

Синхронная репликация

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

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

Расположение данных

Cloud Firestore — это бессхемная база данных документов. Однако внутри он размещает данные в основном в двух таблицах в стиле реляционной базы данных на уровне хранения следующим образом:

  • Таблица документов : В этой таблице хранятся документы.
  • Таблица индексов : в этой таблице хранятся записи индекса, которые позволяют эффективно получать результаты и сортировать их по значению индекса.

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

Расположение данных

Один регион против нескольких регионов

При создании базы данных необходимо выбрать регион или несколько регионов .

Единственное региональное местоположение — это определенное географическое местоположение, например us-west1 . Разделения данных базы данных Cloud Firestore имеют реплики в разных зонах выбранного региона, как объяснялось ранее.

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

Дополнительную информацию о местонахождении региона см. в разделе «Местоположения Cloud Firestore .

Один регион против нескольких регионов

Понимание жизни записи в Cloud Firestore

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

Для всех видов записи Cloud Firestore предоставляет свойства ACID (атомарность, согласованность, изоляция и надежность) реляционных баз данных. Cloud Firestore также обеспечивает сериализуемость , что означает, что все транзакции отображаются так, как если бы они выполнялись в последовательном порядке.

Шаги высокого уровня в транзакции записи

Когда клиент Cloud Firestore выполняет запись или фиксирует транзакцию, используя любой из упомянутых ранее методов, внутри это выполняется как транзакция чтения-записи базы данных на уровне хранения. Транзакция позволяет Cloud Firestore предоставлять свойства ACID, упомянутые ранее.

На первом этапе транзакции Cloud Firestore считывает существующий документ и определяет изменения, которые необходимо внести в данные в таблице «Документы».

Это также включает внесение необходимых обновлений в таблицу индексов следующим образом:

  • Поля, добавляемые в документы, требуют соответствующих вставок в таблицу «Индексы».
  • Поля, удаляемые из документов, требуют соответствующего удаления в таблице «Индексы».
  • Поля, которые изменяются в документах, требуют как удаления (для старых значений), так и вставки (для новых значений) в таблицу индексов.

Чтобы вычислить упомянутые ранее мутации, Cloud Firestore считывает конфигурацию индексирования проекта. Конфигурация индексирования хранит информацию об индексах проекта. Cloud Firestore использует два типа индексов: однополевые и составные. Подробное представление об индексах, созданных в Cloud Firestore , см. в разделе Типы индексов в Cloud Firestore .

После расчета мутаций Cloud Firestore собирает их внутри транзакции, а затем фиксирует ее.

Понимание транзакции записи на уровне хранения

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

На следующей диаграмме база данных Cloud Firestore имеет восемь разделений (отмечено 1–8), размещенных на трех разных серверах хранения в одной зоне, и каждое разделение реплицируется в 3 (или более) разных зонах. У каждого раскола есть лидер Паксоса, который может находиться в разных зонах для разных расколов.

<класс диапазона= Разделение базы данных Cloud Firestore">

Рассмотрим базу данных Cloud Firestore , содержащую коллекцию Restaurants , следующим образом:

Коллекция ресторанов

Клиент Cloud Firestore запрашивает следующее изменение документа в коллекции Restaurant , обновляя значение поля priceCategory .

Перейти к документу в коллекции

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

  1. Создайте транзакцию чтения-записи.
  2. Прочтите документ restaurant1 в коллекции Restaurants из таблицы Documents на уровне хранения.
  3. Прочтите индексы документа из таблицы Индексы .
  4. Вычислите мутации, которые необходимо внести в данные. В данном случае имеется пять мутаций:
    • M1: Обновите строку для restaurant1 в таблице документов , чтобы отразить изменение стоимости поля priceCategory .
    • M2 и M3: Удалить ряды для старого значения priceCategory в таблице индексов для нисходящих и восходящих индексов.
    • M4 и M5: вставьте строки для нового значения priceCategory в таблице индексов для спуска и повышения индексов.
  5. Совершить эти мутации.

Клиент хранилища в сервисе Cloud Firestore просматривает разделы, которые владеют ключами рядов, которые должны быть изменены. Давайте рассмотрим случай, когда Split 3 обслуживает M1, а Split 6 обслуживает M2-M5. Существует распределенная транзакция, включающая все эти расколы в качестве участников . Разделы участников также могут включать в себя любой другой раздел, из которого данные были прочитаны ранее как часть транзакции чтения-записи.

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

  1. Клиент хранилища выпускает коммит. Коммит содержит мутации M1-M5.
  2. Сплиты 3 и 6 являются участниками этой транзакции. Один из участников выбирается в качестве координатора , например, Split 3. Задача координатора состоит в том, чтобы убедиться, что транзакция либо совершает, либо прерывает атомно для всех участников.
    • Реплики лидера этих расколов несут ответственность за работу, выполняемую участниками и координаторами.
  3. Каждый участник и координатор управляет алгоритмом Paxos с соответствующими репликами.
    • Лидер управляет алгоритмом Paxos с репликами. Кворум достигается, если большинство копий отвечают с ok to commit ответ лидеру.
    • Затем каждый участник уведомляет координатора, когда они готовы (первая фаза двухфазного коммита). Если какой -либо участник не может совершить транзакцию, вся транзакция aborts .
  4. Как только координатор узнает всех участников, в том числе и сами, подготовлена, он передает результат транзакции accept всем участникам (вторая фаза двухфазного коммита). На этом этапе каждый участник записывает решение о совершении стабильного хранения, а транзакция совершается.
  5. Координатор отвечает на клиента хранения в Cloud Firestore , что транзакция была совершена. Параллельно координатор и все участники применяют мутации к данным.

Совершить жизненный цикл

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

Пишет в мультирегионе

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

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

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

Понять жизнь чтения в Cloud Firestore

Этот раздел углубляется в автономные, нереальные чтения в Cloud Firestore . Внутренне сервер Cloud Firestore обрабатывает большинство этих запросов на двух основных этапах:

  1. ОДИНСКОЕ СКАНИРОВАНИЕ В ТАБЛИЦЕ ИНДЕКСОВ
  2. Поиск точек в таблице документов на основе результата более раннего сканирования
Могут быть определенные запросы, которые требуют меньшей обработки или большей обработки (например, в запросах) в Cloud Firestore .

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

Понять транзакцию чтения в слое хранения

В этом разделе описываются типы чтения и то, как они обрабатываются в уровне хранения в Cloud Firestore .

Сильные чтения

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

Одиночный сплит читайте

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

На этом этапе могут произойти следующие случаи в зависимости от выбранной копии:

  • Читать запрос идет в реплику лидера (зона а).
    • Поскольку лидер всегда в курсе, чтение может продолжаться напрямую.
  • Запрос на чтение переходит в реплику, не являющуюся лидером (например, зона B)
    • Сплит 3 может знать по внутреннему состоянию, что у него достаточно информации, чтобы обслуживать чтение, и разделение делает это.
    • Split 3 не уверен, видел ли он последние данные. Он отправляет лидеру сообщение, чтобы попросить временной метки последней транзакции, которую необходимо применить для обслуживания чтения. Как только эта транзакция применяется, чтение может продолжаться.

Затем Cloud Firestore возвращает ответ на своего клиента.

Многооптатный чтение

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

Устаревший читает

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

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

Избегайте горячих точек

Распределения в Cloud Firestore автоматически разбиваются на более мелкие кусочки, чтобы распространять работу по обслуживанию трафика на большие серверы хранения, когда это необходимо, или когда ключевое пространство расширяется. Разделы, созданные для обработки избыточного трафика, сохраняются в течение ~ 24 часов, даже если трафик исчезает. Таким образом, если существуют повторяющиеся движения трафика, сплиты сохраняются, и при необходимости вводится больше расколов. Эти механизмы помогают базам данных Cloud Firestore в AutoScale при увеличении нагрузки на трафик или размера базы данных. Тем не менее, есть некоторые ограничения, которые следует знать, как объяснено ниже.

Расщепление хранения и нагрузки требует времени, а слишком быстрое увеличение трафика может привести к тому, что высокая задержка или крайний срок превысил ошибки, обычно называемые горячими точками , в то время как служба регулирует. Лучшая практика заключается в распространении операций по ключевым диапазону, одновременно увеличивая трафик на сборе в базе данных с 500 операциями в секунду. После этого постепенного наращивания увеличивайте трафик до 50% каждые пять минут. Этот процесс называется правилом 500/50/5 и позиционирует базу данных для оптимального масштабирования для удовлетворения вашей рабочей нагрузки.

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

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

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

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

Поиск неисправностей

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

Что дальше

,

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

Cloud Firestore - это гибкая, масштабируемая база данных для разработки мобильных устройств, Интернета и сервера от Firebase и Google Cloud . Очень легко начать с Cloud Firestore и написать богатые и мощные приложения.

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

См. Следующие разделы для лучших практик перед архитекцией вашего приложения.

Понять компоненты высокого уровня

На следующей диаграмме показаны компоненты высокого уровня, участвующие в Cloud Firestore .

Компоненты высокого уровня

Cloud Firestore SDK и клиентские библиотеки

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

Google Front End (GFE)

Это инфраструктурная служба, общая для всех облачных сервисов Google. GFE принимает входящие запросы и пересылает их в соответствующую службу Google (сервис Cloud Firestore в этом контексте). Он также предоставляет другие важные функции, включая защиту от отрицания атак на обслуживание.

Cloud Firestore Service

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

Cloud Firestore слой хранения

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

Ключевые диапазоны и расщепления

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

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

Синхронная репликация

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

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

Макет данных

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

  • Таблица документов : документы хранятся в этой таблице.
  • Таблица индексов : Индексные записи, которые позволяют эффективно получить результаты и отсортированные по значению индекса, хранятся в этой таблице.

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

Макет данных

Одиночный регион против мультирегиона

Когда вы создаете базу данных, вы должны выбрать регион или мультирегион .

Единственное региональное местоположение-это конкретное географическое местоположение, как US-WEST1 . Разделы данных базы данных Cloud Firestore имеют реплики в разных зонах в выбранной области, как объяснялось ранее.

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

Для получения дополнительной информации о местах региона см. Места Cloud Firestore .

Одиночный регион против мультирегиона

Понять жизнь записи в Cloud Firestore

Клиент Cloud Firestore может написать данные, создавая, обновляя или удаляя один документ. Запись в один документ требует обновления как документа, так и связанных с ним записей индексов атомно на уровне хранения. Cloud Firestore также поддерживает атомные операции, состоящие из нескольких чтений и/или записей в одном или нескольких документах.

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

Шаги высокого уровня в транзакции записи

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

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

Это также включает в себя необходимые обновления в таблице индексов следующим образом:

  • Поля, которые добавляются в документы, нуждаются в соответствующих вставках в таблице индексов.
  • Поля, которые удаляются из документов, нуждаются в соответствующих удалениях в таблице индексов.
  • Поля, которые изменяются в документах, требуют как удаления (для старых значений), так и вставки (для новых значений) в таблицу индексов.

Чтобы рассчитать мутации, упомянутые ранее, Cloud Firestore считывает конфигурацию индексации для проекта. В конфигурации индексации хранится информация об индексах для проекта. Cloud Firestore использует два типа индексов: однопольное и композитное. Подробное понимание индексов, созданных в Cloud Firestore , см. Типы индексов в Cloud Firestore .

Как только мутации рассчитаны, Cloud Firestore собирает их внутри транзакции, а затем занимается этим.

Понять транзакцию записи в слое хранения

Как обсуждалось ранее, запись в Cloud Firestore включает в себя транзакцию чтения-записи в уровне хранения. В зависимости от макета данных, запись может включать в себя один или несколько расколов, как видно в макете данных .

На следующей диаграмме база данных Cloud Firestore содержит восемь сплит (помеченные 1-8), размещенные на трех различных серверах хранения в одной зоне, и каждое разделение реплицируется в 3 (или более) разных зонах. У каждого разделения есть лидер Paxos, который может быть в другой зоне для разных расщеплений.

<span class = Cloud Firestore Database Split ">

Рассмотрим базу данных Cloud Firestore , в которой есть коллекция Restaurants следующим образом:

Коллекция ресторана

Клиент Cloud Firestore запрашивает следующее изменение в документе в коллекции Restaurant , обновив стоимость поля priceCategory .

Переоборудовать документ в сборе

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

  1. Создайте транзакцию чтения-записи.
  2. Прочитайте документ restaurant1 в коллекции Restaurants из таблицы документов со слоя хранения.
  3. Прочитайте индексы для документа из таблицы индексов .
  4. Вычислите мутации, которые должны быть сделаны для данных. В этом случае есть пять мутаций:
    • M1: Обновите строку для restaurant1 в таблице документов , чтобы отразить изменение стоимости поля priceCategory .
    • M2 и M3: Удалить ряды для старого значения priceCategory в таблице индексов для нисходящих и восходящих индексов.
    • M4 и M5: вставьте строки для нового значения priceCategory в таблице индексов для спуска и повышения индексов.
  5. Совершить эти мутации.

Клиент хранилища в сервисе Cloud Firestore просматривает разделы, которые владеют ключами рядов, которые должны быть изменены. Давайте рассмотрим случай, когда Split 3 обслуживает M1, а Split 6 обслуживает M2-M5. Существует распределенная транзакция, включающая все эти расколы в качестве участников . Разделы участников также могут включать в себя любой другой раздел, из которого данные были прочитаны ранее как часть транзакции чтения-записи.

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

  1. Клиент хранилища выпускает коммит. Коммит содержит мутации M1-M5.
  2. Сплиты 3 и 6 являются участниками этой транзакции. Один из участников выбирается в качестве координатора , например, Split 3. Задача координатора состоит в том, чтобы убедиться, что транзакция либо совершает, либо прерывает атомно для всех участников.
    • Реплики лидера этих расколов несут ответственность за работу, выполняемую участниками и координаторами.
  3. Каждый участник и координатор управляет алгоритмом Paxos с соответствующими репликами.
    • Лидер управляет алгоритмом Paxos с репликами. Кворум достигается, если большинство копий отвечают с ok to commit ответ лидеру.
    • Затем каждый участник уведомляет координатора, когда они готовы (первая фаза двухфазного коммита). Если какой -либо участник не может совершить транзакцию, вся транзакция aborts .
  4. Как только координатор узнает всех участников, в том числе и сами, подготовлена, он передает результат транзакции accept всем участникам (вторая фаза двухфазного коммита). На этом этапе каждый участник записывает решение о совершении стабильного хранения, а транзакция совершается.
  5. Координатор отвечает на клиента хранения в Cloud Firestore , что транзакция была совершена. Параллельно координатор и все участники применяют мутации к данным.

Совершить жизненный цикл

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

Пишет в мультирегионе

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

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

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

Понять жизнь чтения в Cloud Firestore

Этот раздел углубляется в автономные, нереальные чтения в Cloud Firestore . Внутренне сервер Cloud Firestore обрабатывает большинство этих запросов на двух основных этапах:

  1. ОДИНСКОЕ СКАНИРОВАНИЕ В ТАБЛИЦЕ ИНДЕКСОВ
  2. Поиск точек в таблице документов на основе результата более раннего сканирования
Могут быть определенные запросы, которые требуют меньшей обработки или большей обработки (например, в запросах) в Cloud Firestore .

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

Понять транзакцию чтения в слое хранения

В этом разделе описываются типы чтения и то, как они обрабатываются в уровне хранения в Cloud Firestore .

Сильные чтения

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

Одиночный сплит читайте

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

На этом этапе могут произойти следующие случаи в зависимости от выбранной копии:

  • Читать запрос идет в реплику лидера (зона а).
    • Поскольку лидер всегда в курсе, чтение может продолжаться напрямую.
  • Запрос на чтение переходит в реплику, не являющуюся лидером (например, зона B)
    • Сплит 3 может знать по внутреннему состоянию, что у него достаточно информации, чтобы обслуживать чтение, и разделение делает это.
    • Split 3 не уверен, видел ли он последние данные. Он отправляет лидеру сообщение, чтобы попросить временной метки последней транзакции, которую необходимо применить для обслуживания чтения. Как только эта транзакция применяется, чтение может продолжаться.

Затем Cloud Firestore возвращает ответ на своего клиента.

Многооптатный чтение

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

Устаревший читает

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

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

Избегайте горячих точек

Распределения в Cloud Firestore автоматически разбиваются на более мелкие кусочки, чтобы распространять работу по обслуживанию трафика на большие серверы хранения, когда это необходимо, или когда ключевое пространство расширяется. Разделы, созданные для обработки избыточного трафика, сохраняются в течение ~ 24 часов, даже если трафик исчезает. Таким образом, если существуют повторяющиеся движения трафика, сплиты сохраняются, и при необходимости вводится больше расколов. Эти механизмы помогают базам данных Cloud Firestore в AutoScale при увеличении нагрузки на трафик или размера базы данных. Тем не менее, есть некоторые ограничения, которые следует знать, как объяснено ниже.

Расщепление хранения и нагрузки требует времени, а слишком быстрое увеличение трафика может привести к тому, что высокая задержка или крайний срок превысил ошибки, обычно называемые горячими точками , в то время как служба регулирует. Лучшая практика заключается в распространении операций по ключевым диапазону, одновременно увеличивая трафик на сборе в базе данных с 500 операциями в секунду. After this gradual ramp up, increase the traffic by up to 50% every five minutes. This process is called the 500/50/5 rule and positions the database to optimally scale to meet your workload.

Though splits are created automatically with increasing load, Cloud Firestore can split a key range only until it's serving a single document using a dedicated set of replicated storage servers. As a result, high and sustained volumes of concurrent operations on a single document may lead to a hotspot on that document. If you encounter sustained high latencies on a single document, you should consider modifying your data model to split or replicate the data across multiple documents.

Contention errors happen when multiple operations try to read and/or write the same document simultaneously.

Another special case of hotspotting happens when a sequentially increasing/decreasing key is used as the document ID in Cloud Firestore , and there is a considerably high number of operations per second. Creating more splits doesn't help here since the surge of traffic simply moves to the newly created split. Since Cloud Firestore automatically indexes all fields in the document by default, such moving hotspots may also be created on the index space for a document field that contains a sequentially increasing/decreasing value like a timestamp.

Note that by following the practices outlined above, Cloud Firestore can scale to serve arbitrarily large workloads without you having to adjust any configuration.

Поиск неисправностей

Cloud Firestore provides the Key Visualizer as a diagnostic tool designed to analyze usage patterns and troubleshoot hotspotting issues.

What's Next

,

Read this document to make informed decisions on architecting your applications for high performance and reliability. This document includes advanced Cloud Firestore topics. If you're just starting out with Cloud Firestore , see the quickstart guide instead.

Cloud Firestore is a flexible, scalable database for mobile device, web, and server development from Firebase and Google Cloud . It's very easy to get started with Cloud Firestore and write rich and powerful applications.

To make sure that your applications continue to perform well as your database size and traffic increase, it helps to understand the mechanics of reads and writes in the Cloud Firestore backend. You must also understand the interaction of your read and writes with the storage layer and the underlying constraints that may affect performance.

See the following sections for best practices before architecting your application.

Understand the high level components

The following diagram shows the high level components involved in a Cloud Firestore API request.

High level components

Cloud Firestore SDK and client libraries

Cloud Firestore supports SDKs and client libraries for different platforms. While an app can make direct HTTP and RPC calls to the Cloud Firestore API, the client libraries provide a layer of abstraction to simplify API usage and implement best practices. They may also provide additional features such as offline access, caches, and so on.

Google Front End (GFE)

This is an infrastructure service common to all Google cloud services. The GFE accepts incoming requests and forwards them to the relevant Google service ( Cloud Firestore service in this context). It also provides other important functionalities, including protection against Denial of Service attacks.

Cloud Firestore service

The Cloud Firestore service performs checks on the API request, which includes authentication, authorization, quota checks, and security rules, and also manages transactions. This Cloud Firestore service includes a storage client that interacts with the storage layer for the data reads and writes.

Cloud Firestore storage layer

The Cloud Firestore storage layer is responsible for storing both the data and metadata, and the associated database features provided by Cloud Firestore . The following sections describe how data is organized in the Cloud Firestore storage layer and how the system scales. Learning about how data is organized can help you design a scalable data model and better understand the best practices in Cloud Firestore .

Key Ranges and Splits

Cloud Firestore is a NoSQL, document-oriented database. You store data in documents , which are organized in hierarchies of collections . The collection hierarchy and document ID are translated to a single key for each document. Documents are logically stored and ordered lexicographically by this single key. We use the term key range to refer to a lexicographically contiguous range of keys.

A typical Cloud Firestore database is too large to fit on a single physical machine. There are also scenarios where the workload on the data is too heavy for one machine to handle. To handle large workloads, Cloud Firestore partitions the data into separate pieces that can be stored on and served from multiple machines or storage servers . These partitions are made on the database tables in blocks of key ranges called splits.

Synchronous Replication

It is important to note that the database is always being replicated automatically and synchronously. The splits of data have replicas in different zones to keep them available even when a zone becomes inaccessible. Consistent replication to the different copies of the split is managed by the Paxos algorithm for consensus. One replica of each split is elected to act as the Paxos leader, which is responsible for handling writes to that split. The synchronous replication gives you the ability to always be able to read the latest version of data from Cloud Firestore .

The overall result of this is a scalable and highly available system that provides low latencies for both reads and writes, irrespective of heavy workloads and at very large scale.

Data layout

Cloud Firestore is a schemaless document database. However, internally it lays out the data primarily in two relational database-style tables in its storage layer as follows:

  • Documents table: Documents are stored in this table.
  • Indexes table: Index entries that make it possible to get results efficiently and sorted by index value are stored in this table.

The following diagram shows how the tables for a Cloud Firestore database might look like with the splits. The splits are replicated in three different zones and each split has an assigned Paxos leader.

Data layout

Single Region versus Multi-Region

When you create a database, you must select a region or multi-region .

A single regional location is a specific geographic location, like us-west1 . The splits of data of a Cloud Firestore database have replicas in different zones within the selected region, as explained earlier.

A multi-region location consists of a defined set of regions where replicas of the database are stored. In a multi-region deployment of Cloud Firestore , two of the regions have full replicas of the entire data in the database. A third region has a witness replica that does not maintain a full set of data, but participates in replication. By replicating the data between multiple regions, data is available to be written and read even with the loss of an entire region.

For more information about the locations of a region, see Cloud Firestore locations .

Single region versus multi-region

Understand life of a write in Cloud Firestore

A Cloud Firestore client can write data by creating, updating, or deleting a single document. A write to a single document requires updating both the document and its associated index entries atomically in the storage layer. Cloud Firestore also supports atomic operations consisting of multiple reads and/or writes to one or more documents.

For all kinds of writes, Cloud Firestore provides the ACID properties (atomicity, consistency, isolation, and durability) of relational databases. Cloud Firestore also provides serializability , which means that all transactions appear as if executed in a serial order.

High-level steps in a write transaction

When the Cloud Firestore client issues a write or commits a transaction, using any of the methods mentioned earlier, internally this is executed as a database read-write transaction in the storage layer. The transaction enables Cloud Firestore to provide the ACID properties mentioned earlier.

As the first step of a transaction, Cloud Firestore reads the existing document, and determines the mutations to be made to the data in the Documents table.

This also includes making necessary updates to the Indexes table as follows:

  • Fields that are being added to the documents need corresponding inserts in the Indexes table.
  • Fields that are being removed from the documents need corresponding deletes in the Indexes table.
  • Fields that are being modified in the documents, need both deletes (for old values) and inserts (for new values) in the Indexes table.

To calculate the mutations mentioned earlier, Cloud Firestore reads the indexing configuration for the project. The indexing configuration stores information about the indexes for a project. Cloud Firestore uses two types of indexes: single-field and composite. For a detailed understanding of the indexes created in Cloud Firestore , see Index types in Cloud Firestore .

Once the mutations are calculated, Cloud Firestore collects them inside a transaction and then commits it.

Understand a write transaction in the storage layer

As discussed earlier, a write in Cloud Firestore involves a read-write transaction in the storage layer. Depending on the layout of data, a write might involve one or more splits as seen in the data layout .

In the following diagram, the Cloud Firestore database has eight splits (marked 1-8) hosted on three different storage servers in a single zone, and each split is replicated in 3(or more) different zones. Each split has a Paxos leader, which might be in a different zone for different splits.

<span class= Cloud Firestore database split">

Consider a Cloud Firestore database that has the Restaurants collection as follows:

Restaurant collection

The Cloud Firestore client requests the following change to a document in the Restaurant collection by updating the value of the priceCategory field.

Change to a document in collection

The following high-level steps describe what happens as part of the write:

  1. Create a read-write transaction.
  2. Read the restaurant1 document in the Restaurants collection from the Documents table from the storage layer.
  3. Read the indexes for the document from the Indexes table.
  4. Compute the mutations to be made to the data. In this case, there are five mutations:
    • M1: Update the row for restaurant1 in the Documents table to reflect the change in value of the priceCategory field.
    • M2 and M3: Delete the rows for the old value of priceCategory in the Indexes table for descending and ascending indexes.
    • M4 and M5: Insert the rows for the new value of priceCategory in the Indexes table for descending and ascending indexes.
  5. Commit these mutations.

The storage client in the Cloud Firestore service looks up the splits that owns the keys of the rows to be changed. Let's consider a case where Split 3 serves M1, and Split 6 serves M2-M5. There is a distributed transaction, involving all these splits as participants . The participant splits may also include any other split from which data was read earlier as part of the read-write transaction.

The following steps describe what happens as part of the commit:

  1. The storage client issues a commit. The commit contains the mutations M1-M5.
  2. Splits 3 and 6 are the participants in this transaction. One of the participants is chosen as the coordinator , such as Split 3. The job of the coordinator is to make sure the transaction either commits or aborts atomically across all participants.
    • The leader replicas of these splits are responsible for work done by the participants and coordinators.
  3. Each participant and coordinator runs a Paxos algorithm with their respective replicas.
    • The leader runs a Paxos algorithm with the replicas. Quorum is achieved if most of the replicas reply with an ok to commit response to the leader.
    • Each participant then notifies the coordinator when they are prepared (first phase of two-phase commit). If any participant cannot commit the transaction, the whole transaction aborts .
  4. Once the coordinator knows all participants, including itself, are prepared, it communicates the accept transaction outcome to all the participants (second phase of two-phase commit). In this phase, each participant records the commit decision to stable storage and the transaction is committed.
  5. The coordinator responds to the storage client in Cloud Firestore that the transaction has been committed. In parallel, the coordinator and all the participants apply the mutations to the data.

Commit lifecycle

When the Cloud Firestore database is small, it may happen that a single split owns all the keys in the mutations M1-M5. In such a case, there is only one participant in the transaction and the two-phase commit mentioned earlier is not required, thus making the writes faster.

Writes in multi-region

In a multi-region deployment, the spread of replicas across regions increases availability, but comes with a performance cost. The communication between replicas in different regions takes longer round trip times. Hence, the baseline latency for Cloud Firestore operations is slightly more compared to single region deployments.

We configure the replicas in a way that leadership for splits always stays in the primary region. The primary region is the one from which traffic is incoming to the Cloud Firestore server. This decision of leadership reduces the round-trip delay in communication between the storage client in Cloud Firestore and the replica leader (or coordinator for multi-split transactions).

Each write in Cloud Firestore also involves some interaction with the real-time engine in Cloud Firestore . For more information about real-time queries, see Understand real-time queries at scale .

Understand the life of a read in Cloud Firestore

This section delves into standalone, non-realtime reads in Cloud Firestore . Internally, the Cloud Firestore server handles most of these queries in two major stages:

  1. A single range scan over the Indexes table
  2. Point lookups in the Documents table based on the result of the earlier scan
There may be certain queries that require less processing or more processing (for example, IN queries) in Cloud Firestore .

The data reads from the storage layer are internally done by using a database transaction to ensure consistent reads. However, unlike the transactions used for writes, these transactions do not take locks. Instead, they work by choosing a timestamp, then executing all reads at that timestamp. Since they do not acquire locks, they do not block concurrent read-write transactions. To execute this transaction, the storage client in Cloud Firestore specifies a timestamp bound, which tells the storage layer how to choose a read timestamp. The type of timestamp bound chosen by the storage client in Cloud Firestore is determined by the read options for the Read request.

Understand a read transaction in the storage layer

This section describes the types of reads and how they are processed in the storage layer in Cloud Firestore .

Strong reads

By default, Cloud Firestore reads are strongly consistent . This strong consistency means that a Cloud Firestore read returns the latest version of the data that reflects all writes that have been committed up until the start of the read.

Single Split read

The storage client in Cloud Firestore looks up the splits that own the keys of the rows to be read. Let's assume that it needs to do a read from Split 3 from the earlier section . The client sends the read request to the nearest replica to reduce round trip latency.

At this point, the following cases might happen depending on the chosen replica:

  • Read request goes to a leader replica (Zone A).
    • As the leader is always up-to-date, the read can proceed directly.
  • Read request goes to a non-leader replica (such as, Zone B)
    • Split 3 may know by its internal state that it has enough information to serve the read and the split does so.
    • Split 3 is unsure if it has seen the latest data. It sends a message to the leader to ask for the timestamp of the last transaction it needs to apply to serve the read. Once that transaction is applied, the read can proceed.

Cloud Firestore then returns the response to its client.

Multi-split read

In the situation where the reads have to be done from multiple splits, the same mechanism happens across all the splits. Once the data has been returned from all the splits, the storage client in Cloud Firestore combines the results. Cloud Firestore then responds to its client with this data.

Stale reads

Strong reads are the default mode in Cloud Firestore . However, it comes at a cost of potential higher latency due to the communication that may be required with the leader. Often your Cloud Firestore application doesn't need to read the latest version of the data and the functionality works well with data that may be a few seconds stale.

In such a case, the client may opt to receive stale reads by using the read_time read options. In this case, reads are done as the data was at read_time , and the closest replica is highly likely to already have verified it has data at the specified read_time . For noticeably better performance, 15 seconds is a reasonable staleness value. Even for stale reads, rows yielded are consistent with each other.

Avoid hotspots

The splits in Cloud Firestore are automatically broken into smaller pieces to distribute the work of serving traffic to more storage servers when needed or when the key space expands. Splits created to handle excess traffic are retained for around ~24 hours even if the traffic goes away. So if there are recurring traffic spikes, the splits are maintained and more splits are introduced whenever required. These mechanisms help Cloud Firestore databases to autoscale under increasing traffic load or database size. However, there are some limitations to be aware of as explained below.

Splitting storage and load takes time, and ramping up traffic too fast may cause high latency or deadline exceeded errors, commonly referred to as hotspots , while the service adjusts. The best practice is to distribute operations across the key range, while ramping up traffic on a collection in a database with 500 operations per second. After this gradual ramp up, increase the traffic by up to 50% every five minutes. This process is called the 500/50/5 rule and positions the database to optimally scale to meet your workload.

Though splits are created automatically with increasing load, Cloud Firestore can split a key range only until it's serving a single document using a dedicated set of replicated storage servers. As a result, high and sustained volumes of concurrent operations on a single document may lead to a hotspot on that document. If you encounter sustained high latencies on a single document, you should consider modifying your data model to split or replicate the data across multiple documents.

Contention errors happen when multiple operations try to read and/or write the same document simultaneously.

Another special case of hotspotting happens when a sequentially increasing/decreasing key is used as the document ID in Cloud Firestore , and there is a considerably high number of operations per second. Creating more splits doesn't help here since the surge of traffic simply moves to the newly created split. Since Cloud Firestore automatically indexes all fields in the document by default, such moving hotspots may also be created on the index space for a document field that contains a sequentially increasing/decreasing value like a timestamp.

Note that by following the practices outlined above, Cloud Firestore can scale to serve arbitrarily large workloads without you having to adjust any configuration.

Поиск неисправностей

Cloud Firestore provides the Key Visualizer as a diagnostic tool designed to analyze usage patterns and troubleshoot hotspotting issues.

What's Next