Bigtable i Dataflow: grafika monitorowania bazy danych (klient HBase Java)

1. Wprowadzenie

W ramach tego ćwiczenia w programowaniu użyjesz narzędzi do monitorowania Cloud Bigtable, aby tworzyć różne dzieła sztuki, zapisując i odczytując dane za pomocą Cloud Dataflow oraz klienta Java HBase.

Dowiesz się,

  • Wczytywanie do Bigtable dużych ilości danych za pomocą Cloud Dataflow
  • Monitorowanie instancji i tabel Bigtable podczas przetwarzania danych
  • Wysyłanie zapytania do Bigtable za pomocą zadania Dataflow
  • Poznaj narzędzie Key Visualizer, którego można używać do znajdowania hotspotów ze względu na Twój schemat
  • Tworzenie dzieł sztuki za pomocą usługi Key Visualizer

d098cc81f78f02eb.png

Jak oceniasz korzystanie z Cloud Bigtable?

Początkujący Poziom średnio zaawansowany Biegły

Jak wykorzystasz ten samouczek?

Tylko do przeczytania Przeczytaj go i wykonaj ćwiczenia
.

2. Tworzenie bazy danych Bigtable

Cloud Bigtable to oferowana przez Google usługa baz danych NoSQL do obsługi big data. Z tej samej bazy danych korzysta wiele podstawowych usług Google, m.in. wyszukiwarki, Analytics, Map i Gmaila. Idealnie nadaje się do uruchamiania dużych zbiorów zadań analitycznych i tworzenia aplikacji z małymi opóźnieniami. Więcej informacji znajdziesz w przewodniku Wprowadzenie do Cloud Bigtable Codelabs.

Utwórz projekt

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.

a74d156ca7862b28.png

Aby ułatwić sobie kopiowanie i wklejanie poleceń ćwiczenia w programie, ustaw następujące zmienne środowiskowe:

BIGTABLE_PROJECT=$GOOGLE_CLOUD_PROJECT
INSTANCE_ID="keyviz-art-instance"
CLUSTER_ID="keyviz-art-cluster"
TABLE_ID="art"
CLUSTER_NUM_NODES=1
CLUSTER_ZONE="us-central1-c" # You can choose a zone closer to you

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

3. Naucz się pisać w Bigtable za pomocą Dataflow

Podstawy pisania

Podczas zapisywania danych w Cloud Bigtable musisz podać obiekt konfiguracji CloudBigtableTableConfiguration. Ten obiekt określa identyfikator projektu i instancji dla Twojej tabeli oraz nazwę samej tabeli:

CloudBigtableTableConfiguration bigtableTableConfig =
    new CloudBigtableTableConfiguration.Builder()
        .withProjectId(PROJECT_ID)
        .withInstanceId(INSTANCE_ID)
        .withTableId(TABLE_ID)
        .build();

Dzięki temu Twój potok może przekazywać obiekty HBase Mutation, które mogą obejmować Put i Delete.

p.apply(Create.of("hello", "world"))
    .apply(
        ParDo.of(
            new DoFn<String, Mutation>() {
              @ProcessElement
              public void processElement(@Element String rowkey, OutputReceiver<Mutation> out) {
                long timestamp = System.currentTimeMillis();
                Put row = new Put(Bytes.toBytes(rowkey));

                row.addColumn(...);
                out.output(row);
              }
            }))
    .apply(CloudBigtableIO.writeToTable(bigtableTableConfig));

Zadanie LoadData Dataflow

Na następnej stronie pokażemy, jak uruchomić zadanie LoadData, ale tutaj przywołam ważne części potoku.

Aby wygenerować dane, utworzysz potok, który korzysta z klasy GenerateSequence (podobnie do pętli for) do zapisywania szeregu wierszy z kilkoma megabajtami losowych danych. Klucz wiersza będzie numerem seryjnym dopełnionym i odwróconym, więc 250 zmienia się w 0000000052.

LoadData.java

String numberFormat = "%0" + maxLength + "d";

p.apply(GenerateSequence.from(0).to(max))
    .apply(
        ParDo.of(
            new DoFn<Long, Mutation>() {
              @ProcessElement
              public void processElement(@Element Long rowkey, OutputReceiver<Mutation> out) {
                String paddedRowkey = String.format(numberFormat, rowkey);

                // Reverse the rowkey for more efficient writing
                String reversedRowkey = new StringBuilder(paddedRowkey).reverse().toString();
                Put row = new Put(Bytes.toBytes(reversedRowkey));

                // Generate random bytes
                byte[] b = new byte[(int) rowSize];
                new Random().nextBytes(b);

                long timestamp = System.currentTimeMillis();
                row.addColumn(Bytes.toBytes(COLUMN_FAMILY), Bytes.toBytes("C"), timestamp, b);
                out.output(row);
              }
            }))
    .apply(CloudBigtableIO.writeToTable(bigtableTableConfig));

4. Generowanie danych do Bigtable i monitorowanie napływu

