Bigtable e Dataflow: arte de monitoramento de banco de dados (cliente Java do HBase)

1. Introdução

Neste codelab, você vai usar as ferramentas de monitoramento do Cloud Bigtable para criar várias obras de arte por meio da gravação e leitura de dados com o Cloud Dataflow e o cliente Java HBase.

Você aprenderá como realizar as seguintes tarefas:

  • Carregar grandes quantidades de dados no Bigtable usando o Cloud Dataflow
  • Monitorar instâncias e tabelas do Bigtable conforme os dados são ingeridos
  • Consultar o Bigtable usando um job do Dataflow
  • Explore a principal ferramenta de visualização, que pode ser usada para encontrar pontos de acesso devido ao design do seu esquema
  • Crie arte usando o visualizador principal

d098cc81f78f02eb.png

Como você classificaria sua experiência de uso do Cloud Bigtable?

Iniciante Intermediário Proficiente

Como você usará este tutorial?

Somente leitura Ler e fazer os exercícios

2. Criar o banco de dados do Bigtable

O Cloud Bigtable é o serviço de banco de dados de Big Data NoSQL do Google. É o mesmo banco de dados usado em vários serviços principais do Google, como Pesquisa, Analytics, Maps e Gmail. Ele é ideal para executar grandes cargas de trabalho analíticas e criar aplicativos de baixa latência. Confira o codelab Introdução ao Cloud Bigtable para ver uma introdução mais detalhada.

Criar um projeto

Primeiro, crie um novo projeto. Use o Cloud Shell integrado, que pode ser aberto clicando no botão "Ativar o Cloud Shell" no canto superior direito.

a74d156ca7862b28.png

Defina as variáveis de ambiente abaixo para facilitar a ação de copiar e colar os comandos do 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

O Cloud Shell vem com as ferramentas que você vai usar neste codelab, a ferramenta de linha de comando gcloud, a interface de linha de comando cbt e o Maven, que já estão instalados.

Execute este comando para ativar as APIs do Cloud Bigtable.

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

Crie uma instância executando o seguinte comando:

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

Após criar a instância, preencha o arquivo de configuração cbt e crie uma tabela e um grupo de colunas executando os seguintes comandos:

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

cbt createtable $TABLE_ID
cbt createfamily $TABLE_ID cf

3. Saiba como gravar no Bigtable com o Dataflow

Noções básicas de escrita

Ao gravar no Cloud Bigtable, você precisa fornecer um objeto de configuração CloudBigtableTableConfiguration. Esse objeto especifica o ID do projeto e o ID da instância para sua tabela, bem como o nome da própria tabela:

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

Em seguida, o pipeline pode transmitir objetos Mutation do HBase, que podem incluir as funções 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));

O job LoadData Dataflow

A próxima página vai mostrar como executar o job LoadData, mas aqui vou chamar as partes importantes do pipeline.

Para gerar dados, você vai criar um pipeline que usa a classe GenerateSequence (de modo semelhante a uma repetição "for") para gravar várias linhas com alguns megabytes de dados aleatórios. A rowkey será o número de sequência preenchido e invertido, de modo que 250 se tornará 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. Gerar dados no Bigtable e monitorar a entrada

Os comandos a seguir vão executar um job do Dataflow que gera 40 GB de dados na sua tabela, mais do que o suficiente para a ativação do Key Visualizer:

Ative a API Cloud Dataflow

gcloud services enable dataflow.googleapis.com

Acesse o código no GitHub e mude para o diretório

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

Gere os dados (o script leva cerca de 15 minutos)

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"

Monitorar a importação

É possível monitorar o job na IU do Cloud Dataflow. Além disso, é possível visualizar a carga na instância do Cloud Bigtable com a IU de monitoramento.

Na interface do Dataflow, é possível ver o gráfico do job e as diversas métricas dele, incluindo elementos processados, vCPUs atuais e capacidade.

