Bigtable und Dataflow: Datenbankmonitoring (HBase Java Client)

Bigtable und Dataflow:
Datenbankmonitoring (HBase Java Client)

Informationen zu diesem Codelab

subjectZuletzt aktualisiert: Okt. 8, 2020
account_circleVerfasst von thebilly

1. Einführung

In diesem Codelab verwenden Sie die Monitoring-Tools von Cloud Bigtable, um durch das Schreiben und Lesen von Daten mit Cloud Dataflow und dem Java HBase-Client verschiedene Kunstwerke zu schaffen.

Du lernst, wie du

  • Mit Cloud Dataflow große Datenmengen in Bigtable laden
  • Bigtable-Instanzen und -Tabellen bei der Datenaufnahme überwachen
  • Bigtable mit einem Dataflow-Job abfragen
  • Mit dem Key Visualizer-Tool Hotspots aufgrund Ihres Schemadesigns ermitteln
  • Kunstwerke mit dem Key Visualizer erstellen

d098cc81f78f02eb.png

<ph type="x-smartling-placeholder"> <ph type="x-smartling-placeholder">

Wie würden Sie Ihre Erfahrung mit Cloud Bigtable bewerten?

Wie möchten Sie diese Anleitung nutzen?

2. Bigtable-Datenbank erstellen

Cloud Bigtable ist der NoSQL-Big-Data-Datenbankdienst von Google. Dieselbe Datenbank wird auch für viele Hauptdienste von Google verwendet, z. B. für die Google-Suche, Analytics, Maps und Gmail. Es eignet sich ideal zum Ausführen großer analytischen Arbeitslasten und zum Erstellen von Anwendungen mit niedriger Latenz. Sehen Sie sich das Einführung in Cloud Bigtable-Codelab für eine ausführliche Einführung an.

Projekt erstellen

Erstellen Sie zuerst ein neues Projekt. Verwenden Sie die integrierte Cloud Shell, die Sie durch Klicken auf die Schaltfläche "Cloud Shell aktivieren" oben rechts.

a74d156ca7862b28.png

Legen Sie die folgenden Umgebungsvariablen fest, um das Kopieren und Einfügen der Codelab-Befehle zu vereinfachen:

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

Die Tools für dieses Codelab, das gcloud-Befehlszeilentool und die cbt-Befehlszeile sowie Maven sind in Cloud Shell bereits installiert.

Aktivieren Sie die Cloud Bigtable APIs mit diesem Befehl.

gcloud services enable bigtable.googleapis.com bigtableadmin.googleapis.com

Erstellen Sie mit dem folgenden Befehl eine Instanz:

gcloud bigtable instances create $INSTANCE_ID \
    --cluster=$CLUSTER_ID \
    --cluster-zone=$CLUSTER_ZONE \
    --cluster-num-nodes=$CLUSTER_NUM_NODES \
    --display-name=$INSTANCE_ID

Nachdem Sie die Instanz erstellt haben, füllen Sie die cbt-Konfigurationsdatei aus und erstellen dann eine Tabelle und eine Spaltenfamilie, indem Sie die folgenden Befehle ausführen:

echo project = $GOOGLE_CLOUD_PROJECT > ~/.cbtrc
echo instance = $INSTANCE_ID >> ~/.cbtrc

cbt createtable $TABLE_ID
cbt createfamily $TABLE_ID cf

3. Lernen: Mit Dataflow in Bigtable schreiben

Grundlagen des Schreibens

Wenn Sie in Cloud Bigtable schreiben, müssen Sie ein CloudBigtableTableConfiguration-Konfigurationsobjekt angeben. Dieses Objekt gibt die Projekt-ID und Instanz-ID für Ihre Tabelle sowie den Namen der Tabelle selbst an:

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

Dann kann Ihre Pipeline HBase-Mutation-Objekte übergeben, zu denen auch Put und Delete gehören können.

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));

Der Dataflow-Job "LoadData"

Auf der nächsten Seite erfahren Sie, wie Sie den LoadData-Job ausführen, aber hier werde ich auf die wichtigen Teile der Pipeline hinweisen.

Zum Generieren von Daten erstellen Sie eine Pipeline, die mithilfe der Klasse GenerateSequence (ähnlich einer For-Schleife) eine Anzahl von Zeilen mit einigen Megabyte an zufälligen Daten schreibt. Der Zeilenschlüssel ist die aufgefüllte und umgekehrte Sequenznummer, sodass 250 zu 0000000052 wird.

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. Daten in Bigtable generieren und Inflow beobachten

Mit den folgenden Befehlen wird ein Dataflow-Job ausgeführt, der 40 GB Daten in Ihrer Tabelle generiert. Das ist mehr als ausreichend, damit Key Visualizer aktiviert werden kann:

Cloud Dataflow API aktivieren

gcloud services enable dataflow.googleapis.com

Rufen Sie den Code von GitHub ab und wechseln Sie in das Verzeichnis

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

Daten generieren (das Skript dauert etwa 15 Minuten)

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"

Import überwachen

Sie können den Job in der Cloud Dataflow-UI überwachen. Sie können sich auch die Auslastung Ihrer Cloud Bigtable-Instanz mithilfe der zugehörigen Monitoring-UI ansehen.

