Cloud Bigtable cho người dùng Cassandra

1. Giới thiệu

Lớp học lập trình này là hướng dẫn cho bất kỳ ai đang di chuyển truy vấn từ Apache Cassandra sang Google Cloud Bigtable.

Trong lớp học lập trình này, bạn sẽ

  • Sử dụng trình mô phỏng Cloud Bigtable
  • Khám phá trường hợp sử dụng chuỗi thời gian
  • Tạo bảng và nhóm cột
  • Tìm hiểu các tính năng tương đương của Cloud Bigtable Java với tính năng Chèn, Cập nhật, Chọn và Xoá CQL

Bạn đánh giá trải nghiệm sử dụng Google Cloud Platform 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. Thiết lập

Bạn sẽ xem một tập dữ liệu mẫu chỉ có vài hàng để nhanh chóng nắm bắt các khái niệm chính.

Cassandra

Các truy vấn Cassandra tương đương sẽ xuất hiện ở mỗi bước, vì vậy, bạn có thể theo dõi một cụm cục bộ nếu muốn, hoặc bạn có thể nhanh chóng thiết lập một cụm Cassandra nhấp để triển khai và SSH vào cụm đó.

Nếu bạn đang theo dõi, hãy tạo và sử dụng một không gian phím. Chiến lược sao chép sẽ không quan trọng ở đây.

cqlsh> create keyspace mykeyspace with replication = {'class':'SimpleStrategy','replication_factor' : 2};
cqlsh> use mykeyspace;

Cloud Bigtable

Bạn cần có một thực thể Cloud Bigtable cho bảng của mình. Bạn có thể thiết lập một phiên bản cục bộ miễn phí bằng trình mô phỏng. Bạn sẽ không cần tạo không gian khoá trong Cloud Bigtable. Việc sao chép sẽ do cấu hình thực thể của bạn xử lý.

Sử dụng lệnh sau để khởi động trình mô phỏng:

gcloud beta emulators bigtable start

Sau đó, trong một cửa sổ hoặc thẻ shell khác, hãy đặt biến môi trường của trình mô phỏng bằng lệnh này:

$(gcloud beta emulators bigtable env-init) #Sets BIGTAB`LE_EMULATOR_HOST

Sau đó, hãy tạo một dự án Java mà bạn sẽ dùng để chạy các mã ví dụ và nhập ứng dụng Cloud Bigtable với Maven, Gradle hoặc SBT. Sau đó, trong một tệp Java mới, hãy tạo kết nối với ứng dụng dữ liệu.

BigtableDataSettings settings =
    BigtableDataSettings.newBuilder().setProjectId(projectId).setInstanceId(instanceId).build();

try {
  dataClient = BigtableDataClient.create(settings);
} catch (Exception e) {
  System.out.println("Error during data client connection: \n" + e.toString());
}

3. Tạo bảng

Trong cả bảng Cassandra và Cloud Bigtable, mỗi hàng đều có một khoá liên kết với nó. Khoá Cassandra có một khoá phân vùng và cột phân cụm có thể riêng biệt hoặc chồng chéo. Toàn bộ các khoá của Cloud Bigtable đều được dùng để phân tách (phân vùng) và sắp xếp. Hai hệ thống này cực kỳ giống nhau khi xây dựng khoá chính/khoá hàng. Về cơ bản, cả hai hệ thống đều là danh sách được sắp xếp theo từ điển, trong đó các khoá đóng vai trò là hình thức phân phối hàng chính giữa các nút. Trong hầu hết các trường hợp, bạn có thể sử dụng lại cùng một khoá cho Cloud Bigtable.

Trong lớp học lập trình này, bạn sẽ sử dụng Cloud Bigtable để lưu trữ dữ liệu chuỗi thời gian về điện thoại di động và máy tính bảng di động (đừng nhầm lẫn với máy tính bảng Bigtable.) Dưới đây là hướng dẫn tạo bảng.

Cassandra

cqlsh:mykeyspace> create table mobileTimeSeries (
           deviceid text,
           devicetype text,
           date date,
           connected_cell map<timestamp,Boolean>, 
           os_build text, 
           os_name text,
           PRIMARY KEY((devicetype, deviceid), date));

Cloud Bigtable

Bạn có thể tạo một bảng và nhóm cột bằng ứng dụng Java, nhưng cách dễ nhất là sử dụng lệnh sau đây với công cụ cbt:

cbt createtable mobile-time-series families=stats_summary

