Bigtable e Dataflow: arte di monitoraggio dei database (client Java HBase)

1. Introduzione

In questo codelab, utilizzerai gli strumenti di monitoraggio di Cloud Bigtable per creare varie opere d'arte scrivendo e leggendo i dati con Cloud Dataflow e il client Java HBase.

Imparerai a

  • Carica grandi quantità di dati in Bigtable utilizzando Cloud Dataflow
  • Monitora le istanze e le tabelle Bigtable durante l'importazione dei dati
  • Query su Bigtable utilizzando un job Dataflow
  • Esplora lo strumento Key Visualizer, che può essere usato per trovare gli hotspot in base alla progettazione dello schema
  • Crea arte usando il Key Visualizer

d098cc81f78f02eb.png

Come valuteresti la tua esperienza di utilizzo di Cloud Bigtable?

Principiante Livello intermedio Eccellente

Come utilizzerai questo tutorial?

Solo lettura Leggilo e completa gli esercizi

2. Crea il tuo database Bigtable

Cloud Bigtable è il servizio di database di big data NoSQL di Google. È lo stesso database su cui si basano molti dei principali servizi di Google, tra cui Ricerca, Analytics, Maps e Gmail. È ideale per eseguire carichi di lavoro analitici di grandi dimensioni e creare applicazioni a bassa latenza. Consulta Introduction to Cloud Bigtable Codelab per un'introduzione approfondita.

Creare un progetto

Per prima cosa, crea un nuovo progetto. Usa Cloud Shell integrato, che puoi aprire facendo clic su "Attiva Cloud Shell" nell'angolo in alto a destra.

a74d156ca7862b28.png

Imposta le seguenti variabili di ambiente per semplificare l'operazione di copia e incolla dei comandi del codelab:

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 include gli strumenti che utilizzerai in questo codelab, lo strumento a riga di comando gcloud, l'interfaccia a riga di comando cbt e Maven, già installati.

Abilita le API Cloud Bigtable eseguendo questo comando.

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

Crea un'istanza eseguendo questo comando:

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

Dopo aver creato l'istanza, compila il file di configurazione cbt, quindi crea una famiglia di tabelle e colonne eseguendo questi comandi:

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

cbt createtable $TABLE_ID
cbt createfamily $TABLE_ID cf

3. Scopri: scrivere in Bigtable con Dataflow

Nozioni di base sulla scrittura

Quando scrivi in Cloud Bigtable, devi fornire un oggetto di configurazione CloudBigtableTableConfiguration. Questo oggetto specifica l'ID progetto e l'ID istanza della tabella, nonché il nome della tabella stessa:

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

Quindi la pipeline può passare oggetti HBase Mutation, che possono includere Put e 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));

Job Dataflow di LoadData

La pagina successiva mostrerà come eseguire il job LoadData, ma qui tratterò le parti importanti della pipeline.

Per generare dati, creerai una pipeline che utilizza la classe GenerateSequence (analogamente a un ciclo for) per scrivere un numero di righe con pochi megabyte di dati casuali. Il valore rowkey corrisponderà al numero di sequenza riempito e invertito, quindi 250 diventa 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. Genera dati in Bigtable e monitora il flusso

I seguenti comandi eseguiranno un job Dataflow che genera 40 GB di dati nella tabella, più che sufficienti per l'attivazione di Key Visualizer:

Abilita l'API Cloud Dataflow

gcloud services enable dataflow.googleapis.com

Recupera il codice da GitHub e modificalo nella directory

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

Genera i dati (lo script richiede circa 15 minuti)

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"

Monitorare l'importazione

Puoi monitorare il job nell'interfaccia utente di Cloud Dataflow. Inoltre, puoi visualizzare il carico sull'istanza Cloud Bigtable con la relativa UI di monitoraggio.

Nell'interfaccia utente di Dataflow, potrai vedere il grafico del job e le varie metriche del job, inclusi gli elementi elaborati, le vCPU attuali e la velocità effettiva.

9cecc290f5acea15.png

abb0561342dc6b60.png

