Bigtable và Dataflow: Nghệ thuật giám sát cơ sở dữ liệu (Ứng dụng HBase Java)

1. Giới thiệu

Trong lớp học lập trình này, bạn sẽ sử dụng các công cụ giám sát của Cloud Bigtable để tạo ra nhiều tác phẩm nghệ thuật bằng cách ghi và đọc dữ liệu bằng Cloud Dataflowứng dụng Java HBase.

Bạn sẽ tìm hiểu cách

  • Tải một lượng lớn dữ liệu lên Bigtable bằng Cloud Dataflow
  • Theo dõi các phiên bản và bảng Bigtable khi nhập dữ liệu của bạn
  • Truy vấn Bigtable bằng cách sử dụng công việc Dataflow
  • Khám phá công cụ trình hiển thị khoá có thể dùng để tìm điểm phát sóng do cách thiết kế giản đồ của bạn
  • Sáng tạo nghệ thuật bằng video nhạc đơn giản

d098cc81f78f02eb.png

Bạn đánh giá trải nghiệm sử dụng Cloud Bigtable như thế nào?

Người mới tập Trung cấp Thành thạo

Bạn sẽ sử dụng hướng dẫn này như thế nào?

Chỉ có thể đọc Đọc và hoàn thành bài tập

2. Tạo cơ sở dữ liệu Bigtable

Cloud Bigtable là dịch vụ cơ sở dữ liệu NoSQL Big Data của Google. Nền tảng này cũng là cơ sở dữ liệu hỗ trợ nhiều dịch vụ chính của Google, bao gồm Tìm kiếm, Analytics, Maps và Gmail. Giải pháp này rất lý tưởng để chạy các tải công việc phân tích lớn và xây dựng các ứng dụng có độ trễ thấp. Hãy xem Giới thiệu về Lớp học lập trình Cloud Bigtable để được giới thiệu chuyên sâu.

Tạo một dự án

Trước tiên, hãy tạo một dự án mới. Sử dụng Cloud Shell tích hợp sẵn mà bạn có thể mở bằng cách nhấp vào liên kết "Kích hoạt Cloud Shell" ở góc trên bên phải.

a74d156ca7862b28.png

Thiết lập các biến môi trường sau để giúp việc sao chép và dán các lệnh trong lớp học lập trình dễ dàng hơn:

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 đi kèm với các công cụ mà bạn sẽ sử dụng trong lớp học lập trình này, bao gồm công cụ dòng lệnh gcloud, giao diện dòng lệnh cbtMaven, đã được cài đặt.

Bật Cloud Bigtable API bằng cách chạy lệnh này.

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

Tạo một thực thể bằng cách chạy lệnh sau:

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

Sau khi bạn tạo phiên bản, hãy điền vào tệp cấu hình cbt rồi tạo một bảng và nhóm cột bằng cách chạy các lệnh sau:

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

cbt createtable $TABLE_ID
cbt createfamily $TABLE_ID cf

3. Tìm hiểu: Ghi vào Bigtable bằng Dataflow

Kiến thức cơ bản về việc viết lách

Khi ghi vào Cloud Bigtable, bạn phải cung cấp đối tượng cấu hình CloudBigtableTableConfiguration. Đối tượng này chỉ định mã dự án và mã phiên bản cho bảng, cũng như tên của bảng:

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

Sau đó, quy trình của bạn có thể truyền các đối tượng HBase Mutation, có thể bao gồm Put và 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));

Công việc LoadData Dataflow

Trang tiếp theo sẽ chỉ cho bạn cách chạy công việc LoadData, nhưng ở đây tôi sẽ gọi ra các phần quan trọng đối với quy trình.

Để tạo dữ liệu, bạn sẽ tạo một quy trình sử dụng lớp GenerateSequence (tương tự như một vòng lặp for) để ghi một số hàng với vài megabyte dữ liệu ngẫu nhiên. Khoá hàng sẽ là số thứ tự được thêm vào và đảo ngược, vì vậy 250 trở thành 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. Tạo dữ liệu vào Bigtable và theo dõi luồng thu

Các lệnh sau sẽ chạy công việc dataflow tạo ra 40 GB dữ liệu trong bảng của bạn, quá đủ để Trình hiển thị chính kích hoạt:

Bật Cloud Dataflow API

gcloud services enable dataflow.googleapis.com

Lấy mã từ github và thay đổi vào thư mục

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

Tạo dữ liệu (tập lệnh mất khoảng 15 phút)

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"

Theo dõi quá trình nhập

Bạn có thể giám sát công việc trong giao diện người dùng Cloud Dataflow. Ngoài ra, bạn có thể xem tải trên thực thể Cloud Bigtable bằng giao diện người dùng giám sát của thực thể đó.

Trong giao diện người dùng Dataflow, bạn có thể thấy biểu đồ công việc và nhiều chỉ số về công việc, trong đó có các phần tử được xử lý, vCPU hiện tại và công suất.

9cecc290f5acea15.pngs

