Podczas tworzenia aplikacji korzystającej z Cloud Firestore możesz używać wymienionych tu sprawdzonych metod jako szybkiego źródła informacji.
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ę w wielu regionach 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 na nie wrażliwa, 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 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 kodowania:
.kropka[nawias otwierający]nawias zamykający*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 to:
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 przechowywania.
Zmniejsz liczbę dokumentów w transakcji. Jeśli chcesz zapisać dużą liczbę dokumentów, rozważ użycie narzędzia do zapisu zbiorczego zamiast narzędzia do zapisu atomowego.
Wykluczenia indeksu
W przypadku większości aplikacji możesz polegać na automatycznym indeksowaniu, a także na linkach do komunikatów o błędach, aby zarządzać indeksami. W tych przypadkach warto dodać wyjątki dotyczące pojedynczych pól:
| Zgłoszenie | Opis |
|---|---|
| Duże pola tekstowe | 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 dotyczących czasu życia danych (TTL), 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. Zalecamy dodanie wykluczeń indeksowania automatycznego dla pól TTL. |
| Duże pola tablicy lub mapy | Duże pola tablicy lub mapy mogą zbliżać się do limitu 40 tys. pozycji indeksu na dokument. Jeśli nie wysyłasz zapytań na podstawie dużego pola tablicy lub mapy, wyłącz jego indeksowanie. |
Operacje odczytu i zapisu
Dokładna maksymalna szybkość, z jaką aplikacja może aktualizować pojedynczy dokument, zależy w dużej mierze od obciążenia. Więcej informacji znajdziesz w artykule Aktualizacje pojedynczego dokumentu.
W miarę możliwości używaj połączeń asynchronicznych zamiast synchronicznych. Wywołania asynchroniczne minimalizują wpływ czasu 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 zapytania, 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 API REST lub RPC zamiast za pomocą pakietu SDK, powinna implementować ponawianie transakcji, aby zwiększyć niezawodność.
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 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 wysokim tempie 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 pod względem kolejności leksykograficznej, ponieważ w przeciwnym razie aplikacja będzie zgłaszać błędy rywalizacji. Ten problem jest znany jako hotspotting. Może wystąpić, jeśli aplikacja wykonuje jedną 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żą szybkoś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ą ostatnio usunięte dane. Zapytanie może pominąć dużą liczbę wpisów w indeksie, jeśli wcześniejsze wyniki zapytania zostały niedawno usunięte.
Przykładem zbioru zadań, który może pomijać wiele usuniętych danych, jest ten, 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 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
Stopniowo zwiększaj ruch w przypadku nowych kolekcji lub dokumentów o podobnej nazwie, aby dać Cloud Firestore wystarczająco dużo czasu na przygotowanie dokumentów do zwiększonego ruchu. 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 Firestorelimitach standardowych. 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 jest szczególnie ważne, 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ć 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 przenoszenia ruchu do nowego zbierania danych 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 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. Dodaj do dokumentu użytkownika pole, które śledzi stan migracji tego użytkownika. Wybierz partię użytkowników do przeniesienia na podstawie skrótu identyfikatora użytkownika. Użyj zadania wsadowego, aby przeprowadzić migrację dokumentów dla tej partii użytkowników, a w przypadku użytkowników w trakcie migracji użyj odczytów równoległych.
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 wzrost poniesionych kosztówCloud Firestore.
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 stosowanie 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.