Cassandra 사용자를 위한 Cloud Bigtable

1. 소개

이 Codelab은 Apache Cassandra에서 Google Cloud Bigtable로 쿼리를 마이그레이션하는 모든 사용자를 위한 가이드입니다.

이 Codelab에서는

  • Cloud Bigtable 에뮬레이터 사용
  • 시계열 사용 사례 살펴보기
  • 테이블 및 column family 만들기
  • CQL 삽입, 업데이트, 선택, 삭제에 해당하는 Cloud Bigtable Java의 기능에 대해 알아보기

귀하의 Google Cloud Platform 사용 경험을 평가해 주세요.

초급 중급 고급

본 가이드를 어떻게 사용하실 계획인가요?

<ph type="x-smartling-placeholder"></ph> 읽기 전용 읽고 연습 활동을 완료하세요

2. 설정

핵심 개념을 빠르게 이해할 수 있도록 몇 개의 행만 있는 샘플 데이터 세트를 살펴볼 것입니다.

Cassandra

각 단계에 상응하는 Cassandra 쿼리가 있으므로 원하는 경우 로컬 클러스터를 따르거나 클릭하여 배포 Cassandra 클러스터를 빠르게 설정하고 SSH를 통해 연결할 수 있습니다.

계속 진행하는 경우 키스페이스를 만들어 사용하세요. 여기서는 복제 전략이 중요하지 않습니다.

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

Cloud Bigtable

테이블에 Cloud Bigtable 인스턴스가 있어야 합니다. 에뮬레이터를 사용하여 로컬 인스턴스를 무료로 설정할 수 있습니다. Cloud Bigtable에서는 키스페이스를 만들 필요가 없으며 인스턴스 구성에서 복제를 처리합니다.

다음 명령어를 사용하여 에뮬레이터를 시작합니다.

gcloud beta emulators bigtable start

그런 다음 다른 셸 창 또는 탭에서 다음 명령어로 에뮬레이터 환경 변수를 설정합니다.

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

그런 다음 코드 예시를 실행하는 데 사용할 Java 프로젝트를 만들고 Maven, Gradle 또는 SBT로 Cloud Bigtable 클라이언트를 가져옵니다. 그런 다음 새 Java 파일에서 데이터 클라이언트에 대한 연결을 만듭니다.

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. 테이블 만들기

Cassandra 테이블과 Cloud Bigtable 테이블 모두에서 각 행에는 연결된 키가 있습니다. Cassandra 키에는 분리되거나 중복될 수 있는 파티션 키와 클러스터링 열이 있습니다. Cloud Bigtable 키 전체가 분할 (파티션) 및 정렬에 사용됩니다. 이 두 시스템은 기본/행 키 생성에 있어 매우 유사합니다. 두 시스템 모두 기본적으로 사전순으로 정렬된 목록으로, 키가 노드 간 행 분배의 기본 형태를 취합니다. 대부분의 경우 Cloud Bigtable에 동일한 키를 재사용할 수 있습니다.

이 Codelab에서는 Cloud Bigtable을 사용하여 휴대전화 및 모바일 태블릿에 대한 시계열 데이터를 저장합니다 (Bigtable 태블릿과 혼동하지 말 것). 테이블을 만드는 방법은 다음과 같습니다.

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

자바 클라이언트를 사용하여 테이블 및 column family를 만들 수 있지만 cbt 도구와 함께 다음 명령어를 사용하는 것이 가장 쉽습니다.

cbt createtable mobile-time-series families=stats_summary

Cloud Bigtable은 NoSQL 데이터베이스이므로 테이블 생성 시 스키마를 정의할 필요는 없지만 실행할 쿼리에 대해 생각해 보고 이를 위해 row key를 최적화해야 합니다.

키 마이그레이션을 위한 가장 일반적인 전략은 모든 파티션 키와 클러스터링 열을 가져와 조인하여 Cloud Bigtable row key를 나타내는 문자열을 만드는 것입니다. 일반적으로 문자열 기반 키는 Key Visualizer를 통한 키 배포를 디버깅하는 데 도움이 되므로 사용하는 것이 좋습니다. 해시 '#'과 같은 구분자를 사용할 수 있습니다. 가독성을 높일 수 있습니다.

이 예에서는 '[DEVICE_TYPE]#[DEVICE_ID]#[YYYYMMDD]'의 rowkey를 사용합니다.

4. 삽입

삽입은 Cassandra와 Cloud Bigtable 간에 상당히 유사합니다. 여기서는 '[DEVICE_TYPE]#[DEVICE_ID]#[YYYYMMDD]'의 rowkey를 사용하여 하나의 행을 삽입한 다음 여러 행을 삽입합니다.

Cassandra