Cloud Bigtable là một cơ sở dữ liệu NoSQL, vì vậy, bạn sẽ không cần xác định giản đồ khi tạo bảng, nhưng cần suy nghĩ về các truy vấn mà bạn sẽ chạy và tối ưu hóa khoá hàng cho các truy vấn đó.

Chiến lược phổ biến nhất để di chuyển khoá chỉ đơn giản là lấy tất cả các khoá phân vùng và cột phân cụm rồi kết hợp chúng để tạo thành một chuỗi đại diện cho khoá hàng của Cloud Bigtable. Thường thì bạn nên sử dụng khoá dựa trên chuỗi vì những khoá này giúp gỡ lỗi cho quá trình phân phối khoá thông qua Key Visualr. Bạn có thể sử dụng dấu phân cách như hàm băm "#" giữa các giá trị cột để giúp dễ đọc.

Trong ví dụ này, chúng tôi sẽ sử dụng khoá hàng là "[DEVICE_TYPE]#[DEVICE_ID]#[YYYYMMDD]"

4. Phụ trang

Cách chèn khá giống nhau giữa Cassandra và Cloud Bigtable. Tại đây, bạn sẽ chèn một hàng, sau đó chèn nhiều hàng bằng cách sử dụng khoá hàng là "[DEVICE_TYPE]#[DEVICE_ID]#[YYYYMMDD]".

Cassandra

Đơn

cqlsh:mykeyspace> insert into mobileTimeSeries (deviceid, devicetype, date, connected_cell, os_build) values ('4c410523', 'phone',toDate(now()), {toTimeStamp(now()): true}, 'PQ2A.190405.003');

Theo lô

cqlsh:mykeyspace> BEGIN BATCH
insert into mobileTimeSeries (deviceid, devicetype, date, os_name, os_build) values ('a0b81f74', 'tablet', '2019-01-01', 'chromeos', '12155.0.0-rc1');
insert into mobileTimeSeries (deviceid, devicetype, date, os_name, os_build) values ('a0b81f74', 'tablet', '2019-01-02','chromeos', '12145.0.0-rc6');
APPLY BATCH;

Cloud Bigtable

Đơn

Tạo một đột biến bằng khoá hàng và dữ liệu mà bạn muốn dùng, sau đó áp dụng đột biến đó cho ứng dụng dữ liệu. Bạn sẽ thêm một hàng dữ liệu cho điện thoại có thông tin về kết nối di động và hệ điều hành của điện thoại đó.

try {
  System.currentTimeMillis();
  long timestamp = (long) 1556712000 * 1000; // Timestamp of June 1, 2019 12:00

  String rowKey = "phone#4c410523#20190501";
  ByteString one = ByteString.copyFrom(new byte[] {0, 0, 0, 0, 0, 0, 0, 1});

  RowMutation rowMutation =
      RowMutation.create(tableId, rowKey)
          .setCell(
              COLUMN_FAMILY_NAME,
              ByteString.copyFrom("connected_cell".getBytes()),
              timestamp,
              one)
          .setCell(COLUMN_FAMILY_NAME, "os_build", timestamp, "PQ2A.190405.003");

  dataClient.mutateRow(rowMutation);
} catch (Exception e) {
  System.out.println("Error during Write: \n" + e.toString());
}

Theo lô

Xác định nhiều lần đột biến trên một đối tượng BulkMutation, sau đó dùng ứng dụng dữ liệu để áp dụng tất cả các lần đột biến bằng một lệnh gọi API. Bạn sẽ thêm dữ liệu trong vài ngày về tên và phiên bản hệ điều hành của máy tính bảng trên thiết bị di động.

try {
  long timestamp = (long) 1556712000 * 1000; // Timestamp of June 1, 2019 12:00

  BulkMutation bulkMutation =
      BulkMutation.create(tableId)
          .add(
              "tablet#a0b81f74#20190501",
              Mutation.create()
                  .setCell(COLUMN_FAMILY_NAME, "os_name", timestamp, "chromeos")
                  .setCell(COLUMN_FAMILY_NAME, "os_build", timestamp, "12155.0.0-rc1"))
          .add(
              "tablet#a0b81f74#20190502",
              Mutation.create()
                  .setCell(COLUMN_FAMILY_NAME, "os_name", timestamp, "chromeos")
                  .setCell(COLUMN_FAMILY_NAME, "os_build", timestamp, "12155.0.0-rc6"));

  dataClient.bulkMutateRows(bulkMutation);
} catch (Exception e) {
  System.out.println("Error during WriteBatch: \n" + e.toString());
}

