Podczas tworzenia aplikacji, która korzysta z Cloud Firestore, możesz szybko sprawdzić te sprawdzone metody.
Lokalizacja bazy danych
Podczas tworzenia instancji bazy danych wybierz lokalizację bazy danych, która znajduje się najbliżej użytkowników i zasobów obliczeniowych. Dalekie przeskoki sieciowe są bardziej podatne na błędy i zwiększają opóźnienie zapytania.
Aby zmaksymalizować dostępność i trwałość aplikacji, wybierz lokalizację w wielu regionach i umieść krytyczne zasoby obliczeniowe w co najmniej 2 regionach.
Wybierz lokalizację w jednym regionie, aby obniżyć koszty, zmniejszyć opóźnienia zapisu (jeśli Twoja aplikacja jest wrażliwa na opóźnienia) lub kolokować 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 monotonicznie rosnących identyfikatorów dokumentów, takich jak:
Customer1,Customer2,Customer3, ...Product 1,Product 2,Product 3, ...
Takie sekwencyjne identyfikatory mogą prowadzić do powstawania punktów krytycznych, które wpływają na czas oczekiwania.
Nazwy pól
Unikaj tych znaków w nazwach pól, ponieważ wymagają one dodatkowego znaku zmiany znaczenia:
.kropka[nawias otwierający]nawias zamykający*gwiazdka`grawis
Indeksy
Zmniejszanie opóźnienia zapisu
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. Najprostszym rozwiązaniem jest wyłączenie indeksowania malejącego i indeksowania tablic. Usunięcie nieużywanych indeksowanych wartości obniży też koszty miejsca na dane.
Zmniejsz liczbę dokumentów w transakcji. Jeśli chcesz zapisać dużą liczbę dokumentów, rozważ użycie zapisu zbiorczego zamiast zapisu niepodzielnego.
Wykluczenia indeksów
W przypadku większości aplikacji możesz polegać na automatycznym indeksowaniu i linkach w komunikatach o błędach, aby zarządzać indeksami. Możesz jednak dodać wyjątki dla pojedynczych pól w tych przypadkach:
| Zgłoszenie | Opis |
|---|---|
| Duże pola ciągów znaków | Jeśli masz pole ciągu, które często zawiera długie wartości ciągu, których nie używasz do tworzenia zapytań, możesz obniżyć koszty miejsca na dane, wyłączając to pole z indeksowania. |
| Wysokie częstotliwoś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 zapisów na sekundę. Jeśli nie wysyłasz zapytań na podstawie pola z wartościami sekwencyjnymi, możesz wyłączyć to pole z indeksowania, aby ominąć ten limit. Na przykład w przypadku IoT z wysokim współczynnikiem zapisu kolekcja zawierająca dokumenty z polem sygnatury czasowej może zbliżyć się do limitu 500 zapisów na sekundę. |
| Pola TTL |
Jeśli używasz zasad TTL (czasu życia danych), pamiętaj, że pole TTL musi być sygnaturą czasową. Indeksowanie pól TTL jest domyślnie włączone i może wpływać na wydajność przy większym natężeniu ruchu. Zalecamy dodanie wykluczeń indeksowania automatycznego dla pól TTL. |
| Duże pola tablic lub map | Duże pola tablicy lub mapy mogą zbliżyć 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 je z indeksowania. |
Operacje odczytu i zapisu
Dokładna maksymalna częstotliwość, z jaką aplikacja może aktualizować pojedynczy dokument, zależy w dużej mierze od zbioru zadań. Więcej informacji znajdziesz w artykule Aktualizacje pojedynczego dokumentu.
Jeśli to możliwe, używaj wywołań asynchronicznych zamiast synchronicznych. Wywołania asynchroniczne minimalizują wpływ na czas oczekiwania. Załóżmy na przykład, że aplikacja potrzebuje wyniku wyszukiwania dokumentu i wyników zapytania, zanim wyrenderuje odpowiedź. Jeśli wyszukiwanie i zapytanie nie są zależne od danych, nie trzeba czekać na zakończenie wyszukiwania przed rozpoczęciem zapytania.
Nie używaj przesunięć. Zamiast tego używaj kursorów. Użycie przesunięcia zapobiega tylko 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 Twoja aplikacja jest obciążana opłatami za operacje odczytu wymagane do ich pobrania.
Ponowne próby transakcji
Pakiety SDK i biblioteki klienta Cloud Firestore automatycznie ponawiają nieudane transakcje, aby poradzić sobie z przejściowymi błędami. Jeśli Twoja aplikacja uzyskuje dostęp do Cloud Firestore bezpośrednio przez interfejsy API REST lub RPC, a nie przez pakiet SDK, powinna implementować ponowne próby transakcji, aby zwiększyć niezawodność.
Aktualizacje w czasie rzeczywistym
Sprawdzone metody dotyczące aktualizacji w czasie rzeczywistym znajdziesz w artykule Informacje o zapytaniach w czasie rzeczywistym na dużą skalę.
Projektowanie pod kątem skalowalności
Poniższe sprawdzone metody opisują, jak unikać sytuacji, które powodują problemy z rywalizacją.
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 testów obciążenia. Dokładna maksymalna częstotliwość, 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 dotyczy problem.
Operacja zapisu dokumentu aktualizuje dokument i wszystkie powiązane indeksy oraz synchronicznie stosuje operację zapisu w kworum replik Cloud Firestore. Przy wystarczająco wysokich częstotliwościach zapisu w bazie danych zaczną występować rywalizacje, większe opóźnienia lub inne błędy.
Wysokie współczynniki odczytu, zapisu i usuwania w wąskim zakresie dokumentów
Unikaj wysokich częstotliwości odczytu lub zapisu w przypadku dokumentów, które są blisko siebie pod względem leksykograficznym. W przeciwnym razie w aplikacji będą występować błędy rywalizacji. Ten problem jest znany jako hotspotting i może wystąpić w aplikacji, jeśli wykonuje ona dowolne z tych czynności:
tworzy nowe dokumenty z bardzo dużą częstotliwością i przydziela im własne, monotonicznie rosnące identyfikatory;
Cloud Firestore przydziela identyfikatory dokumentów za pomocą algorytmu rozproszenia. Jeśli tworzysz nowe dokumenty, używając automatycznych identyfikatorów dokumentów, nie powinno dochodzić do hotspottingu podczas zapisywania.
tworzy nowe dokumenty w szybkim tempie w kolekcji, która zawiera niewiele dokumentów;
tworzy nowe dokumenty z monotonicznie rosnącym polem, takim jak sygnatura czasowa, z bardzo dużą szybkością;
Usuwa dokumenty z kolekcji z dużą szybkością.
Zapisuje dane w bazie danych z bardzo dużą szybkością bez stopniowego zwiększania ruchu.
Unikanie pomijania usuniętych danych
Unikaj zapytań, które pomijają ostatnio usunięte dane. Jeśli wyniki zapytania zostały niedawno usunięte, zapytanie może pominąć dużą liczbę wpisów indeksu.
Przykładem zbioru zadań, który może wymagać pominięcia dużej ilości usuniętych danych, jest zbiór, który 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 uruchamiane, skanuje wpisy indeksu dla pola created w ostatnio usuniętych dokumentach. Spowalnia to zapytania.
Aby poprawić 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 powyższym przykładzie użyto pola, którego wartość rośnie monotonicznie, co jest antywzorcem w przypadku dużej liczby operacji zapisu.
Zwiększanie ruchu
Należy stopniowo zwiększać ruch do nowych kolekcji lub dokumentów o podobnych nazwach, aby usługa Cloud Firestore miała wystarczająco dużo czasu na przygotowanie dokumentów na zwiększony ruch. Zalecamy rozpoczęcie od maksymalnie 500 operacji na sekundę w nowej kolekcji, a następnie zwiększanie ruchu o 50% co 5 minut. Podobnie możesz zwiększyć ruch związany z zapisywaniem, ale pamiętaj o standardowych limitach Cloud Firestore. Upewnij się, że operacje są rozłożone stosunkowo równomiernie w całym zakresie kluczy. Nazywa się to zasadą „500/50/5”.
Przenoszenie ruchu do nowej kolekcji
Stopniowe zwiększanie ruchu jest szczególnie ważne, jeśli przenosisz ruch w aplikacji z jednej kolekcji do innej. Prostym sposobem na przeprowadzenie tej migracji jest odczytanie danych ze starej kolekcji, a jeśli dokument nie istnieje, odczytanie danych z nowej kolekcji. Może to jednak spowodować nagły wzrost ruchu w dokumentach o podobnych nazwach w nowej kolekcji. Cloud Firestore może nie być w stanie skutecznie 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 znajdziesz przykładową strategię znaną jako odczyty równoległe. Musisz określić, czy ta strategia jest skuteczna w przypadku Twoich danych. Ważnym czynnikiem będzie wpływ operacji równoległych na koszty podczas migracji.
Odczyty 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 współczynnik odczytów nieistniejących dokumentów może prowadzić do hotspottingu, dlatego pamiętaj, aby stopniowo zwiększać obciążenie nowej kolekcji. Lepszą strategią jest skopiowanie starego dokumentu do nowej kolekcji, a następnie usunięcie go. Stopniowo zwiększaj liczbę odczytów równoległych, aby mieć pewność, że Cloud Firestore poradzi sobie z ruchem kierowanym do 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 do wybrania losowego odsetka użytkowników próbujących zapisać nowe dokumenty. Upewnij się, że wynik hashowania identyfikatora użytkownika nie jest zniekształcony przez funkcję ani 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 w sekwencyjnych identyfikatorach dokumentów, aby zapobiec powstawaniu hotspotów. Po zakończeniu zadania wsadowego możesz odczytywać tylko z nowej kolekcji.
Ulepszeniem 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 przenieść dokumenty dla tej partii użytkowników, i użyj odczytów równoległych dla użytkowników w trakcie migracji.
Pamiętaj, że nie możesz łatwo przywrócić poprzedniego stanu, chyba że podczas fazy migracji wykonasz podwójne zapisy zarówno starych, jak i nowych encji. Spowoduje to wzrost kosztów Cloud Firestore.
Prywatność
- Unikaj przechowywania informacji poufnych w identyfikatorze projektu w chmurze. Identyfikator projektu w chmurze może być przechowywany dłużej niż sam projekt.
- Zgodnie ze sprawdzonymi metodami dotyczącymi zgodności danych zalecamy, aby nie przechowywać informacji poufnych w nazwach dokumentów i nazwach pól dokumentów.
Ochrona przed nieuprawnionym dostępem
Zapobiegaj nieautoryzowanym operacjom na bazie danych za pomocą Cloud Firestore Security Rules. Na przykład użycie reguł może zapobiec sytuacji, w której złośliwy użytkownik wielokrotnie pobiera całą bazę danych.
Dowiedz się więcej o korzystaniu z Cloud Firestore Security Rules.