Bigtable и Dataflow: искусство мониторинга баз данных (клиент HBase Java)

1. Введение

В этой лабораторной работе вы будете использовать инструменты мониторинга Cloud Bigtable для создания различных произведений искусства посредством записи и чтения данных с помощью Cloud Dataflow и клиента Java HBase .

Вы узнаете, как

  • Загружайте большие объемы данных в Bigtable с помощью Cloud Dataflow.
  • Отслеживайте экземпляры и таблицы Bigtable по мере приема данных.
  • Запрос Bigtable с помощью задания потока данных
  • Изучите ключевой инструмент визуализатора, который можно использовать для поиска «горячих точек» в зависимости от конструкции вашей схемы.
  • Создавайте произведения искусства с помощью ключевого визуализатора

d098cc81f78f02eb.png

Как бы вы оценили свой опыт использования Cloud Bigtable?

Новичок Средний Опытный

Как вы будете использовать этот урок?

Прочтите только до конца Прочитайте его и выполните упражнения.

2. Создайте базу данных Bigtable.

Cloud Bigtable — это служба баз данных больших данных NoSQL от Google. Это та же самая база данных, которая поддерживает многие основные службы Google, включая поиск, аналитику, карты и Gmail. Он идеально подходит для выполнения больших аналитических рабочих нагрузок и создания приложений с малой задержкой. Подробную информацию можно найти в разделе «Введение в Cloud Bigtable Codelab» .

Создать проект

Сначала создайте новый проект. Используйте встроенную Cloud Shell, которую можно открыть, нажав кнопку «Активировать Cloud Shell» в правом верхнем углу.

a74d156ca7862b28.png

Установите следующие переменные среды, чтобы упростить копирование и вставку команд 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 поставляется с инструментами, которые вы будете использовать в этой лаборатории: инструмент командной строки gcloud , интерфейс командной строки cbt и Maven , которые уже установлены.

Включите API Cloud Bigtable, выполнив эту команду.

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

Создайте экземпляр, выполнив следующую команду:

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

После создания экземпляра заполните файл конфигурации cbt, а затем создайте семейство таблиц и столбцов, выполнив следующие команды:

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

cbt createtable $TABLE_ID
cbt createfamily $TABLE_ID cf

3. Узнайте: запись в Bigtable с помощью Dataflow

Основы письма

При записи в Cloud Bigtable необходимо предоставить объект конфигурации CloudBigtableTableConfiguration . Этот объект указывает идентификатор проекта и идентификатор экземпляра вашей таблицы, а также имя самой таблицы:

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

Затем ваш конвейер сможет передавать объекты HBase Mutation , которые могут включать Put и 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));

Задание потока данных LoadData

На следующей странице будет показано, как запустить задание LoadData, но здесь я назову важные части конвейера.

Для генерации данных вы создадите конвейер, который использует класс GenerateSequence (аналогично циклу for) для записи ряда строк с несколькими мегабайтами случайных данных. Ключ строки будет дополненным и перевернутым порядковым номером, поэтому 250 станет 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. Генерируйте данные в Bigtable и отслеживайте приток

Следующие команды запустят задание потока данных, которое сгенерирует в вашу таблицу 40 ГБ данных, что более чем достаточно для активации Key Visualizer:

Включите API Cloud Dataflow

gcloud services enable dataflow.googleapis.com

Получите код с github и перейдите в каталог.

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

Сгенерируйте данные (скрипт занимает около 15 минут)

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"

Контролируйте импорт

Вы можете отслеживать задание в пользовательском интерфейсе Cloud Dataflow . Кроме того, вы можете просмотреть нагрузку на свой экземпляр Cloud Bigtable с помощью пользовательского интерфейса мониторинга .

В пользовательском интерфейсе потока данных вы сможете увидеть график задания и различные показатели задания, включая обработанные элементы, текущие виртуальные ЦП и пропускную способность.

9cecc290f5acea15.png

abb0561342dc6b60.png