5. Nội dung cập nhật

Tại đây, bạn sẽ cập nhật một ô chưa được ghi rồi ghi một giá trị mới vào ô đó trong khi vẫn giữ lại các phiên bản trước đó.

Cassandra

Thêm ô

cqlsh:mykeyspace> UPDATE mobileTimeSeries SET os_name = 'android' WHERE devicetype='phone' AND deviceid = '4c410523' AND date = '2019-09-06';

Cập nhật các ô

cqlsh:mykeyspace> UPDATE mobileTimeSeries SET connected_cell = connected_cell +  {toTimeStamp(now()): false} WHERE devicetype='phone' AND deviceid = '4c410523' AND date = '2019-09-06';

Cloud Bigtable

Trong Cloud Bigtable, bạn có thể xử lý các bản cập nhật giống như hoạt động ghi.

Thêm ô

Việc này cũng giống như việc viết các ô, chỉ cần cung cấp một cột mà trước đây bạn chưa ghi vào. Tại đây, bạn sẽ thêm tên hệ điều hành vào hàng của điện thoại.

try {
  long timestamp = (long) 1556713800 * 1000; // Timestamp of June 1, 2019 12:30

  String rowKey = "phone#4c410523#20190501";

  RowMutation rowMutation =
      RowMutation.create(tableId, rowKey)
          .setCell(COLUMN_FAMILY_NAME, "os_name", timestamp, "android");

  dataClient.mutateRow(rowMutation);
} catch (Exception e) {
  System.out.println("Error during update: \n" + e.toString());
}

Đang cập nhật ô

Tại đây, bạn sẽ thêm một dữ liệu mới về trạng thái kết nối di động của điện thoại. Bạn có thể dễ dàng sử dụng phiên bản ô để lưu trữ một phần dữ liệu của chuỗi thời gian. Bạn chỉ cần cung cấp dấu thời gian để ghi và thêm một phiên bản mới cho ô. Để làm sạch dữ liệu, bạn có thể sử dụng tính năng thu gom rác để xoá các phiên bản sau một khoảng thời gian hoặc một khoảng thời gian nhất định.

try {
  long timestamp = (long) 1556713800 * 1000; // Timestamp of June 1, 2019 12:30

  String rowKey = "phone#4c410523#20190501";

  ByteString zero = ByteString.copyFrom(new byte[] {0, 0, 0, 0, 0, 0, 0, 0});

  RowMutation rowMutation =
      RowMutation.create(tableId, rowKey)
          .setCell(
              COLUMN_FAMILY_NAME,
              ByteString.copyFrom("connected_cell".getBytes()),
              timestamp,
              zero);

  dataClient.mutateRow(rowMutation);
} catch (Exception e) {
  System.out.println("Error during update2: \n" + e.toString());
}

6. Chọn

Bây giờ, bạn sẽ truy xuất dữ liệu đã ghi vào bảng. Khi di chuyển câu lệnh chọn CQL, bạn cần xem xét một số khía cạnh của câu lệnh chọn lọc, chẳng hạn như cột, lọc theo mệnh đề where, cũng như giới hạn và tổng hợp các hàm như nhóm theo. Ở đây, bạn chỉ xem xét hai câu lệnh chọn đơn giản để có ý tưởng cơ bản, nhưng có thể xem trong tài liệu để biết thêm thông tin về cách chọn. Trong Cloud Bigtable có hai loại thao tác truy xuất: Tải và Quét. Truy xuất một hàng trong khi quá trình quét truy xuất hàng loạt hàng.

Cassandra

Đơn

cqlsh:mykeyspace> SELECT * FROM mobileTimeSeries WHERE devicetype='phone' AND deviceid = '4c410523' AND date = '2019-09-04';

Nhiều

cqlsh:mykeyspace> SELECT * FROM mobileTimeSeries WHERE devicetype='tablet' AND deviceid = 'a0b81f74' AND date >= '2019-09-04';

Cloud Bigtable

Độc thân

Sử dụng tra cứu hàng để lấy dữ liệu cho một số điện thoại cụ thể vào ngày cụ thể, tất cả đều nằm trong một hàng. Thao tác này sẽ trả về từng phiên bản có dấu thời gian của các giá trị, vì vậy, bạn sẽ thấy hai dòng cho connect_cell tại các dấu thời gian khác nhau.

