Zrozum zapytania w czasie rzeczywistym na dużą skalę, Zrozum zapytania w czasie rzeczywistym na dużą skalę

Przeczytaj ten dokument, aby uzyskać wskazówki dotyczące skalowania aplikacji bezserwerowej powyżej tysięcy operacji na sekundę lub setek tysięcy jednoczesnych użytkowników. Ten dokument zawiera zaawansowane tematy, które pomogą Ci dogłębnie zrozumieć system. Jeśli dopiero zaczynasz korzystać z Cloud Firestore, zamiast tego zapoznaj się z przewodnikiem szybkiego startu .

Cloud Firestore i mobilne/internetowe zestawy SDK Firebase zapewniają potężny model tworzenia aplikacji bezserwerowych, w których kod po stronie klienta bezpośrednio uzyskuje dostęp do bazy danych. Zestawy SDK umożliwiają klientom nasłuchiwanie aktualizacji danych w czasie rzeczywistym. Aktualizacje w czasie rzeczywistym umożliwiają tworzenie responsywnych aplikacji, które nie wymagają infrastruktury serwerowej. Chociaż bardzo łatwo jest coś uruchomić, pomaga zrozumieć ograniczenia w systemach tworzących Cloud Firestore, dzięki czemu Twoja aplikacja bezserwerowa skaluje się i działa dobrze, gdy wzrasta ruch.

Zobacz poniższe sekcje, aby uzyskać porady dotyczące skalowania aplikacji.

Wybierz lokalizację bazy danych blisko użytkowników

Poniższy diagram przedstawia architekturę aplikacji czasu rzeczywistego:

Przykładowa architektura aplikacji czasu rzeczywistego

Gdy aplikacja działająca na urządzeniu użytkownika (mobilnym lub internetowym) nawiązuje połączenie z Cloud Firestore, połączenie jest kierowane do serwera frontendowego Cloud Firestore w tym samym regionie , w którym znajduje się Twoja baza danych. Na przykład, jeśli Twoja baza danych znajduje się w us-east1 , połączenie przechodzi również do frontendu Cloud Firestore, również w us-east1 . Połączenia te są długotrwałe i pozostają otwarte do momentu jawnego zamknięcia przez aplikację. Frontend odczytuje dane z podstawowych systemów pamięci masowej Cloud Firestore.

Odległość między fizyczną lokalizacją użytkownika a lokalizacją bazy danych Cloud Firestore wpływa na opóźnienie doświadczane przez użytkownika. Na przykład użytkownik w Indiach, którego aplikacja komunikuje się z bazą danych w regionie Google Cloud w Ameryce Północnej, może uznać, że działanie jest wolniejsze, a aplikacja mniej płynna, niż gdyby baza danych znajdowała się bliżej, na przykład w Indiach lub w innej części Azji .

Projekt zapewniający niezawodność

Następujące tematy poprawiają lub wpływają na niezawodność Twojej aplikacji:

Włącz tryb offline

Zestawy SDK Firebase zapewniają trwałość danych w trybie offline. Jeśli aplikacja na urządzeniu użytkownika nie może połączyć się z Cloud Firestore, nadal można z niej korzystać, pracując z danymi przechowywanymi lokalnie w pamięci podręcznej. Zapewnia to dostęp do danych nawet wtedy, gdy użytkownicy doświadczają niestabilnych połączeń internetowych lub całkowicie tracą dostęp na kilka godzin lub dni. Aby uzyskać więcej informacji na temat trybu offline, zobacz Włączanie danych offline .

Omówienie automatycznych ponownych prób

Zestawy SDK Firebase zajmują się ponawianiem operacji i przywracaniem zerwanych połączeń. Pomaga to obejść błędy przejściowe spowodowane ponownym uruchomieniem serwerów lub problemami sieciowymi między klientem a bazą danych.

Wybieraj pomiędzy lokalizacjami regionalnymi i wieloregionalnymi

Wybór pomiędzy lokalizacjami regionalnymi i wieloregionalnymi wiąże się z kilkoma kompromisami. Główną różnicą jest sposób replikowania danych. Dzięki temu gwarantujemy dostępność Twojej aplikacji. Instancja obejmująca wiele regionów zapewnia większą niezawodność obsługi i trwałość danych, ale kompromisem jest koszt.

Zrozumienie systemu zapytań w czasie rzeczywistym