Bigtable offre strumenti di monitoraggio standard per le operazioni di lettura/scrittura, lo spazio di archiviazione utilizzato, la percentuale di errori e altro ancora a livello di istanza, cluster e tabella. Inoltre, Bigtable dispone anche di Key Visualizer che suddivide l'utilizzo in base alle chiavi di riga che utilizzeremo una volta generati almeno 30 GB di dati.

996f8589332dfc19.png

5. Scopri: lettura da Bigtable con Dataflow

Nozioni di base sulla lettura

Quando leggi da Cloud Bigtable, devi fornire un oggetto di configurazione CloudBigtableTableScanConfiguration. È simile a CloudBigtableTableConfiguration, ma puoi specificare le righe di cui eseguire la scansione e da cui leggere.

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

Quindi utilizzalo per avviare la pipeline:

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

Tuttavia, se vuoi eseguire una lettura come parte della pipeline, puoi passare un CloudBigtableTableConfiguration a un doFn che estende AbstractCloudBigtableTableDoFn.

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

Quindi chiama super() con la tua configurazione e getConnection() per ottenere una connessione distribuita.

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

Job Dataflow di ReadData

Per questo codelab dovrai leggere la tabella ogni secondo, in modo da poter avviare la pipeline con una sequenza generata che attiva più intervalli di lettura in base all'ora in cui un file CSV inserito è stato inserito.

È necessario un po' di calcolo per determinare quali intervalli di righe analizzare data l'ora, ma puoi fare clic sul nome del file per visualizzare il codice sorgente se vuoi saperne di più.

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. Crea il tuo capolavoro

ad9c4c0b90626a3b.png

Ora che sai come caricare i dati in Bigtable e leggerli con Dataflow, puoi eseguire il comando finale che genererà un'immagine della Gioconda in 8 ore.

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"

Puoi utilizzare un bucket con immagini esistenti. In alternativa, puoi creare un file di input da una qualsiasi delle tue immagini con questo strumento e quindi caricarlo in un bucket GCS pubblico.

I nomi file sono creati a partire da gs://keyviz-art/[painting]_[hours]h.txt esempio: gs://keyviz-art/american_gothic_4h.txt

opzioni per il disegno:

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

opzioni di ora: 1, 4, 8, 12, 24, 48, 72, 96, 120, 144

Rendi pubblico il bucket o il file GCS assegnando a allUsers il ruolo Storage Object Viewer.

ee089815364150d2.png

Dopo aver scelto l'immagine, modifica il parametro --file-path in questo comando:

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. Controlla più tardi

Potrebbero essere necessarie alcune ore perché l'immagine completa diventi realtà, ma dopo 30 minuti dovresti iniziare a vedere l'attività nel visualizzatore chiave. Puoi utilizzare diversi parametri: zoom, luminosità e metrica. Puoi eseguire lo zoom utilizzando la rotellina del mouse o trascinando un rettangolo sulla griglia del visualizzatore dei tasti.

La luminosità modifica il ridimensionamento dell'immagine, il che è utile per vedere più da vicino una zona molto calda.

8e847f03df25572b.png

Puoi anche modificare la metrica da visualizzare. Ci sono OP, client di lettura byte, client byte scritti per citarne alcuni. "Leggi byte client" sembra produrre immagini fluide mentre "Ops" produce immagini con più linee che possono risultare molto interessanti su alcune immagini.

33eb5dcf4e4be861.png

8. Completa la configurazione

Eseguire la pulizia per evitare addebiti

Per evitare che al tuo account Google Cloud Platform vengano addebitati costi relativi alle risorse utilizzate in questo codelab, devi eliminare la tua istanza.

gcloud bigtable instances delete $INSTANCE_ID

Argomenti trattati

  • Scrittura su Bigtable con Dataflow
  • Lettura da Bigtable con Dataflow (all'inizio della pipeline, al centro della pipeline)
  • Utilizzo degli strumenti di monitoraggio di Dataflow
  • Utilizzo degli strumenti di monitoraggio di Bigtable, tra cui Key Visualizer

Passaggi successivi