In der Dataflow-UI werden die Jobgrafik und verschiedene Jobmesswerte wie verarbeitete Elemente, aktuelle vCPUs und Durchsatz angezeigt.

9cecc290f5acea15.png

abb0561342dc6b60.png

Bigtable verfügt über Standard-Monitoringtools für Lese-/Schreibvorgänge, verwendeter Speicher, Fehlerrate und mehr auf Instanz-, Cluster- und Tabellenebene. Darüber hinaus verfügt Bigtable über den Key Visualizer, der Ihre Nutzung anhand der Zeilenschlüssel aufschlüsselt, die wir verwenden werden, sobald mindestens 30 GB Daten generiert wurden.

996f8589332dfc19.png

5. Lernen: Mit Dataflow aus Bigtable auslesen

Grundlagen des Lesens

Wenn Sie aus Cloud Bigtable lesen, müssen Sie ein CloudBigtableTableScanConfiguration-Konfigurationsobjekt angeben. Dies ähnelt dem CloudBigtableTableConfiguration, Sie können jedoch die Zeilen angeben, die gescannt und aus denen gelesen werden soll.

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();

Verwenden Sie dieses dann, um Ihre Pipeline zu starten:

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

Wenn Sie jedoch einen Lesevorgang als Teil Ihrer Pipeline ausführen möchten, können Sie einen CloudBigtableTableConfiguration an eine doFn übergeben, die AbstractCloudBigtableTableDoFn erweitert.

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

Rufen Sie dann super() mit Ihrer Konfiguration und getConnection() auf, um eine verteilte Verbindung zu erhalten.

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);
    }   
}

Der Dataflow-Job ReadData

Für dieses Codelab müssen Sie jede Sekunde aus der Tabelle lesen, damit Sie Ihre Pipeline mit einer generierten Sequenz starten können, die mehrere Lesebereiche basierend auf dem Zeitpunkt einer eingegebenen CSV-Datei auslöst.

Es ist ein wenig Mathematik erforderlich, um die zu scannenden Zeilenbereiche angesichts der Zeit zu bestimmen. Sie können jedoch auf den Dateinamen klicken, um den Quellcode anzuzeigen, wenn Sie mehr erfahren möchten.

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. Dein Meisterwerk wird erstellt

ad9c4c0b90626a3b.png

Nachdem Sie nun wissen, wie Sie Daten in Bigtable laden und mit Dataflow aus ihnen lesen, können Sie den letzten Befehl ausführen, der ein Bild der Mona Lisa über einen Zeitraum von 8 Stunden generiert.

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"

Es gibt einen Bucket mit vorhandenen Images, den Sie verwenden können. Alternativ können Sie mit diesem Tool eine Eingabedatei aus Ihren eigenen Bildern erstellen und diese dann in einen öffentlichen GCS-Bucket hochladen.

Dateinamen stammen aus gs://keyviz-art/[painting]_[hours]h.txt. Beispiel: gs://keyviz-art/american_gothic_4h.txt

Maloptionen:

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

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

Machen Sie den GCS-Bucket oder die GCS-Datei öffentlich, indem Sie allUsers die Rolle Storage Object Viewer zuweisen.

ee089815364150d2.png

Nachdem Sie das Bild ausgewählt haben, ändern Sie einfach den Parameter --file-path in diesem Befehl:

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. Später prüfen

Es kann einige Stunden dauern, bis das vollständige Bild zum Leben erweckt wird. Nach 30 Minuten sollten Sie jedoch Aktivitäten im Key Visualizer sehen. Es gibt mehrere Parameter, mit denen Sie experimentieren können: Zoom, Helligkeit und Messwert. Sie können zoomen, das Mausrad verwenden oder ein Rechteck auf dem Key Visualizer-Raster ziehen.

Durch die Helligkeit wird die Skalierung des Bildes geändert. Dies ist hilfreich, wenn Sie einen sehr heißen Bereich genauer betrachten möchten.

8e847f03df25572b.png

Außerdem lässt sich anpassen, welcher Messwert angezeigt wird. Es gibt OPs, Read bytes-Client, Writes bytes-Client, um nur einige zu nennen. „Lesebyte-Client“ scheint flüssige Bilder zu erzeugen, während „Ops“ erzeugt Bilder mit mehr Linien, die auf manchen Bildern sehr cool aussehen können.

33eb5dcf4e4be861.png

8. Fertigstellen

Bereinigen Sie Ihre Daten, um Gebühren zu vermeiden

Löschen Sie die Instanz, damit Ihrem Google Cloud Platform-Konto die in diesem Codelab verwendeten Ressourcen nicht in Rechnung gestellt werden.

gcloud bigtable instances delete $INSTANCE_ID

Behandelte Themen

  • Mit Dataflow in Bigtable schreiben
  • Lesen aus Bigtable mit Dataflow (zu Beginn der Pipeline, in der Mitte der Pipeline)
  • Dataflow-Monitoringtools verwenden
  • Bigtable-Monitoringtools einschließlich Key Visualizer verwenden

Weiteres Vorgehen