Zapytania w czasie rzeczywistym, zwane także odbiornikami migawek, pozwalają aplikacji nasłuchiwać zmian w bazie danych i otrzymywać powiadomienia o niskim opóźnieniu, gdy tylko dane się zmienią. Aplikacja może uzyskać ten sam wynik, okresowo odpytując bazę danych o aktualizacje, ale często jest to wolniejsze, droższe i wymaga więcej kodu. Przykłady konfigurowania zapytań w czasie rzeczywistym i korzystania z nich można znaleźć w artykule Pobieranie aktualizacji w czasie rzeczywistym . W poniższych sekcjach szczegółowo opisano działanie odbiorników migawek i opisano niektóre najlepsze praktyki skalowania zapytań w czasie rzeczywistym przy jednoczesnym zachowaniu wydajności.

Wyobraź sobie dwóch użytkowników, którzy łączą się z Cloud Firestore za pośrednictwem aplikacji do przesyłania wiadomości zbudowanej przy użyciu jednego z mobilnych zestawów SDK.

Klient A zapisuje do bazy danych, aby dodać i zaktualizować dokumenty w kolekcji zwanej chatroom :

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

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

Klient B nasłuchuje aktualizacji w tej samej kolekcji przy użyciu odbiornika migawek. Klient B otrzymuje natychmiastowe powiadomienie za każdym razem, gdy ktoś utworzy nową wiadomość. Poniższy diagram przedstawia architekturę słuchacza migawek:

Architektura połączenia słuchacza migawki

Następująca sekwencja zdarzeń ma miejsce, gdy Klient B łączy słuchacza migawek z bazą danych:

  1. Klient B otwiera połączenie z Cloud Firestore i rejestruje słuchacza, wykonując wywołanie onSnapshot(collection("chatroom")) za pośrednictwem pakietu SDK Firebase. Ten słuchacz może pozostać aktywny przez wiele godzin.
  2. Frontend Cloud Firestore wysyła zapytanie do bazowego systemu pamięci masowej w celu załadowania zbioru danych. Ładuje cały zestaw wyników pasujących dokumentów. Nazywamy to zapytaniem odpytującym . Następnie system ocenia reguły bezpieczeństwa Firebase bazy danych, aby sprawdzić, czy użytkownik może uzyskać dostęp do tych danych. Jeśli użytkownik jest autoryzowany, baza danych zwraca dane użytkownikowi.
  3. Zapytanie klienta B przechodzi następnie do trybu nasłuchiwania . Odbiornik rejestruje się w programie obsługi subskrypcji i czeka na aktualizacje danych.
  4. Klient A wysyła teraz operację zapisu w celu zmodyfikowania dokumentu.
  5. Baza danych zatwierdza zmianę dokumentu w swoim systemie przechowywania.
  6. Transakcyjnie system zatwierdza tę samą aktualizację w wewnętrznym dzienniku zmian. Dziennik zmian ustala ścisłą kolejność zmian w miarę ich pojawiania się.
  7. Dziennik zmian z kolei udostępnia zaktualizowane dane grupie osób zajmujących się obsługą subskrypcji.
  8. Wykonywany jest mechanizm odwrotnego dopasowywania zapytań , aby sprawdzić, czy zaktualizowany dokument pasuje do aktualnie zarejestrowanych odbiorników migawek. W tym przykładzie dokument pasuje do odbiornika migawek Klienta B. Jak sama nazwa wskazuje, o odwrotnym dopasowywaniu zapytań można myśleć jak o zwykłym zapytaniu do bazy danych, ale wykonywanym w odwrotnej kolejności. Zamiast przeszukiwać dokumenty w celu znalezienia tych, które pasują do zapytania, skutecznie przeszukuje zapytania, aby znaleźć te, które pasują do przychodzącego dokumentu. Po znalezieniu dopasowania system przekazuje dany dokument do słuchaczy migawek. Następnie system ocenia reguły bezpieczeństwa Firebase bazy danych, aby mieć pewność, że tylko autoryzowani użytkownicy otrzymają dane.
  9. System przekazuje aktualizację dokumentu do zestawu SDK na urządzeniu klienta B i uruchamia wywołanie zwrotne onSnapshot . Jeśli włączona jest trwałość lokalna, zestaw SDK stosuje aktualizację również do lokalnej pamięci podręcznej.

Kluczowa część skalowalności Cloud Firestore zależy od rozwinięcia dziennika zmian do programów obsługi subskrypcji i serwerów frontendowych. Rozgałęzianie umożliwia efektywną propagację pojedynczej zmiany danych w celu obsługi milionów zapytań w czasie rzeczywistym i podłączonych użytkowników. Uruchamiając wiele replik wszystkich tych komponentów w wielu strefach (lub wielu regionach w przypadku wdrożenia w wielu regionach), Cloud Firestore osiąga wysoką dostępność i skalowalność.

