Podczas tworzenia aplikacji korzystającej z Cloud Firestore możesz używać podanych tu sprawdzonych metod jako szybkiego odniesienia.
Lokalizacja bazy danych
Podczas tworzenia instancji bazy danych wybierz lokalizację bazy danych najbliższą użytkownikom i zasobom obliczeniowym. Odległe przeskoki sieciowe są bardziej podatne na błędy i zwiększają opóźnienie zapytania.
Aby zmaksymalizować dostępność i trwałość aplikacji, wybierz lokalizację obejmującą wiele regionów i umieść krytyczne 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 kolokować ją z innymi zasobami GCP.
Identyfikatory dokumentów
- Unikaj identyfikatorów dokumentów
.
i..
. - Unikaj używania ukośników
/
w identyfikatorach dokumentów. Nie używaj identyfikatorów dokumentów, które rosną monotonicznie, np.:
Customer1
,Customer2
,Customer3
, ...Product 1
,Product 2
,Product 3
, ...
Takie sekwencyjne identyfikatory mogą prowadzić do punktów krytycznych, które wpływają na opóźnienie.
Nazwy pól
Unikaj w nazwach pól tych znaków, ponieważ wymagają one dodatkowego użycia symbolu zmieniającego znaczenie:
.
kropka[
nawias otwierający]
prawy nawias*
gwiazdka`
grawis
Indeksy
Skracanie czasu oczekiwania na zapis
Głównym czynnikiem wpływającym na czas oczekiwania na zapis jest rozgałęzienie indeksu. Sprawdzone metody ograniczania rozgałęzienia indeksu:
Ustaw wykluczenia indeksów na poziomie kolekcji. Prostym domyślnym ustawieniem jest wyłączenie indeksowania malejącego i tablicowego. Usunięcie nieużywanych wartości indeksowanych obniży też koszty pamięci.
Zmniejsz liczbę dokumentów w transakcji. Jeśli chcesz zapisać dużą liczbę dokumentów, użyj narzędzia do zapisu zbiorczego zamiast narzędzia do zapisu atomowego.
Wykluczenia indeksu
W przypadku większości aplikacji możesz zarządzać indeksami, korzystając z automatycznego indeksowania i linków do komunikatów o błędach. Możesz jednak dodać wyjątki dotyczące pojedynczych pól w tych przypadkach:
Zgłoszenie | Opis |
---|---|
Duże pola ciągów znaków | Jeśli masz pole tekstowe, które często zawiera długie wartości tekstowe, których nie używasz do wysyłania zapytań, możesz obniżyć koszty przechowywania, wyłączając indeksowanie tego pola. |
Wysokie szybkości zapisu w kolekcji zawierającej dokumenty z wartościami sekwencyjnymi | Jeśli indeksujesz pole, którego wartość rośnie lub maleje sekwencyjnie między dokumentami w kolekcji, np. sygnaturę czasową, maksymalna szybkość zapisu w kolekcji wynosi 500 operacji zapisu na sekundę. Jeśli nie wysyłasz zapytań na podstawie pola z wartościami sekwencyjnymi, możesz wyłączyć indeksowanie tego pola, aby ominąć ten limit. W przypadku zastosowań IoT z wysoką częstotliwością zapisu, np. w kolekcji zawierającej dokumenty z polem sygnatury czasowej, można zbliżyć się do limitu 500 zapisów na sekundę. |
Pola TTL |
Jeśli używasz zasad TTL (czasu życia), pamiętaj, że pole TTL musi zawierać sygnaturę czasową. Indeksowanie pól TTL jest domyślnie włączone i może wpływać na wydajność przy wyższym natężeniu ruchu. Najlepiej jest dodać wykluczenia pojedynczych pól dla pól TTL. |
Pola dużych tablic lub map | Duże pola tablicy lub mapy mogą zbliżać się do limitu 40 000 wpisów indeksu na dokument. Jeśli nie wysyłasz zapytań na podstawie dużej tablicy lub pola mapy, wyłącz indeksowanie. |
Operacje odczytu i zapisu
Dokładna maksymalna częstotliwość aktualizowania pojedynczego dokumentu przez aplikację zależy w dużej mierze od zbioru zadań. Więcej informacji znajdziesz w artykule Aktualizacje pojedynczego dokumentu.
W miarę możliwości używaj wywołań asynchronicznych zamiast synchronicznych. Wywołania asynchroniczne minimalizują wpływ na czas oczekiwania. Rozważmy na przykład aplikację, która przed wygenerowaniem odpowiedzi potrzebuje wyniku wyszukiwania dokumentu i wyników zapytania. Jeśli wyszukiwanie i zapytanie nie są od siebie zależne, nie musisz synchronicznie czekać na zakończenie wyszukiwania przed rozpoczęciem zapytania.
Nie używaj przesunięć. Zamiast tego używaj kursorów. Użycie przesunięcia tylko zapobiega zwracaniu pominiętych dokumentów do aplikacji, ale te dokumenty są nadal pobierane wewnętrznie. Pominięte dokumenty wpływają na czas oczekiwania na zapytanie, a za operacje odczytu wymagane do ich pobrania naliczane są opłaty.
Ponawianie transakcji
Cloud Firestore Pakiety SDK i biblioteki klienta automatycznie ponawiają nieudane transakcje, aby poradzić sobie z przejściowymi błędami. Jeśli Twoja aplikacja uzyskuje dostęp do Cloud Firestore bezpośrednio za pomocą interfejsów REST lub RPC zamiast za pomocą pakietu SDK, powinna implementować ponawianie transakcji, aby zwiększyć niezawodność.
Aktualizacje w czasie rzeczywistym
Sprawdzone metody związane z aktualizacjami 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 powodują problemy z konkurencją.
Aktualizacje pojedynczego dokumentu
Podczas projektowania aplikacji zastanów się, jak szybko aktualizuje ona 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 obejmują szybkość zapisu, rywalizację między żądaniami i liczbę indeksów, których dotyczą problemy.
Operacja zapisu dokumentu aktualizuje dokument i wszystkie powiązane indeksy oraz Cloud Firestoresynchronicznie stosuje operację zapisu w kworum replik. Przy wystarczająco wysokich szybkościach zapisu baza danych zacznie napotykać konflikty, większe opóźnienia lub inne błędy.
wysokie wskaźniki odczytu, zapisu i usuwania w wąskim zakresie dokumentów;
Unikaj wysokich wskaźników odczytu lub zapisu w przypadku dokumentów bliskich sobie leksykograficznie, ponieważ w przeciwnym razie w aplikacji wystąpią błędy związane z konkurencją. Ten problem jest znany jako hotspotting. Może wystąpić, jeśli aplikacja wykonuje dowolną z tych czynności:
Tworzy nowe dokumenty z bardzo dużą częstotliwością i przydziela im własne identyfikatory, które rosną monotonicznie.
Cloud Firestore przydziela identyfikatory dokumentów za pomocą algorytmu rozproszonego. Jeśli tworzysz nowe dokumenty za pomocą automatycznych identyfikatorów dokumentów, nie powinno wystąpić zjawisko hotspottingu podczas zapisywania.
Tworzy nowe dokumenty z dużą częstotliwością w kolekcji z niewielką liczbą dokumentów.
Tworzy nowe dokumenty z polem o wartości rosnącej monotonicznie, np. sygnaturą czasową, z bardzo dużą częstotliwością.
Usuwa dokumenty z kolekcji z dużą szybkością.
zapisuje dane w bazie danych z bardzo dużą szybkością, nie zwiększając stopniowo ruchu;
Unikaj pomijania usuniętych danych
Unikaj zapytań, które pomijają niedawno usunięte dane. Zapytanie może pominąć dużą liczbę wpisów w indeksie, jeśli wczesne wyniki zapytania zostały niedawno usunięte.
Przykładem obciążenia, które może musieć pominąć wiele usuniętych danych, jest obciążenie próbujące 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 uruchamiane, skanuje wpisy indeksu dla pola created
w przypadku ostatnio usuniętych dokumentów. Spowalnia to 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: w przykładzie powyżej użyto pola, którego wartość rośnie monotonicznie, co jest niezalecanym wzorcem w przypadku dużej liczby operacji zapisu.
Zwiększanie ruchu
Ruch do nowych kolekcji lub dokumentów o podobnych nazwach należy zwiększać stopniowo, aby dać Cloud Firestore wystarczająco dużo czasu na przygotowanie dokumentów na większy ruch. Zalecamy rozpoczęcie od maksymalnie 500 operacji na sekundę w przypadku nowej kolekcji, a następnie zwiększanie ruchu o 50% co 5 minut. Podobnie możesz zwiększyć ruch związany z zapisem, ale pamiętaj o Cloud Firestorestandardowych limitach. Upewnij się, że operacje są rozłożone w miarę równomiernie w całym zakresie kluczy. Jest to tak zwana zasada „500/50/5”.
Przenoszenie ruchu do nowej kolekcji
Stopniowe zwiększanie ma szczególne znaczenie, jeśli przenosisz ruch z aplikacji z jednej kolekcji do drugiej. Prostym sposobem na przeprowadzenie tej migracji jest odczytanie danych ze starej kolekcji, a jeśli dokument nie istnieje, odczytanie go z nowej kolekcji. Może to jednak spowodować nagły wzrost natężenia ruchu w przypadku dokumentów w nowej kolekcji, które są bliskie leksykograficznie. Cloud Firestore może nie być w stanie skutecznie przygotować nowego zbioru na zwiększony ruch, zwłaszcza jeśli zawiera on niewiele dokumentów.
Podobny problem może wystąpić, jeśli zmienisz identyfikatory wielu dokumentów w tej samej kolekcji.
Najlepsza strategia przenoszenia ruchu do nowej kolekcji zależy od modelu danych. Poniżej znajdziesz przykład strategii znanej jako czytanie równoległe. Musisz określić, czy ta strategia jest skuteczna w przypadku Twoich danych. Ważnym czynnikiem będzie wpływ kosztów operacji równoległych na migrację.
Czytanie równoległe
Aby wdrożyć odczyty równoległe podczas przenoszenia ruchu do nowej kolekcji, najpierw odczytaj dane ze starej kolekcji. Jeśli dokumentu nie ma, odczytaj go z nowej kolekcji. Wysoki odsetek odczytów nieistniejących dokumentów może prowadzić do tworzenia się hotspotów, dlatego pamiętaj, aby stopniowo zwiększać obciążenie nowej kolekcji. Lepszym rozwiązaniem jest skopiowanie starego dokumentu do nowej kolekcji, a następnie usunięcie starego dokumentu. Stopniowo zwiększaj liczbę odczytów równoległych, aby mieć pewność, że Cloud Firestore poradzi sobie z ruchem kierowanym do nowej kolekcji.
Możliwa strategia stopniowego zwiększania liczby odczytów lub zapisów w nowej kolekcji polega na użyciu deterministycznego haszu identyfikatora użytkownika do wybrania losowego odsetka użytkowników, którzy próbują zapisać nowe dokumenty. Upewnij się, że wynik haszowania identyfikatora użytkownika nie jest zniekształcony przez Twoją funkcję ani przez zachowanie użytkownika.
W międzyczasie uruchom zadanie wsadowe, które skopiuje wszystkie dane ze starych dokumentów do nowej kolekcji. Zadanie wsadowe powinno unikać zapisywania kolejnych identyfikatorów dokumentów, aby zapobiec powstawaniu punktów dostępu. Po zakończeniu zadania wsadowego możesz tylko odczytywać dane z nowej kolekcji.
Udoskonaleniem tej strategii jest migracja małych grup użytkowników naraz. Dodaj do dokumentu użytkownika pole, które śledzi stan migracji tego użytkownika. Wybierz grupę użytkowników do przeniesienia na podstawie skrótu identyfikatora użytkownika. Użyj zadania wsadowego, aby przeprowadzić migrację dokumentów dla tej grupy użytkowników, i użyj odczytów równoległych w przypadku użytkowników w trakcie migracji.
Pamiętaj, że nie możesz łatwo cofnąć zmian, chyba że w fazie migracji będziesz zapisywać podwójnie zarówno stare, jak i nowe jednostki. Spowoduje to wzrostCloud Firestore poniesionych kosztów.
Prywatność
- Unikaj przechowywania informacji poufnych w identyfikatorze projektu w chmurze. Identyfikator projektu Cloud może być zachowany po zakończeniu projektu.
- Zgodnie z zasadami dotyczącymi zgodności danych zalecamy, aby nie przechowywać informacji poufnych 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. Na przykład używanie reguł może zapobiec sytuacji, w której złośliwy użytkownik wielokrotnie pobiera całą bazę danych.
Dowiedz się więcej o używaniu Cloud Firestore Security Rules.