Te polecenia uruchomią zadanie Dataflow, które wygeneruje 40 GB danych w tabeli, czyli więcej, niż wystarczy, aby aktywować usługę Key Visualizer:

Włączanie Cloud Dataflow API

gcloud services enable dataflow.googleapis.com

Pobierz kod z githuba i przejdź do katalogu

git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git
cd java-docs-samples/bigtable/beam/keyviz-art

Wygeneruj dane (skrypt zajmuje około 15 minut)

mvn compile exec:java -Dexec.mainClass=keyviz.LoadData \
"-Dexec.args=--bigtableProjectId=$BIGTABLE_PROJECT \
--bigtableInstanceId=$INSTANCE_ID --runner=dataflow \
--bigtableTableId=$TABLE_ID --project=$GOOGLE_CLOUD_PROJECT"

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.

W interfejsie Dataflow możesz zobaczyć wykres zadań i różne wskaźniki zadań, w tym przetworzone elementy, bieżące procesory wirtualne i przepustowość.

9cecc290f5acea15.png

abb0561342dc6b60.png

Bigtable udostępnia standardowe narzędzia do monitorowania operacji odczytu i zapisu, wykorzystanego miejsca na dane, odsetka błędów i innych funkcji na poziomie instancji, klastra i tabeli. Oprócz tego Bigtable ma też Key Visualizer, który dzieli wykorzystanie według kluczy wierszy, których użyjemy po wygenerowaniu co najmniej 30 GB danych.

996f8589332dfc19.png

5. Naucz się: odczytywać dane z Bigtable za pomocą Dataflow

Podstawy czytania

Podczas odczytu z Cloud Bigtable musisz podać obiekt konfiguracji CloudBigtableTableScanConfiguration. To działanie jest podobne do CloudBigtableTableConfiguration, z tym że możesz określić wiersze do skanowania i odczytywania.

Scan scan = new Scan();
scan.setCacheBlocks(false);
scan.setFilter(new FirstKeyOnlyFilter());

CloudBigtableScanConfiguration config =
    new CloudBigtableScanConfiguration.Builder()
        .withProjectId(options.getBigtableProjectId())
        .withInstanceId(options.getBigtableInstanceId())
        .withTableId(options.getBigtableTableId())
        .withScan(scan)
        .build();

Następnie użyj go do uruchomienia potoku:

p.apply(Read.from(CloudBigtableIO.read(config)))
    .apply(...

Jeśli jednak chcesz wykonać odczyt w ramach potoku, możesz przekazać CloudBigtableTableConfiguration do doFn rozszerzenia AbstractCloudBigtableTableDoFn.

p.apply(GenerateSequence.from(0).to(10))
    .apply(ParDo.of(new ReadFromTableFn(bigtableTableConfig, options)));

Następnie wywołaj super() ze swoją konfiguracją i getConnection(), aby uzyskać połączenie rozproszone.

public static class ReadFromTableFn extends AbstractCloudBigtableTableDoFn<Long, Void> {
    public ReadFromTableFn(CloudBigtableConfiguration config, ReadDataOptions readDataOptions) {
      super(config);
    }

    @ProcessElement
    public void processElement(PipelineOptions po) {
        Table table = getConnection().getTable(TableName.valueOf(options.getBigtableTableId()));
        ResultScanner imageData = table.getScanner(scan);
    }   
}

Zadanie ReadData Dataflow

W ramach tych ćwiczeń w Codelabs musisz odczytywać dane z tabeli co sekundę, dzięki czemu możesz rozpocząć potok od wygenerowanej sekwencji, która aktywuje wiele zakresów odczytu na podstawie czasu wprowadzenia pliku CSV.

Aby określić, które zakresy wierszy należy przeskanować w danym czasie, należy nieco matematyki, ale jeśli chcesz dowiedzieć się więcej, możesz kliknąć nazwę pliku, aby wyświetlić kod źródłowy.

ReadData.java

p.apply(GenerateSequence.from(0).withRate(1, new Duration(1000)))
    .apply(ParDo.of(new ReadFromTableFn(bigtableTableConfig, options)));

ReadData.java

  public static class ReadFromTableFn extends AbstractCloudBigtableTableDoFn<Long, Void> {

    List<List<Float>> imageData = new ArrayList<>();
    String[] keys;

    public ReadFromTableFn(CloudBigtableConfiguration config, ReadDataOptions readDataOptions) {
      super(config);
      keys = new String[Math.toIntExact(getNumRows(readDataOptions))];
      downloadImageData(readDataOptions.getFilePath());
      generateRowkeys(getNumRows(readDataOptions));
    }

    @ProcessElement
    public void processElement(PipelineOptions po) {
      // Determine which column will be drawn based on runtime of job.
      long timestampDiff = System.currentTimeMillis() - START_TIME;
      long minutes = (timestampDiff / 1000) / 60;
      int timeOffsetIndex = Math.toIntExact(minutes / KEY_VIZ_WINDOW_MINUTES);

      ReadDataOptions options = po.as(ReadDataOptions.class);
      long count = 0;

      List<RowRange> ranges = getRangesForTimeIndex(timeOffsetIndex, getNumRows(options));
      if (ranges.size() == 0) {
        return;
      }

      try {
        // Scan with a filter that will only return the first key from each row. This filter is used
        // to more efficiently perform row count operations.
        Filter rangeFilters = new MultiRowRangeFilter(ranges);
        FilterList firstKeyFilterWithRanges = new FilterList(
            rangeFilters,
            new FirstKeyOnlyFilter(),
            new KeyOnlyFilter());
        Scan scan =
            new Scan()
                .addFamily(Bytes.toBytes(COLUMN_FAMILY))
                .setFilter(firstKeyFilterWithRanges);

        Table table = getConnection().getTable(TableName.valueOf(options.getBigtableTableId()));
        ResultScanner imageData = table.getScanner(scan);
      } catch (Exception e) {
        System.out.println("Error reading.");
        e.printStackTrace();
      }
    }

    /**
     * Download the image data as a grid of weights and store them in a 2D array.
     */
    private void downloadImageData(String artUrl) {
    ...
    }

    /**
     * Generates an array with the rowkeys that were loaded into the specified Bigtable. This is
     * used to create the correct intervals for scanning equal sections of rowkeys. Since Bigtable
     * sorts keys lexicographically if we just used standard intervals, each section would have
     * different sizes.
     */
    private void generateRowkeys(long maxInput) {
    ...
    }

    /**
     * Get the ranges to scan for the given time index.
     */
    private List<RowRange> getRangesForTimeIndex(@Element Integer timeOffsetIndex, long maxInput) {
    ...
    }
  }

6. Tworzenie własnego dzieła

ad9c4c0b90626a3b.png

Wiesz już, jak wczytać dane do Bigtable i odczytywać je za pomocą Dataflow. Teraz możesz uruchomić ostatnie polecenie, które wygeneruje obraz Mona Lisy w ciągu 8 godzin.

mvn compile exec:java -Dexec.mainClass=keyviz.ReadData \
"-Dexec.args=--bigtableProjectId=$BIGTABLE_PROJECT \
--bigtableInstanceId=$INSTANCE_ID --runner=dataflow \
--bigtableTableId=$TABLE_ID --project=$GOOGLE_CLOUD_PROJECT"

Dostępny jest zasobnik z istniejącymi obrazami, którego możesz użyć. Możesz też utworzyć plik wejściowy na podstawie dowolnego ze swoich obrazów za pomocą tego narzędzia, a potem przesłać go do publicznego zasobnika GCS.

Nazwy plików pochodzą z przykładu gs://keyviz-art/[painting]_[hours]h.txt: gs://keyviz-art/american_gothic_4h.txt

opcje malowania:

  • american_gothic
  • mona_lisa
  • pearl_earring
  • persistence_of_memory
  • starry_night
  • sunday_afternoon
  • the_scream

opcje godzin: 1, 4, 8, 12, 24, 48, 72, 96, 120, 144

Ustaw zasobnik lub plik GCS jako publiczny, nadając usłudze allUsers rolę Storage Object Viewer.

ee089815364150d2.png

Po wybraniu obrazu zmień parametr --file-path za pomocą tego polecenia:

mvn compile exec:java -Dexec.mainClass=keyviz.ReadData \
"-Dexec.args=--bigtableProjectId=$BIGTABLE_PROJECT \
--bigtableInstanceId=$INSTANCE_ID --runner=dataflow \
--bigtableTableId=$TABLE_ID --project=$GOOGLE_CLOUD_PROJECT \
--filePath=gs://keyviz-art/american_gothic_4h.txt"

7. Sprawdź to później

Aktywowanie całego obrazu może potrwać kilka godzin, ale po 30 minutach w usłudze Key Visualizer powinna zacząć pojawiać się aktywność. Jest kilka parametrów, których możesz użyć: zoom, jasność i wskaźnik. Możesz powiększać obraz za pomocą kółka myszy lub przeciągając prostokąt na siatce kluczowej wizualizacji.

Jasność zmienia skalowanie obrazu, co jest pomocne, jeśli chcesz dokładnie przyjrzeć się bardzo gorącemu obszarowi.

8e847f03df25572b.png

Możesz też określić, które dane mają być wyświetlane. Obejmuje to między innymi operacje operacyjne, klienta odczytu bajtów i klienta zapisu bajtów. „Klient odczytujący bajty” pozwala uzyskać płynne obrazy, generuje obrazy z większą liczbą linii, które na niektórych obrazach mogą wyglądać naprawdę atrakcyjnie.

33eb5dcf4e4be861.png

8. 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

  • Zapisywanie w Bigtable za pomocą Dataflow
  • Odczyt z Bigtable za pomocą Dataflow (na początku potoku, w jego trakcie)
  • Korzystanie z narzędzi do monitorowania Dataflow
  • Korzystanie z narzędzi do monitorowania Bigtable, w tym narzędzia Key Visualizer

Dalsze kroki