9cecc290f5acea15.png

abb0561342dc6b60.png

O Bigtable tem ferramentas de monitoramento padrão para operações de leitura/gravação, armazenamento usado, taxa de erros e muito mais no nível da instância, do cluster e da tabela. Além disso, o Bigtable tem o Key Visualizer, que detalha o uso com base nas chaves de linha que serão utilizadas quando pelo menos 30 GB de dados forem gerados.

996f8589332dfc19.png

5. Saiba: como ler do Bigtable com o Dataflow

Noções básicas de leitura

Ao ler no Cloud Bigtable, é necessário fornecer um objeto de configuração CloudBigtableTableScanConfiguration. É semelhante a CloudBigtableTableConfiguration, mas é possível especificar as linhas a serem verificadas e lidas.

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

Em seguida, use-o para iniciar o pipeline:

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

No entanto, se você quiser fazer uma leitura como parte do pipeline, transmita um CloudBigtableTableConfiguration para um doFn que estenda o AbstractCloudBigtableTableDoFn.

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

Em seguida, chame super() com sua configuração e getConnection() para receber uma conexão distribuída.

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

O job ReadData Dataflow

Neste codelab, você precisará ler a tabela a cada segundo para iniciar o pipeline com uma sequência gerada que aciona vários intervalos de leitura com base no horário em que um arquivo CSV é inserido.

É preciso fazer alguns cálculos para determinar quais intervalos de linhas devem ser verificados de acordo com o tempo, mas você pode clicar no nome do arquivo para ver o código-fonte se quiser saber mais.

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. Como criar sua obra-prima

ad9c4c0b90626a3b.png

Agora que você sabe como carregar dados no Bigtable e ler essas informações com o Dataflow, execute o comando final, que vai gerar uma imagem da Mona Lisa por 8 horas.

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"

Existe um bucket com imagens existentes que você pode usar. Outra opção é criar um arquivo de entrada a partir de suas próprias imagens com esta ferramenta e, em seguida, fazer upload delas para um bucket público do GCS.

Os nomes dos arquivos são feitos com base no exemplo de gs://keyviz-art/[painting]_[hours]h.txt: gs://keyviz-art/american_gothic_4h.txt

opções de pintura:

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

opções de hora: 1, 4, 8, 12, 24, 48, 72, 96, 120, 144

Torne público o bucket ou arquivo do GCS atribuindo a allUsers o papel Storage Object Viewer.

ee089815364150d2.png

Depois de escolher a imagem, basta alterar o parâmetro --file-path neste 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. Verificar mais tarde

A imagem no tamanho original pode levar algumas horas para ganhar vida, mas após 30 minutos você começará a notar atividades no visualizador principal. É possível testar vários parâmetros: zoom, brilho e métrica. É possível aplicar zoom usando a roda de rolagem do mouse ou arrastando um retângulo na grade do principal visualizador.

O brilho muda a escala da imagem, o que é útil se você quiser analisar detalhadamente uma área muito quente.

8e847f03df25572b.png

Também é possível definir qual métrica é exibida. Há OPs, cliente de leitura de bytes e cliente de gravação, para citar alguns. "Ler bytes de cliente" parece produzir imagens suaves, enquanto as "Ops" produz imagens com mais linhas, o que pode ficar muito legal em algumas imagens.

33eb5dcf4e4be861.png

8. Concluir

Fazer uma limpeza para evitar cobranças

Para evitar cobranças na sua conta do Google Cloud Platform pelos recursos usados neste codelab, exclua sua instância.

gcloud bigtable instances delete $INSTANCE_ID

O que vimos

  • Como gravar no Bigtable com o Dataflow
  • Leitura do Bigtable com Dataflow (no início do pipeline, no meio do pipeline)
  • Como usar as ferramentas de monitoramento do Dataflow
  • Como usar as ferramentas de monitoramento do Bigtable, incluindo o Key Visualizer

Próximas etapas