Sprawdzone metody dotyczące Cloud Firestore

Podczas tworzenia aplikacji korzystającej z funkcji Cloud Firestore możesz skorzystać z wymienionych tutaj sprawdzonych metod.

Lokalizacja bazy danych

Podczas tworzenia instancji bazy danych wybierz lokalizację bazy danych najbliższą użytkownikom i zasobom obliczeniowym. Dalekie skoki sieciowe są bardziej podatne na błędy i zwiększają opóźnienie zapytań.

Aby zmaksymalizować dostępność i trwałość aplikacji, wybierz lokalizację w wielu regionach i umieść kluczowe zasoby obliczeniowe w co najmniej 2 regionach.

Wybierz lokalizację regionalną, aby obniżyć koszty, zmniejszyć opóźnienia zapisu (jeśli Twoja aplikacja jest wrażliwa na opóźnienia) lub zlokalizować zasoby w tym samym regionie co inne zasoby GCP.

Identyfikatory dokumentów

  • Unikaj identyfikatorów dokumentu ....
  • Unikaj stosowania / ukośnika w dół w identyfikatorach dokumentów.
  • Nie używaj monotonicznie rosnących identyfikatorów dokumentów, takich jak:

    • Customer1, Customer2, Customer3, ...
    • Product 1, Product 2, Product 3, ...

    Takie identyfikatory sekwencyjne mogą prowadzić do punktów krytycznych, które wpływają na opóźnienia.