try {
  String rowKey = "phone#4c410523#20190501";

  Row row = dataClient.readRow(tableId, rowKey);
  for (RowCell cell : row.getCells()) {

    System.out.printf(
        "Family: %s    Qualifier: %s    Value: %s    Timestamp: %s%n",
        cell.getFamily(),
        cell.getQualifier().toStringUtf8(),
        cell.getValue().toStringUtf8(),
        cell.getTimestamp());
  }
} catch (Exception e) {
  System.out.println("Error during lookup: \n" + e.toString());
}

Nhiều

Sử dụng tính năng quét phạm vi để xem dữ liệu của một tháng trên một máy tính bảng di động cụ thể được trải đều trên nhiều hàng. Bạn có thể sử dụng bộ lọc với các giá trị này để chỉ lấy những phiên bản nhất định của dữ liệu hoặc lọc các giá trị.

try {
  Query query = Query.create(tableId).range("tablet#a0b81f74#201905", "tablet#a0b81f74#201906");
  ServerStream<Row> rowStream = dataClient.readRows(query);
  for (Row row : rowStream) {
    System.out.println("Row Key: " + row.getKey().toStringUtf8());
    for (RowCell cell : row.getCells()) {

      System.out.printf(
          "Family: %s    Qualifier: %s    Value: %s    Timestamp: %s%n",
          cell.getFamily(),
          cell.getQualifier().toStringUtf8(),
          cell.getValue().toStringUtf8(),
          cell.getTimestamp());
    }
  }
} catch (Exception e) {
  System.out.println("Error during scan: \n" + e.toString());
}

7. Xóa

Tại đây, bạn sẽ xoá dữ liệu đã đưa vào bảng. Trước tiên, bạn cần xoá từng hàng, sau đó bạn xoá nhiều hàng.

CQL của Cassandra cho phép xoá một hàng cũng như xoá dải ô khi tất cả các cột chính được chỉ định. Bạn có thể thực hiện điều này với Bigtable bằng cách quét một dải ô rồi thực hiện xoá ở cấp độ hàng. Lưu ý rằng bạn sẽ nhận được kết quả tương tự, nhưng sẽ có nhiều thao tác hơn vì mỗi thao tác xoá sẽ là một thao tác riêng.

Cassandra

Đơn

cqlsh:mykeyspace> DELETE from mobileTimeSeries where devicetype='phone' and deviceid = '4c410523';

Nhiều

cqlsh:mykeyspace> DELETE from mobileTimeSeries where devicetype='tablet' and deviceid = 'a0b81f74';

Cloud Bigtable

Đơn

Tại đây, bạn sẽ xoá dữ liệu của một số điện thoại và ngày cụ thể. Sử dụng phím hàng để xoá từng hàng một.

try {
  String rowKey = "phone#4c410523#20190501";

  RowMutation mutation = RowMutation.create(tableId, rowKey).deleteRow();

  dataClient.mutateRow(mutation);
} catch (Exception e) {
  System.out.println("Error during Delete: \n" + e.toString());
}

Nhiều

Tại đây, bạn sẽ xóa tất cả dữ liệu về một máy tính bảng di động cụ thể. Để di chuyển một truy vấn CQL xoá nhiều hàng, bạn cần thực hiện quét rồi xoá từng hàng bằng cách sử dụng tập hợp các khoá hàng thu được.

try {
  Query query = Query.create(tableId).prefix("tablet#a0b81f7");
  ServerStream<Row> rowStream = dataClient.readRows(query);
  BulkMutation bulkMutation = BulkMutation.create(tableId);
  for (Row row : rowStream) {
    bulkMutation.add(row.getKey(), Mutation.create().deleteRow());
  }

  dataClient.bulkMutateRows(bulkMutation);
} catch (Exception e) {
  System.out.println("Error during DeleteMultiple: \n" + e.toString());
}

8. Sắp hoàn tất

Dọn dẹp

Cassandra

Nếu bạn đã tạo một cụm Cassandra để tiếp tục theo dõi thao tác này, hãy xoá cụm này như bình thường.

Cloud Bigtable

Nếu đã tạo bảng trên một thực thể Cloud Bigtable hiện có, bạn có thể xoá bảng đó bằng lệnh cbt

cbt deletetable mobile-time-series

Nếu dùng trình mô phỏng, bạn có thể dừng trình mô phỏng để hoàn thành mọi công việc bằng cách nhập Ctrl-C vào cửa sổ dòng lệnh mà bạn đã khởi động.

Các bước tiếp theo