Bigtable имеет стандартные инструменты мониторинга операций чтения/записи, используемого хранилища, частоты ошибок и многого другого на уровне экземпляра, кластера и таблицы. Помимо этого, в Bigtable также есть Key Visualizer , который разбивает ваше использование на основе ключей строк, которые мы будем использовать после того, как будет сгенерировано не менее 30 ГБ данных.

996f8589332dfc19.png

5. Изучите: чтение из Bigtable с помощью Dataflow.

Основы чтения

При чтении из Cloud Bigtable необходимо предоставить объект конфигурации CloudBigtableTableScanConfiguration . Это похоже на CloudBigtableTableConfiguration , но вы можете указать строки для сканирования и чтения.

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

Затем используйте это для запуска вашего конвейера:

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

Однако если вы хотите выполнить чтение в рамках своего конвейера, вы можете передать CloudBigtableTableConfiguration в doFn , который расширяет AbstractCloudBigtableTableDoFn .

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

Затем вызовите super() с вашей конфигурацией и getConnection() чтобы получить распределенное соединение.

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

Задание ReadData Dataflow

Для этой лаборатории кода вам нужно будет считывать данные из таблицы каждую секунду, чтобы вы могли запустить конвейер с сгенерированной последовательностью, которая запускает несколько диапазонов чтения в зависимости от времени ввода CSV-файла.

Чтобы определить, какие диапазоны строк сканировать с учетом времени, нужно немного математики, но вы можете щелкнуть имя файла, чтобы просмотреть исходный код, если хотите узнать больше.

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. Создание своего шедевра

ad9c4c0b90626a3b.png

Теперь, когда вы понимаете, как загружать данные в Bigtable и читать их с помощью Dataflow, вы можете запустить последнюю команду, которая сгенерирует изображение Моны Лизы за 8 часов.

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"

Существует ведро с существующими изображениями, которые вы можете использовать. Или вы можете создать с помощью этого инструмента входной файл из любого собственного изображения , а затем загрузить его в общедоступную корзину GCS.

Имена файлов создаются из gs://keyviz-art/[painting]_[hours]h.txt пример: gs://keyviz-art/american_gothic_4h.txt

варианты покраски:

  • американская_готика
  • мона_лиса
  • жемчужная_серьга
  • постоянство_памяти
  • звездная_ночь
  • воскресенье_после полудня
  • the_scream

варианты часов: 1, 4, 8, 12, 24, 48, 72, 96, 120, 144.

Сделайте корзину или файл GCS общедоступным, предоставив allUsers роль Storage Object Viewer .

ee089815364150d2.png

Выбрав изображение, просто измените параметр --file-path в этой команде:

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. Проверьте это позже

Полное изображение может появиться через несколько часов, но через 30 минут вы должны начать видеть активность в ключевом визуализаторе. Есть несколько параметров, с которыми вы можете играть: масштабирование, яркость и метрика. Вы можете масштабировать изображение, используя колесо прокрутки мыши или перетаскивая прямоугольник на сетке ключевого визуализатора.

Яркость изменяет масштаб изображения, что полезно, если вы хотите подробно рассмотреть очень горячую область.

8e847f03df25572b.png

Вы также можете настроить, какой показатель будет отображаться. Есть OP, клиент чтения байтов, клиент записи байтов и многие другие. «Клиент чтения байтов», кажется, создает плавные изображения, а «Ops» создает изображения с большим количеством линий, которые могут выглядеть очень круто на некоторых изображениях.

33eb5dcf4e4be861.png

8. Завершите

Наведите порядок, чтобы избежать обвинений

Чтобы избежать взимания платы с вашей учетной записи Google Cloud Platform за ресурсы, используемые в этой лаборатории кода, вам следует удалить свой экземпляр.

gcloud bigtable instances delete $INSTANCE_ID

Что мы рассмотрели

  • Запись в Bigtable с помощью Dataflow
  • Чтение из Bigtable с помощью Dataflow (в начале вашего конвейера, в середине вашего конвейера)
  • Использование инструментов мониторинга потока данных
  • Использование инструментов мониторинга Bigtable, включая Key Visualizer

Следующие шаги