1. Wprowadzenie
Z tego ćwiczenia w Codelabs dowiesz się, jak korzystać z Cloud Bigtable za pomocą klienta Java HBase.
Dowiesz się,
- Unikaj częstych błędów projektowania schematów
- Importuj dane do pliku sekwencji
- Tworzenie zapytania o dane
Gdy skończysz, zobaczysz kilka map z danymi autobusów z Nowego Jorku. Na przykład możesz utworzyć tę mapę termiczną podróży autobusem na Manhattanie:
Jak oceniasz swoje doświadczenia z korzystaniem z Google Cloud Platform?
Jak wykorzystasz ten samouczek?
2. Informacje o zbiorze danych
Oglądasz zbiór danych o autobusach z Nowego Jorku. Ponad 300 tras autobusowych i 5800 pojazdów odbywa się tymi trasami. Nasz zbiór danych zawiera dziennik, który zawiera nazwę miejsca docelowego, identyfikator pojazdu, szerokość i długość geograficzną, spodziewaną godzinę przyjazdu i zaplanowaną godzinę przyjazdu. Zbiór danych składa się z migawek z czerwca 2017 roku wykonywanych mniej więcej co 10 minut.
3. Projekt schematu
Aby uzyskać najlepszą wydajność Cloud Bigtable, musisz przemyśleć projektowanie schematu. Dane w Cloud Bigtable są automatycznie sortowane leksykograficznie, więc jeśli dobrze zaprojektujesz schemat, zapytania o powiązane dane będą bardzo skuteczne. Cloud Bigtable umożliwia wykonywanie zapytań z wykorzystaniem wyszukiwania punktowego według klucza wiersza lub skanowania zakresu wierszy, które zwracają sąsiadujący zestaw wierszy. Jeśli jednak schemat nie jest dobrze przemyślany, możesz łączyć wiele wyszukiwań wierszy lub, co gorsza, przeprowadzać pełne skanowanie tabel, co jest bardzo powolnym działaniem.
Planowanie zapytań
Nasze dane zawierają różne informacje, ale w tym ćwiczeniach z programowania należy użyć lokalizacji i miejsca docelowego autobusu.
Na podstawie tych informacji możesz wykonać te zapytania:
- Sprawdź lokalizację pojedynczego autobusu w danej godzinie.
- Pobierz dane z całego dnia dla linii autobusowej lub konkretnego autobusu.
- Wyszukaj wszystkie autobusy w prostokątnym widoku na mapie.
- Pobierz aktualne lokalizacje wszystkich autobusów (jeśli te dane były pozyskiwane w czasie rzeczywistym).
Nie można w optymalny sposób wykonać tego zbioru zapytań razem. Jeśli na przykład sortujesz dane według czasu, nie możesz przeprowadzić skanowania na podstawie lokalizacji bez pełnego skanowania tabeli. Ustalenie priorytetów na podstawie zapytań, które wykonujesz najczęściej,
W ramach tego ćwiczenia w Codelabs dowiesz się, jak zoptymalizować i wykonywać następujący zestaw zapytań:
- Uzyskiwanie informacji o lokalizacji konkretnego pojazdu w ciągu godziny.
- Uzyskaj informacje o lokalizacji całej linii autobusowej w ciągu godziny.
- Sprawdź lokalizacje wszystkich autobusów na Manhattanie w ciągu godziny.
- Sprawdź najnowsze lokalizacje wszystkich autobusów na Manhattanie w ciągu godziny.
- Pobierz lokalizację całej linii autobusowej w ciągu miesiąca.
- Uzyskiwanie lokalizacji całej linii autobusowej z danym miejscem docelowym w ciągu godziny.
Projektowanie klucza wiersza
W ramach tych ćwiczeń w Codelabs będziesz pracować ze statycznym zbiorem danych, ale zaprojektujesz schemat zapewniający skalowalność. Zaprojektujesz schemat, który pozwoli przesyłać do tabeli więcej danych magistrali, zachowując przy tym dobrą wydajność.
Oto proponowany schemat klucza wiersza:
[Firma autobusowa/linia autobusu/sygnatura czasowa zaokrąglona w dół do godziny/identyfikatora pojazdu]. Każdy wiersz zawiera godzinę danych, a każda komórka zawiera wiele wersji danych z sygnaturami czasowymi.
W tym ćwiczeniu w Codelabs wykorzystasz 1 grupę kolumn. Oto przykładowy widok danych. Dane są sortowane według klucza wiersza.
Klucz wiersza | cf:VehicleLocation.Współrzędne | cf:LocationLocation.Longitude | … |
MTA/M86-SBS/1496275200000/NYCT_5824 | 40.781212 @20:52:54.0040.776163 @20:43:19.0040.778714 @20:33:46.00 | -73.961942 @20:52:54.00-73.946949 @20:43:19.00-73.953731 @20:33:46.00 | … |
MTA/M86-SBS/1496275200000/NYCT_5840 | 40.780664 @20:13:51.0040.788416 @20:03:40.00 | -73.958357 @20:13:51.00 -73.976748 @20:03:40.00 | … |
MTA/M86-SBS/1496275200000/NYCT_5867 | 40.780281 @20:51:45.0040.779961 @20:43:15.0040.788416 @20:33:44.00 | -73.946890 @20:51:45.00-73.959465 @20:43:15.00-73.976748 @20:33:44.00 | … |
... | ... | ... | … |
4. Utwórz instancję, tabelę i rodzinę
Następnie utwórz tabelę Cloud Bigtable.
Najpierw utwórz nowy projekt. Użyj wbudowanej usługi Cloud Shell, którą możesz otworzyć, klikając „Aktywuj Cloud Shell”. w prawym górnym rogu.
Aby ułatwić sobie kopiowanie i wklejanie poleceń ćwiczenia w programie, ustaw następujące zmienne środowiskowe:
INSTANCE_ID="bus-instance" CLUSTER_ID="bus-cluster" TABLE_ID="bus-data" CLUSTER_NUM_NODES=3 CLUSTER_ZONE="us-central1-c"
Cloud Shell zawiera narzędzia, których użyjesz w tym ćwiczeniu z programowania, narzędzie wiersza poleceń gcloud, interfejs wiersza poleceń cbt i Maven.
Włącz interfejsy Cloud Bigtable API, uruchamiając to polecenie.
gcloud services enable bigtable.googleapis.com bigtableadmin.googleapis.com
Utwórz instancję, uruchamiając to polecenie:
gcloud bigtable instances create $INSTANCE_ID \ --cluster=$CLUSTER_ID \ --cluster-zone=$CLUSTER_ZONE \ --cluster-num-nodes=$CLUSTER_NUM_NODES \ --display-name=$INSTANCE_ID
Po utworzeniu instancji wypełnij plik konfiguracji cbt, a następnie utwórz tabelę i grupę kolumn, uruchamiając te polecenia:
echo project = $GOOGLE_CLOUD_PROJECT > ~/.cbtrc echo instance = $INSTANCE_ID >> ~/.cbtrc cbt createtable $TABLE_ID cbt createfamily $TABLE_ID cf
5. Importuj dane
Zaimportuj zbiór plików sekwencji na potrzeby tego ćwiczenia z programowania z gs://cloud-bigtable-public-datasets/bus-data
, wykonując te czynności:
Włącz Cloud Dataflow API, uruchamiając to polecenie.
gcloud services enable dataflow.googleapis.com
Uruchom następujące polecenia, aby zaimportować tabelę.
NUM_WORKERS=$(expr 3 \* $CLUSTER_NUM_NODES) gcloud beta dataflow jobs run import-bus-data-$(date +%s) \ --gcs-location gs://dataflow-templates/latest/GCS_SequenceFile_to_Cloud_Bigtable \ --num-workers=$NUM_WORKERS --max-workers=$NUM_WORKERS \ --parameters bigtableProject=$GOOGLE_CLOUD_PROJECT,bigtableInstanceId=$INSTANCE_ID,bigtableTableId=$TABLE_ID,sourcePattern=gs://cloud-bigtable-public-datasets/bus-data/*
Monitorowanie importu
Zadanie możesz monitorować w interfejsie użytkownika Cloud Dataflow. Możesz też wyświetlić obciążenie instancji Cloud Bigtable za pomocą jej interfejsu monitorowania. Cały import powinien potrwać 5 minut.
6. Pobierz kod
git clone https://github.com/googlecodelabs/cbt-intro-java.git cd cbt-intro-java
Przejdź na Java 11, uruchamiając następujące polecenia:
sudo update-java-alternatives -s java-1.11.0-openjdk-amd64 && export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64/
7. Przeprowadź wyszukiwanie
Pierwsze zapytanie, które wykonasz, to proste wyszukiwanie wierszy. Dane dotyczące autobusu będą dostępne na linii M86-SBS 1 czerwca 2017 roku od 00:00 do 1:00. Pojazd o identyfikatorze NYCT_5824
znajduje się wtedy na linii autobusowej.
Mając te informacje i znając strukturę schematu (firma autobusowa/linia autobusu/sygnatura czasowa zaokrąglona w dół do godziny/identyfikatora pojazdu) możesz wywnioskować, że kluczem wiersza jest:
MTA/M86-SBS/1496275200000/NYCT_5824
BusQueries.java
private static final byte[] COLUMN_FAMILY_NAME = Bytes.toBytes("cf");
private static final byte[] LAT_COLUMN_NAME = Bytes.toBytes("VehicleLocation.Latitude");
private static final byte[] LONG_COLUMN_NAME = Bytes.toBytes("VehicleLocation.Longitude");
String rowKey = "MTA/M86-SBS/1496275200000/NYCT_5824";
Result getResult =
table.get(
new Get(Bytes.toBytes(rowKey))
.addColumn(COLUMN_FAMILY_NAME, LAT_COLUMN_NAME)
.addColumn(COLUMN_FAMILY_NAME, LONG_COLUMN_NAME));
Wynik powinien zawierać najnowszą lokalizację autobusu z danej godziny. Jeśli jednak chcesz zobaczyć wszystkie lokalizacje, ustaw maksymalną liczbę wersji w żądaniu pobrania.
BusQueries.java
Result getResult =
table.get(
new Get(Bytes.toBytes(rowKey))
.setMaxVersions(Integer.MAX_VALUE)
.addColumn(COLUMN_FAMILY_NAME, LAT_COLUMN_NAME)
.addColumn(COLUMN_FAMILY_NAME, LONG_COLUMN_NAME));
W Cloud Shell uruchom następujące polecenie, aby uzyskać listę szerokości i długości geograficznej tego autobusu w ciągu godziny:
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=lookupVehicleInGivenHour
Możesz skopiować i wkleić długości i szerokości geograficzne do aplikacji MapMaker, aby zwizualizować wyniki. Po kilku warstwach zobaczysz komunikat, że musisz utworzyć bezpłatne konto. Możesz utworzyć konto lub po prostu usunąć istniejące warstwy. To ćwiczenie w Codelabs zawiera wizualizację każdego kroku, jeśli chcesz po prostu kontynuować naukę. Oto wynik pierwszego zapytania:
8. Skanuj
Przejrzyjmy teraz wszystkie dane dotyczące linii autobusowej z tej godziny. Kod skanowania wygląda bardzo podobnie do kodu get. Nadaj skanerowi pozycję początkową, a następnie wskazujesz, że chcesz otrzymywać wiersze z liniami autobusowymi M86-SBS tylko w ciągu godziny. Oznaczenie to sygnaturą czasową 1496275200000.
BusQueries.java
Scan scan;
scan = new Scan();
scan.setMaxVersions(Integer.MAX_VALUE)
.addColumn(COLUMN_FAMILY_NAME, LAT_COLUMN_NAME)
.addColumn(COLUMN_FAMILY_NAME, LONG_COLUMN_NAME)
.withStartRow(Bytes.toBytes("MTA/M86-SBS/1496275200000"))
.setRowPrefixFilter(Bytes.toBytes("MTA/M86-SBS/1496275200000"));
ResultScanner scanner = table.getScanner(scan);
Aby je uzyskać, uruchom to polecenie.
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=scanBusLineInGivenHour
Aplikacja Kreator map może wyświetlać wiele list jednocześnie, dzięki czemu w pierwszym zapytaniu możesz sprawdzić, który z autobusów jest pojazdem.
Ciekawą modyfikacją tego zapytania jest wyświetlenie danych z całego miesiąca dla linii magistrali M86-SBS. Jest to bardzo proste. Aby uzyskać wynik, usuń sygnaturę czasową z wiersza początkowego i filtra prefiksu.
BusQueries.java
scan.withStartRow(Bytes.toBytes("MTA/M86-SBS/"))
.setRowPrefixFilter(Bytes.toBytes("MTA/M86-SBS/"));
// Optionally, reduce the results to receive one version per column
// since there are so many data points.
scan.setMaxVersions(1);
Aby je uzyskać, uruchom to polecenie. (Wyświetli się długa lista wyników).
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=scanEntireBusLine
Po skopiowaniu wyników do Kreatora Map możesz wyświetlić mapę termiczną trasy autobusu. Pomarańczowe plamy wskazują przystanki, a jasnoczerwone plamy to początek i koniec trasy.
9. Wprowadź filtry
Następnie zastosujesz filtrowanie według autobusów jadących na wschód i autobusy kierujące się na zachód, a potem utworzysz osobną mapę termiczną dla każdego z nich.
BusQueries.java
Scan scan;
ResultScanner scanner;
scan = new Scan();
SingleColumnValueFilter valueFilter =
new SingleColumnValueFilter(
COLUMN_FAMILY_NAME,
Bytes.toBytes("DestinationName"),
CompareOp.EQUAL,
Bytes.toBytes("Select Bus Service Yorkville East End AV"));
scan.setMaxVersions(1)
.addColumn(COLUMN_FAMILY_NAME, LAT_COLUMN_NAME)
.addColumn(COLUMN_FAMILY_NAME, LONG_COLUMN_NAME);
scan.withStartRow(Bytes.toBytes("MTA/M86-SBS/"))
.setRowPrefixFilter(Bytes.toBytes("MTA/M86-SBS/"));
scan.setFilter(valueFilter);
scanner = table.getScanner(scan);
Uruchom poniższe polecenie, by uzyskać wyniki dla autobusów jadących na wschód.
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=filterBusesGoingEast
Aby autobusy kierowały się na zachód, zmień ciąg znaków w filtrze valueFilter:
BusQueries.java
SingleColumnValueFilter valueFilter =
new SingleColumnValueFilter(
COLUMN_FAMILY_NAME,
Bytes.toBytes("DestinationName"),
CompareOp.EQUAL,
Bytes.toBytes("Select Bus Service Westside West End AV"));
Uruchom poniższe polecenie, by otrzymać wyniki dla autobusów jadących na zachód.
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=filterBusesGoingWest
Autobusy jadące na wschód
Autobusy jadące na zachód
Dzięki porównaniu obu map termicznych można zobaczyć różnice w trasach, a także tempo. Jedną z interpretacji danych jest to, że na trasie biegnącej w kierunku zachodnim autobusy zatrzymują się częściej, zwłaszcza gdy wjeżdżają do Central Parku. A w autobusach jadących na wschód nie widać wielu zacięć.
10. Skanuj wiele zakresów
Ostatnie zapytanie dotyczy przypadku, gdy w danym obszarze zależy Ci na wielu liniach autobusowych:
BusQueries.java
private static final String[] MANHATTAN_BUS_LINES = {"M1","M2","M3",...
Scan scan;
ResultScanner scanner;
List<RowRange> ranges = new ArrayList<>();
for (String busLine : MANHATTAN_BUS_LINES) {
ranges.add(
new RowRange(
Bytes.toBytes("MTA/" + busLine + "/1496275200000"), true,
Bytes.toBytes("MTA/" + busLine + "/1496275200001"), false));
}
Filter filter = new MultiRowRangeFilter(ranges);
scan = new Scan();
scan.setFilter(filter);
scan.setMaxVersions(Integer.MAX_VALUE)
.addColumn(COLUMN_FAMILY_NAME, LAT_COLUMN_NAME)
.addColumn(COLUMN_FAMILY_NAME, LONG_COLUMN_NAME);
scan.withStartRow(Bytes.toBytes("MTA/M")).setRowPrefixFilter(Bytes.toBytes("MTA/M"));
scanner = table.getScanner(scan);
Aby je uzyskać, uruchom to polecenie.
mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \ -Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \ -Dquery=scanManhattanBusesInGivenHour
11. Zakończ
Czyszczenie danych w celu uniknięcia opłat
Aby uniknąć obciążenia konta Google Cloud Platform opłatami za zasoby zużyte w tym ćwiczeniu z programowania, usuń instancję.
gcloud bigtable instances delete $INSTANCE_ID
Omówione zagadnienia
- Projekt schematu
- Konfigurowanie instancji, tabeli i rodziny
- Importowanie plików sekwencji za pomocą Dataflow
- Tworzenie zapytań z użyciem wyszukiwania, skanowania, skanowania z filtrem i skanowania wielozakresowego
Dalsze kroki
- Więcej informacji o Cloud Bigtable znajdziesz w dokumentacji.
- Wypróbuj inne funkcje Google Cloud Platform. Zapoznaj się z naszymi samouczkami.
- Dowiedz się, jak monitorować dane ciągów czasowych za pomocą integracji z OpenTSDB