abb0561342dc6b60.png

Bigtable có các công cụ giám sát tiêu chuẩn cho các thao tác đọc/ghi, mức sử dụng bộ nhớ, tỷ lệ lỗi, v.v. ở cấp thực thể, cụm và bảng. Ngoài ra, Bigtable còn có Key Visualr (Trình hiển thị chính thức) phân tích mức sử dụng của bạn dựa trên các khoá hàng mà chúng tôi sẽ sử dụng sau khi có ít nhất 30 GB dữ liệu được tạo.

996f8589332dfc19.pngS

5. Tìm hiểu: Đọc từ Bigtable bằng Dataflow

Kiến thức cơ bản về việc đọc

Khi đọc từ Cloud Bigtable, bạn phải cung cấp đối tượng cấu hình CloudBigtableTableScanConfiguration. Lệnh này tương tự như CloudBigtableTableConfiguration, nhưng bạn có thể chỉ định các hàng cần quét và đọc.

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

Sau đó, hãy sử dụng đoạn mã đó để bắt đầu quy trình của bạn:

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

Tuy nhiên, nếu muốn đọc trong quy trình của mình, bạn có thể truyền CloudBigtableTableConfiguration đến doFn mở rộng AbstractCloudBigtableTableDoFn.

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

Sau đó, hãy gọi super() cùng với cấu hình của bạn và getConnection() để nhận kết nối được phân phối.

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

Công việc ReadData Dataflow

Đối với lớp học lập trình này, bạn cần đọc dữ liệu trên bảng mỗi giây để có thể bắt đầu quy trình bằng một trình tự được tạo kích hoạt nhiều phạm vi đọc dựa trên thời gian mà tệp CSV đã nhập.

Có một chút toán học để xác định dải hàng nào cần quét theo thời gian, nhưng bạn có thể nhấp vào tên tệp để xem mã nguồn nếu muốn tìm hiểu thêm.

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. Đang tạo kiệt tác của bạn

ad9c4c0b90626a3b.png

Bây giờ bạn đã hiểu cách tải dữ liệu vào Bigtable và đọc từ đó bằng Dataflow, bạn có thể chạy lệnh cuối cùng sẽ tạo ra hình ảnh của Mona Lisa trong hơn 8 giờ.

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"

Bạn có thể sử dụng một bộ chứa hình ảnh hiện có. Hoặc bạn có thể tạo tệp đầu vào từ bất kỳ hình ảnh nào của riêng bạn bằng công cụ này, sau đó tải chúng lên một bộ chứa GCS công khai.

Tên tệp được tạo từ gs://keyviz-art/[painting]_[hours]h.txt ví dụ: gs://keyviz-art/american_gothic_4h.txt

cách vẽ:

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

Lựa chọn giờ: 1, 4, 8, 12, 24, 48, 72, 96, 120, 144

Chuyển bộ chứa hoặc tệp GCS của bạn sang chế độ công khai bằng cách cấp cho allUsers vai trò Storage Object Viewer.

ee089815364150d2.png

Sau khi đã chọn hình ảnh, bạn chỉ cần thay đổi tham số --file-path trong lệnh sau:

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. Kiểm tra lại sau

Hình ảnh đầy đủ có thể mất vài giờ để hiển thị, nhưng sau 30 phút, bạn sẽ bắt đầu thấy hoạt động trong trình hiển thị hình ảnh chính. Có một vài thông số bạn có thể thử nghiệm: mức thu phóng, độ sáng và chỉ số. Bạn có thể thu phóng bằng con lăn chuột hoặc kéo một hình chữ nhật trên lưới trình hiển thị phím.

Độ sáng thay đổi tỷ lệ của hình ảnh. Điều này rất hữu ích nếu bạn muốn quan sát chuyên sâu một khu vực rất nóng.

8e847f03df25572b.pngS

Bạn cũng có thể điều chỉnh chỉ số nào sẽ được hiển thị. Có OP, ứng dụng Đọc byte, Ghi ứng dụng khách byte và một số ứng dụng khác. "Đọc ứng dụng byte" có vẻ tạo ra hình ảnh mượt mà trong khi "Ops" sẽ tạo ra hình ảnh có nhiều đường kẻ hơn, trông có thể rất thú vị trên một số hình ảnh.

33eb5dcf4e4be861.png.

8. Hoàn tất

Dọn dẹp để tránh bị tính phí

Để tránh làm phát sinh phí tài khoản Google Cloud Platform cho các tài nguyên sử dụng trong lớp học lập trình này, bạn nên xoá phiên bản của mình.

gcloud bigtable instances delete $INSTANCE_ID

Nội dung đã đề cập

  • Ghi vào Bigtable bằng Dataflow
  • Đọc từ Bigtable với Dataflow (Ở đầu quy trình, Ở giữa quy trình của bạn)
  • Sử dụng công cụ theo dõi Dataflow
  • Sử dụng các công cụ giám sát của Bigtable, bao gồm cả Key Visualr

Các bước tiếp theo