Nazwy pól

  • Unikaj tych znaków w nazwach pól, ponieważ wymagają one dodatkowego ucieczki:

    • . okres
    • [ nawias otwierający
    • ] nawias zamykający
    • * gwiazdka
    • ` nawias kwadratowy

Indeksy

Ograniczenie opóźnienia zapisu

Głównym czynnikiem wpływającym na opóźnienie zapisu jest rozgałęzienie indeksu. Sprawdzone metody zmniejszania rozgałęzienia indeksu:

  • Ustaw wykluczenia indeksu na poziomie kolekcji. Domyślnie można wyłączyć indeksowanie malejąco-rosnąco i tablic. Usunięcie nieużywanych wartości indeksowanych spowoduje też obniżenie kosztów pamięci.

  • Zmniejsz liczbę dokumentów w transakcji. W przypadku zapisywania dużej liczby dokumentów rozważ użycie zbiorczego narzędzia do zapisywania zamiast atomistycznego narzędzia do zapisywania wsadów.

Wykluczenia indeksu

W przypadku większości aplikacji możesz polegać na automatycznym indeksowaniu oraz linkach w wiadomościach o błędach, aby zarządzać indeksami. Możesz jednak dodać wyjątki dotyczące pojedynczego pola w tych przypadkach:

Zgłoszenie Opis
Duże pola ciągu znaków

Jeśli masz pole ciągu znaków, które często zawiera długie ciągi znaków, których nie używasz do wykonywania zapytań, możesz obniżyć koszty przechowywania, wykluczając to pole z indeksowania.

wysokie szybkości zapisu w kolekcji zawierającej dokumenty z wartościami sekwencyjnymi.

Jeśli indeksujesz pole, które wzrasta lub maleje sekwencyjnie między dokumentami w kolekcji, np. sygnaturę czasową, maksymalna szybkość zapisu do kolekcji wynosi 500 operacji na sekundę. Jeśli nie wysyłasz zapytań na podstawie pola o wartościach sekwencyjnych, możesz wyłączyć indeksowanie tego pola, aby ominąć ten limit.

W przypadku IoT o wysokiej szybkości zapisu kolekcja zawierająca dokumenty z polem z polem sygnatury czasowej może zbliżyć się do limitu 500 zapiszów na sekundę.

Pola TTL

Jeśli używasz zasad dotyczących czasu życia danych (TTL), pamiętaj, że pole TTL musi zawierać sygnaturę czasową. Indeksowanie w przypadku pól TTL jest domyślnie włączone i może wpływać na wydajność przy większych natężeniach ruchu. Najlepiej jest dodać wykluczenia pojedynczych pól dla pól TTL.

Duże tablice lub pola mapowania

Duże pola tablic lub map mogą zbliżać się do limitu 40 tys. wpisów indeksu na dokument. Jeśli nie wysyłasz zapytania na podstawie dużego pola tablicowego lub pola mapy, wyklucz je z indeksowania.

Operacje odczytu i zapisu

  • Dokładna maksymalna szybkość, z jaką aplikacja może aktualizować pojedynczy dokument, zależy w dużym stopniu od obciążenia. Więcej informacji znajdziesz w artykule Aktualizacja pojedynczego dokumentu.

  • W miarę możliwości używaj wywołań asynchronicznych zamiast synchronicznych. Wywołania asynchroniczne minimalizują wpływ opóźnień. Weź pod uwagę na przykład aplikację, która potrzebuje wyniku wyszukiwania dokumentu i wyników zapytania, zanim zwróci odpowiedź. Jeśli wyszukiwanie i zapytanie nie są zależne od danych, nie musisz czekać synchronicznie na zakończenie wyszukiwania przed rozpoczęciem wykonywania zapytania.

  • Nie używaj przesunięć. Zamiast tego używaj kursorów. Użycie przesunięcia pozwala uniknąć zwrócenia pominiętych dokumentów do aplikacji, ale te dokumenty są nadal pobierane wewnętrznie. Pomijane dokumenty wpływają na opóźnienie zapytania, a Twoja aplikacja jest obciążana za operacje odczytu wymagane do ich pobrania.

Powtórzenia transakcji

Pakiety SDK i biblioteki klienta Cloud Firestore automatycznie powtarzają nieudane transakcje, aby poradzić sobie z przejściowymi błędami. Jeśli Twoja aplikacja uzyskuje dostęp do usługi Cloud Firestore bezpośrednio za pomocą interfejsów API REST lub RPC zamiast za pomocą pakietu SDK, powinna implementować ponowne próby transakcji w celu zwiększenia niezawodności.

Aktualizacje w czasie rzeczywistym

Sprawdzone metody dotyczące aktualizacji w czasie rzeczywistym znajdziesz w artykule Zrozumienie zapytań w czasie rzeczywistym na dużą skalę.

Projektowanie z myślą o skalowaniu

Poniższe sprawdzone metody opisują, jak unikać sytuacji, które mogą powodować problemy z konfliktami.

Aktualizacje pojedynczego dokumentu

Podczas projektowania aplikacji zastanów się nad tym, jak szybko aplikacja aktualizuje pojedyncze dokumenty. Najlepszym sposobem na określenie wydajności zbioru zadań jest przeprowadzenie testu obciążeniowego. Dokładna maksymalna szybkość, z jaką aplikacja może aktualizować pojedynczy dokument, zależy w dużej mierze od obciążenia. Czynniki te to m.in. szybkość zapisu, współzawodnictwo między żądaniami i liczba indeksów, których dotyczy problem.

Operacja zapisu dokumentu aktualizuje dokument i wszystkie powiązane indeksy, a Cloud Firestore synchronicznie stosuje operację zapisu na większości replik. Przy wystarczająco wysokich szybkościach zapisu baza danych zacznie napotykać na konflikty, zwiększone opóźnienia lub inne błędy.

wysokie wskaźniki odczytu, zapisu i usuwania w wąskim zakresie dokumentów;

Unikaj wysokich współczynników odczytu i zapisu, aby zamykać dokumenty według kolejności alfabetycznej. W przeciwnym razie aplikacja może generować błędy kolizji. Ten problem nazywa się „hotspotting”. Aplikacja może mieć problemy z hotspottingiem, jeśli:

  • Tworzy nowe dokumenty z bardzo dużą częstotliwością i przypisuje im monotonicznie rosnące identyfikatory.

    Cloud Firestore przypisuje identyfikatory dokumentów za pomocą algorytmu rozpraszania. Jeśli tworzysz nowe dokumenty za pomocą automatycznych identyfikatorów dokumentów, nie powinno dojść do zjawiska hotspottingu podczas zapisywania.

  • Tworzy nowe dokumenty z dużą częstotliwością w kolekcji z niewielką liczbą dokumentów.

  • Tworzy nowe dokumenty z monotonicznie rosnącym polem, takim jak sygnatura czasowa, z bardzo wysoką częstotliwością.

  • usuwa dokumenty z kolekcji z dużą częstotliwością.

  • Zapisywanie danych w bazie danych z bardzo dużą częstotliwością bez stopniowego zwiększania natężenia ruchu.

Unikaj pomijania usuniętych danych

Unikaj zapytań, które pomijają niedawno usunięte dane. Jeśli pierwsze wyniki zapytania zostały niedawno usunięte, zapytanie może pominąć dużą liczbę wpisów w indeksie.

Przykładem obciążenia, które może wymagać pominięcia dużej ilości usuniętych danych, jest obciążenie, które próbuje znaleźć najstarsze elementy pracy w kolejce. Zapytanie może wyglądać tak:

docs = db.collection('WorkItems').order_by('created').limit(100)
delete_batch = db.batch()
for doc in docs.stream():
  finish_work(doc)
  delete_batch.delete(doc.reference)
delete_batch.commit()

Za każdym razem, gdy to zapytanie jest wykonywane, skanuje ono wpisy indeksu w polu created w przypadku ostatnio usuniętych dokumentów. To spowalnia zapytania.

Aby zwiększyć skuteczność, użyj metody start_at, aby znaleźć najlepsze miejsce na rozpoczęcie. Przykład:

completed_items = db.collection('CompletionStats').document('all stats').get()
docs = db.collection('WorkItems').start_at(
    {'created': completed_items.get('last_completed')}).order_by(
        'created').limit(100)
delete_batch = db.batch()
last_completed = None
for doc in docs.stream():
  finish_work(doc)
  delete_batch.delete(doc.reference)
  last_completed = doc.get('created')

if last_completed:
  delete_batch.update(completed_items.reference,
                      {'last_completed': last_completed})
  delete_batch.commit()

UWAGA: przykład powyżej używa pola monotonicznie rosnącego, które jest nieodpowiednim wzorcem w przypadku wysokich szybkości zapisu.

Zwiększanie natężenia ruchu

Należy stopniowo zwiększać ruch w przypadku nowych kolekcji lub dokumentów o zbliżonej kolejności alfabetycznej, aby Cloud Firestore miały wystarczająco dużo czasu na przygotowanie dokumentów na potrzeby zwiększonego ruchu. Zalecamy rozpoczęcie od maksymalnie 500 operacji na sekundę w przypadku nowej kolekcji, a potem zwiększanie ruchu o 50% co 5 minut. Podobnie możesz zwiększyć ruch zapisu, ale pamiętaj o Cloud Firestore standardowych limitach. Upewnij się, że operacje są rozłożone stosunkowo równomiernie w całym zakresie klucza. Nazywa się to regułą „500/50/5”.

Przenoszenie ruchu do nowej kolekcji

Stopniowe zwiększanie jest szczególnie ważne, jeśli migrujesz ruch w aplikacji z jednego zbioru do drugiego. Prostym sposobem na przeprowadzenie tej migracji jest odczytanie danych ze starej kolekcji, a jeśli dokumentu tam nie ma, to z nowej kolekcji. Może to jednak spowodować nagły wzrost ruchu do dokumentów o zbliżonej kolejności alfabetycznej w nowej kolekcji. Cloud Firestoremoże nie być w stanie efektywnie przygotować nowej kolekcji na zwiększony ruch, zwłaszcza jeśli zawiera ona niewiele dokumentów.

Podobny problem może wystąpić, jeśli zmienisz identyfikatory wielu dokumentów w tej samej kolekcji.

Najlepsza strategia migracji ruchu do nowej kolekcji zależy od modelu danych. Poniżej przedstawiamy przykładową strategię, która nosi nazwę czytanie równoległe. Musisz ustalić, czy ta strategia jest skuteczna w przypadku Twoich danych. Ważnym czynnikiem jest wpływ kosztów operacji równoległych na migrację.

Czytanie równoległe

Aby zastosować równoległe odczyty podczas przenoszenia ruchu do nowej kolekcji, najpierw odczytaj dane ze starej kolekcji. Jeśli dokumentu brakuje, odczytaj go z nowej kolekcji. Wysoka częstotliwość odczytu nieistniejących dokumentów może prowadzić do wychwycenia, dlatego stopniowo zwiększaj obciążenie nowej kolekcji. Lepszą strategią jest skopiowanie starego dokumentu do nowej kolekcji, a potem usunięcie starego dokumentu. stopniowo zwiększać liczbę równoczesnych odczytów, aby mieć pewność, że Cloud Firestore będzie w stanie obsłużyć ruch w nowej kolekcji.

Możliwą strategią stopniowego zwiększania liczby odczytów lub zapisów w nowej kolekcji jest użycie deterministycznego hasha identyfikatora użytkownika w celu wybrania losowego odsetka użytkowników próbujących zapisać nowe dokumenty. Upewnij się, że wynik hasha identyfikatora użytkownika nie jest zafałszowany przez funkcję ani zachowanie użytkownika.

W międzyczasie uruchom zadanie zbiorcze, które skopiuje wszystkie dane ze starych dokumentów do nowej kolekcji. Twoje zadanie zbiorcze powinno unikać zapisywania sekwencyjnych identyfikatorów dokumentów, aby zapobiegać tworzeniu wąskich gardeł. Po zakończeniu zadania zbiorczego możesz odczytywać dane tylko z nowej kolekcji.

Ulepszeniem tej strategii jest przenoszenie małych grup użytkowników naraz. Dodaj do dokumentu użytkownika pole, które będzie śledzić stan migracji tego użytkownika. Wybierz grupę użytkowników do przeniesienia na podstawie haszu identyfikatora użytkownika. Użyj zadania zbiorczego do przeniesienia dokumentów dla tego zbioru użytkowników i użyj równoległych odczytów w przypadku użytkowników w trakcie migracji.

Pamiętaj, że nie możesz łatwo cofnąć zmian, chyba że w trakcie migracji wykonasz zapis podwójny zarówno starych, jak i nowych elementów. Spowoduje to zwiększenie poniesionych kosztówCloud Firestore.

Prywatność

  • Nie przechowuj informacji poufnych w identyfikatorze projektu Cloud. Identyfikator projektu Cloud może być przechowywany dłużej niż czas trwania projektu.
  • Zgodnie ze sprawdzoną metodą zgodności z zasadami dotyczącymi danych zalecamy, aby nie przechowywać poufnych informacji w nazwach dokumentów i nazwach pól dokumentów.

Zapobieganie nieautoryzowanemu dostępowi

Zapobiegaj nieautoryzowanym operacjom w bazie danych za pomocą Cloud Firestore Security Rules. Dzięki regułom możesz np. uniknąć sytuacji, w której złośliwy użytkownik wielokrotnie pobiera całą Twoją bazę danych.

Dowiedz się więcej o używaniu Cloud Firestore Security Rules.