Warto zauważyć, że wszystkie operacje odczytu wykonywane z mobilnych i internetowych zestawów SDK są zgodne z powyższym modelem. Wykonują zapytanie odpytujące, po którym następuje tryb nasłuchiwania, aby zachować gwarancję spójności. Dotyczy to również słuchaczy w czasie rzeczywistym, wywołań mających na celu pobranie dokumentu i zapytań jednorazowych . Można myśleć o pobieraniu pojedynczych dokumentów i jednorazowych zapytaniach jako o krótkotrwałych odbiornikach migawek, które mają podobne ograniczenia dotyczące wydajności.

Zastosuj najlepsze praktyki skalowania zapytań w czasie rzeczywistym

Zastosuj poniższe najlepsze praktyki, aby projektować skalowalne zapytania w czasie rzeczywistym.

Zrozumienie dużego ruchu zapisu w systemie

Ta sekcja pomaga zrozumieć, w jaki sposób system reaguje na rosnącą liczbę żądań zapisu.

Dzienniki zmian Cloud Firestore, które obsługują zapytania w czasie rzeczywistym, automatycznie skalują się w poziomie wraz ze wzrostem ruchu zapisu. Gdy szybkość zapisu bazy danych przekracza możliwości pojedynczego serwera, dziennik zmian jest dzielony na wiele serwerów, a przetwarzanie zapytań zaczyna zużywać dane z wielu programów obsługi subskrypcji zamiast z jednego. Z perspektywy klienta i pakietu SDK wszystko jest przejrzyste i w przypadku podziału nie jest wymagane żadne działanie ze strony aplikacji. Poniższy diagram ilustruje skalowanie zapytań w czasie rzeczywistym:

Architektura rozwinięcia dziennika zmian

Automatyczne skalowanie pozwala zwiększyć ruch zapisu bez ograniczeń, ale w miarę wzrostu ruchu odpowiedź systemu może zająć trochę czasu. Postępuj zgodnie z zaleceniami reguły 5-5-5 , aby uniknąć tworzenia hotspotu zapisu. Key Visualizer to przydatne narzędzie do analizowania hotspotów zapisu.

Wiele aplikacji charakteryzuje się przewidywalnym wzrostem organicznym, który Cloud Firestore może obsłużyć bez żadnych środków ostrożności. Obciążenia wsadowe, takie jak importowanie dużego zestawu danych, mogą jednak zbyt szybko zwiększyć liczbę zapisów. Projektując aplikację, pamiętaj o tym, skąd pochodzi ruch związany z zapisem.

Zrozum, w jaki sposób zapisy i odczyty współdziałają ze sobą

Można myśleć o systemie zapytań w czasie rzeczywistym jak o potoku łączącym operacje zapisu z czytnikami. Za każdym razem, gdy dokument jest tworzony, aktualizowany lub usuwany, zmiana jest propagowana z systemu przechowywania do aktualnie zarejestrowanych słuchaczy. Struktura dziennika zmian Cloud Firestore gwarantuje silną spójność, co oznacza, że ​​Twoja aplikacja nigdy nie otrzyma powiadomień o aktualizacjach, które są nieprawidłowo ustawione w porównaniu z momentem, w którym baza danych zatwierdziła zmiany danych. Upraszcza to tworzenie aplikacji, usuwając przypadki brzegowe dotyczące spójności danych.

Ten połączony potok oznacza, że ​​operacja zapisu powodująca występowanie punktów aktywnych lub rywalizację o blokady może negatywnie wpłynąć na operacje odczytu. Gdy operacje zapisu nie powiodą się lub wystąpią ograniczenia, odczyt może zostać zatrzymany w oczekiwaniu na spójne dane z dziennika zmian. Jeśli tak się stanie w Twojej aplikacji, możesz zobaczyć zarówno powolne operacje zapisu, jak i skorelowane długie czasy odpowiedzi na zapytania. Unikanie gorących punktów jest kluczem do uniknięcia tego problemu.

Przechowuj dokumenty i operacje zapisu na małą skalę

Podczas tworzenia aplikacji za pomocą odbiorników migawek zazwyczaj chcesz, aby użytkownicy szybko dowiadywali się o zmianach danych. Aby to osiągnąć, staraj się, aby wszystko było małe. System może bardzo szybko przepuszczać przez system małe dokumenty zawierające dziesiątki pól. Większe dokumenty zawierające setki pól i duże dane wymagają więcej czasu na przetwarzanie.

Podobnie preferuj krótkie, szybkie operacje zatwierdzania i zapisu, aby utrzymać niskie opóźnienia. Duże partie mogą zapewnić większą przepustowość z punktu widzenia autora, ale w rzeczywistości mogą wydłużyć czas powiadamiania dla odbiorników migawek. Jest to często sprzeczne z intuicją w porównaniu z używaniem innych systemów baz danych, w których można zastosować przetwarzanie wsadowe w celu poprawy wydajności.