싱글

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

Batch

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

싱글

사용할 row key와 데이터로 변형을 만든 다음 데이터 클라이언트를 사용해 변형을 적용합니다. 휴대전화 연결 및 운영체제에 대한 정보가 포함된 데이터 행을 추가합니다.

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

Batch

batchMutation 객체에 여러 변형을 정의한 후 데이터 클라이언트를 사용하여 API 호출 한 번으로 모든 변형을 적용합니다. 모바일 태블릿의 운영체제 이름 및 버전에 관한 며칠 동안의 데이터를 추가합니다.

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. 업데이트

여기에서는 아직 기록되지 않은 셀을 업데이트하고 이전 버전을 유지하면서 셀에 새 값을 작성합니다.

Cassandra

셀 추가

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

셀 업데이트

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

Cloud Bigtable에서는 업데이트를 쓰기와 동일하게 취급할 수 있습니다.

셀 추가

이는 셀을 쓰는 것과 같습니다. 이전에 쓰지 않은 열을 제공하기만 하면 됩니다. 여기서 휴대전화 행에 운영체제 이름을 추가하게 됩니다.

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

셀 업데이트 중

여기에서 휴대전화의 모바일 데이터 연결 상태에 관한 새 데이터를 추가합니다. 셀 버전을 사용하면 시계열 데이터의 일부를 쉽게 저장할 수 있습니다. 쓰기에 대한 타임스탬프를 제공하기만 하면 셀에 새 버전을 추가합니다. 데이터를 정리하려면 가비지 컬렉션을 사용하여 특정 횟수 또는 일정 시간이 지난 후 버전을 삭제하면 됩니다.

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. 선택

이제 테이블에 작성한 데이터를 검색합니다. CQL select 문을 마이그레이션할 때는 열, WHERE 절을 통한 필터링, 그룹화 기준과 같은 제한 및 집계 함수와 같은 SELECT 문의 여러 측면을 고려해야 합니다. 여기서는 기본적인 아이디어를 얻기 위해 두 개의 간단한 SELECT 문만 살펴보겠지만 선택에 관한 자세한 내용은 문서를 참고하세요. Cloud Bigtable에는 가져오기와 스캔이라는 두 가지 유형의 검색 작업이 있습니다. Get은 행 1개를 가져오는 반면 스캔은 행 범위를 검색합니다.

Cassandra

싱글

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

여러 개

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

Cloud Bigtable

싱글

행 조회를 사용하여 지정된 날짜에 특정 전화에 대한 데이터를 가져옵니다. 이 데이터는 모두 한 행에 포함됩니다. 이렇게 하면 타임스탬프가 지정된 각 버전의 값이 반환되므로 서로 다른 타임스탬프에 연결된_셀이 두 개 표시됩니다.

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

여러 개

범위 스캔을 사용하여 여러 행에 분산된 지정된 모바일 태블릿에서 한 달 동안의 데이터를 볼 수 있습니다. 이 값과 함께 필터를 사용하면 특정 버전의 데이터만 가져오거나 값으로 필터링할 수 있습니다.

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. 삭제

여기에서 테이블에 입력한 데이터를 삭제합니다. 먼저 개별 행을 삭제한 다음 여러 행을 삭제합니다.

Cassandra의 CQL은 모든 기본 열이 지정된 경우 단일 행 삭제 및 범위 삭제를 허용합니다. Bigtable에서 범위를 스캔한 후 행 수준 삭제를 수행하면 됩니다. 결과는 동일하지만 각 삭제가 자체 작업이므로 작업이 더 많이 포함됩니다.

Cassandra

싱글

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

여러 개

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

Cloud Bigtable

싱글

여기에서 특정 휴대전화 및 날짜의 데이터를 삭제합니다. row key를 사용하여 한 번에 한 행씩 삭제합니다.

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

여러 개

여기에서 특정 모바일 태블릿의 모든 데이터를 삭제합니다. 여러 행을 삭제하는 CQL 쿼리를 마이그레이션하려면 스캔을 수행한 후 결과 row key 집합을 사용하여 각 행을 삭제해야 합니다.

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. 완료

정리

Cassandra

이 작업을 수행하기 위해 Cassandra 클러스터를 만든 경우 평소와 같이 삭제해도 됩니다.

Cloud Bigtable

기존 Cloud Bigtable 인스턴스에 테이블을 만든 경우 cbt 명령어를 사용하여 테이블을 삭제할 수 있습니다.

cbt deletetable mobile-time-series

에뮬레이터를 사용한 경우, 에뮬레이터를 시작한 터미널에 Ctrl + C를 입력하여 에뮬레이터를 중지하여 모든 작업을 지울 수 있습니다.

다음 단계