Używaj skutecznych słuchaczy

Wraz ze wzrostem szybkości zapisu w bazie danych Cloud Firestore dzieli przetwarzanie danych na wiele serwerów. Algorytm fragmentowania Cloud Firestore próbuje umieścić dane z tej samej kolekcji lub grupy kolekcji na tym samym serwerze dziennika zmian. System stara się zmaksymalizować możliwą przepustowość zapisu, utrzymując jednocześnie liczbę serwerów zaangażowanych w przetwarzanie zapytania na jak najniższym poziomie.

Jednak pewne wzorce mogą nadal prowadzić do nieoptymalnego zachowania odbiorników migawek. Na przykład, jeśli aplikacja przechowuje większość danych w jednym dużym zbiorze, słuchacz może potrzebować połączenia z wieloma serwerami, aby otrzymać wszystkie potrzebne dane. Dzieje się tak nawet wtedy, gdy zastosujesz filtr zapytań. Łączenie się z wieloma serwerami zwiększa ryzyko wolniejszych odpowiedzi.

Aby uniknąć wolniejszych odpowiedzi, zaprojektuj schemat i aplikację tak, aby system mógł obsługiwać słuchaczy bez konieczności przechodzenia do wielu różnych serwerów. Najlepszym rozwiązaniem może być podzielenie danych na mniejsze kolekcje z mniejszą szybkością zapisu.

Przypomina to myślenie o zapytaniach wydajnościowych w relacyjnej bazie danych, które wymagają pełnego przeskanowania tabeli. W relacyjnej bazie danych zapytanie wymagające pełnego przeskanowania tabeli jest odpowiednikiem odbiornika migawek, który obserwuje kolekcję o dużym natężeniu ruchu. Może działać wolniej w porównaniu z zapytaniem, które baza danych może obsłużyć przy użyciu bardziej szczegółowego indeksu. Zapytanie z bardziej szczegółowym indeksem przypomina odbiornik migawek, który obserwuje pojedynczy dokument lub kolekcję, która zmienia się rzadziej. Powinieneś przetestować swoją aplikację, aby najlepiej zrozumieć zachowanie i potrzeby swojego przypadku użycia.

Utrzymuj zapytania odpytywania szybko

Inną kluczową częścią responsywnych zapytań w czasie rzeczywistym jest upewnienie się, że zapytanie odpytujące w celu załadowania danych jest szybkie i wydajne. Przy pierwszym połączeniu nowego odbiornika migawek odbiornik musi załadować cały zestaw wyników i wysłać go do urządzenia użytkownika. Powolne zapytania powodują, że aplikacja jest mniej responsywna. Obejmuje to na przykład zapytania próbujące odczytać wiele dokumentów lub zapytania, które nie korzystają z odpowiednich indeksów.

W pewnych okolicznościach słuchacz może również powrócić ze stanu nasłuchiwania do stanu odpytywania. Dzieje się to automatycznie i jest niewidoczne dla zestawów SDK i aplikacji. Następujące warunki mogą wywołać stan odpytywania:

  • System ponownie równoważy dziennik zmian ze względu na zmiany obciążenia.
  • Hotspoty powodują nieudane lub opóźnione zapisy do bazy danych.
  • Przejściowe ponowne uruchomienie serwera tymczasowo wpływa na odbiorniki.

Jeśli zapytania sondujące są wystarczająco szybkie, stan sondowania staje się przezroczysty dla użytkowników aplikacji.

Preferuj długowiecznych słuchaczy

Otwieranie i utrzymywanie słuchaczy przy życiu tak długo, jak to możliwe, jest często najbardziej opłacalnym sposobem na zbudowanie aplikacji korzystającej z Cloud Firestore. Korzystając z Cloud Firestore, płacisz za dokumenty zwrócone do aplikacji, a nie za utrzymywanie otwartego połączenia. Długowieczny odbiornik migawek odczytuje tylko te dane, których potrzebuje do obsługi zapytania przez cały okres jego istnienia. Obejmuje to wstępną operację odpytywania, po której następują powiadomienia w przypadku faktycznej zmiany danych. Z drugiej strony zapytania jednorazowe ponownie odczytują dane, które mogły nie ulec zmianie od czasu ostatniego wykonania zapytania przez aplikację.

W przypadkach, gdy aplikacja musi zużywać dużą ilość danych, odbiorniki migawek mogą nie być odpowiednie. Na przykład, jeśli w danym przypadku przez połączenie przez dłuższy czas przesyłanych jest wiele dokumentów na sekundę, lepszym rozwiązaniem może być wybranie jednorazowych zapytań uruchamianych z niższą częstotliwością.

Co dalej