Cloud Bigtable dla użytkowników Cassandra

1. Wprowadzenie

To ćwiczenie w Codelabs jest przeznaczone dla każdego, kto przenosi zapytania z Apache Cassandra do Google Cloud Bigtable.

W ramach tego ćwiczenia w Codelabs

  • Używanie emulatora Cloud Bigtable
  • Poznaj przypadek użycia ciągu czasowego
  • Tworzenie tabeli i grupy kolumn
  • Poznaj odpowiedniki Cloud Bigtable w Javie dotyczące wstawiania, aktualizowania, wyboru i usuwania w CQL

Jak oceniasz swoje doświadczenia z korzystaniem z Google Cloud Platform?

Początkujący Poziom średnio zaawansowany Biegły

Jak wykorzystasz ten samouczek?

Tylko do przeczytania Przeczytaj go i wykonaj ćwiczenia
.

2. Skonfiguruj

Zobaczysz przykładowy zbiór danych zawierający tylko kilka wierszy, który pozwoli Ci szybko zrozumieć podstawowe pojęcia.

Cassandra

W każdym kroku dostępne będą takie same zapytania Cassandra, więc możesz wykonać opisane niżej czynności w klastrze lokalnym. Możesz też szybko skonfigurować klaster Cassandra, który można łatwo wdrożyć i użyć do niego SSH.

Jeśli je śledzisz, utwórz i wykorzystaj obszar klawiszy. Strategia replikacji nie będzie w tym przypadku ważna.

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

Cloud Bigtable

Potrzebujesz instancji Cloud Bigtable dla tabeli. Możesz skonfigurować instancję lokalną bezpłatnie za pomocą emulatora. Nie musisz tworzyć przestrzeni kluczy w Cloud Bigtable, replikacja jest obsługiwana przez konfigurację instancji.

Użyj tego polecenia, aby uruchomić emulator:

gcloud beta emulators bigtable start

Następnie w innym oknie powłoki lub na innej karcie ustaw zmienną środowiskową emulatora za pomocą tego polecenia:

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

Następnie utwórz projekt w Javie, którego użyjesz do uruchomienia przykładowego kodu, i zaimportuj klienta Cloud Bigtable za pomocą Maven, Gradle lub SBT. Następnie w nowym pliku Java utwórz połączenie z klientem danych.

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. Tworzenie tabeli

W tabelach Cassandra i Cloud Bigtable z każdym wierszem powiązany jest klucz. Klucze Cassandra mają klucz partycji i kolumnę grupowania, które mogą być oddzielne lub nakładać się na siebie. Do podziału (partycji) i kolejności używane są wszystkie klucze Cloud Bigtable. Te 2 systemy są bardzo podobne pod względem konstrukcji klucza podstawowego/wiersza. Oba systemy są zasadniczo posortowanymi leksykograficznie listami, na których klucze stanowią główną formę rozkładu wierszy między węzłami. W większości przypadków można wykorzystać ten sam klucz w Cloud Bigtable.

Dzięki temu ćwiczeniu w programowaniu wykorzystasz Cloud Bigtable do przechowywania danych ciągu czasowego o telefonach komórkowych i tabletach mobilnych (nie należy ich mylić z dużymi tabletami). Poniżej znajdziesz instrukcje tworzenia tabeli.

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

Tabele i grupę kolumn możesz utworzyć za pomocą klienta w języku Java, ale najłatwiej zrobisz to w narzędziu cbt:

cbt createtable mobile-time-series families=stats_summary

Cloud Bigtable to baza danych NoSQL, więc nie musisz definiować schematu podczas tworzenia tabeli, ale warto zastanowić się nad użyciem zapytań i zoptymalizować dla nich klucz wiersza.

Najpowszechniejszą strategią migracji kluczy jest po prostu połączenie wszystkich kluczy partycji i kolumn grupowych w celu utworzenia ciągu reprezentującego klucz wiersza Cloud Bigtable. Zasadniczo zalecamy używanie kluczy opartych na ciągach znaków, ponieważ pomagają one w debugowaniu dystrybucji kluczy za pomocą narzędzia Key Visualizer. Możesz używać separatora, np. znaku „#” między wartościami kolumn, aby zwiększyć czytelność.

W tym przykładzie użyjemy klucza wiersza „[DEVICE_TYPE]#[DEVICE_ID]#[RRRRMMDD]”

4. Wstawki

Wstawki są dość podobne w Cassandra i Cloud Bigtable. W tym miejscu wstawisz jeden wiersz, a potem kilka wierszy, korzystając z klucza wiersza „[DEVICE_TYPE]#[DEVICE_ID]#[RRRRMMDD]”.

Cassandra

Singiel

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

Wsad

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

Singiel

Utwórz mutację z kluczem wiersza i danymi, których chcesz użyć, a następnie zastosuj ją w kliencie danych. Dodajesz wiersz danych dotyczący telefonu z informacjami o połączeniu z siecią komórkową i systemie operacyjnym.

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

Wsad

Zdefiniuj wiele mutacji w obiekcieBulkMutation, a następnie za pomocą klienta danych zastosuj wszystkie mutacje za pomocą jednego wywołania interfejsu API. Dodajesz dane z kilku dni o nazwie i wersji systemu operacyjnego tabletu.

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. Aktualizacje

W tym przykładzie zaktualizujesz komórkę, która nie została jeszcze zapisana, a następnie wpiszesz w niej nową wartość, zachowując jednocześnie wcześniejsze wersje.

Cassandra

Dodawanie komórek

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

Aktualizowanie komórek

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

W Cloud Bigtable aktualizacje można traktować tak samo jak zapisy.

Dodawanie komórek

Ta funkcja działa tak samo jak zapisywanie komórek. Wystarczy, że dodasz kolumnę, w której dotychczas nie były zapisywane dane. W tym miejscu dodasz nazwę systemu operacyjnego do wiersza telefonu.

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

Aktualizuję komórki

Dodaj w tym miejscu nowe dane o stanie połączenia telefonu z siecią komórkową. Do łatwego przechowywania części danych ciągów czasowych możesz używać wersji komórek. Wystarczy, że podasz sygnaturę czasową zapisu, a dodasz nową wersję komórki. Aby wyczyścić dane, możesz użyć funkcji odśmiecania, aby usunąć wersje po określonej liczbie lub przez określony czas.

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. Wybiera

Teraz pobierzesz dane zapisane w tabeli. Podczas migracji instrukcji wyboru CQL musisz wziąć pod uwagę kilka aspektów instrukcji wyboru, takich jak kolumny, filtrowanie według klauzul Gdzie oraz funkcje ograniczania i agregacji, takie jak „grupuj według”. Oto 2 proste spostrzeżenia, które pomogą Ci zrozumieć podstawowe pojęcie, ale więcej informacji na ten temat znajdziesz w dokumentacji. W Cloud Bigtable dostępne są 2 typy operacji pobierania: pobieranie i skanowanie. Get pobiera 1 wiersz, a skanowanie pobiera zakres wierszy.

Cassandra

Singiel

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

Wiele

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

Cloud Bigtable

Pojedynczy

Wyszukiwanie wierszy w celu uzyskania danych o konkretnym telefonie z określonego dnia, które mieści się w jednym wierszu. Spowoduje to zwrócenie każdej wersji wartości oznaczonej sygnaturą czasową, więc powinny się pojawić 2 wiersze dla connection_cell o różnych sygnaturach czasowych.

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

Wiele

Skanowanie zakresów pozwala wyświetlić dane z określonego tabletu mobilnego z określonego miesiąca w wielu wierszach. Możesz użyć filtrów, aby uzyskać tylko określone wersje danych lub filtrować według wartości.

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. Usunięcia

W tym miejscu usuniesz dane umieszczone w tabeli. Najpierw usuń pojedynczy wiersz, a potem wiele wierszy.

CQL Cassandra umożliwia usuwanie pojedynczych wierszy i zakresów, gdy określone są wszystkie kolumny podstawowe. W Bigtable możesz to zrobić, skanując zakres, a następnie wykonując usuwanie na poziomie wiersza. Pamiętaj, że uzyskasz ten sam wynik, ale z uwzględnieniem większej liczby operacji, ponieważ każde usunięcie będzie osobną operacją.

Cassandra

Singiel

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

Wiele

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

Cloud Bigtable

Singiel

W tym miejscu usuniesz dane z określonego telefonu i daty. Za pomocą klucza wiersza możesz usunąć wiersz po jednym wierszu.

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

Wiele

W tym miejscu usuniesz wszystkie dane określonego tabletu mobilnego. Aby przenieść zapytanie CQL z wieloma wierszami, musisz przeprowadzić skanowanie, a następnie usunąć każdy wiersz, używając wynikowego zestawu kluczy wierszy.

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. Kończę

Czyszczenie danych

Cassandra

Jeśli w związku z tym został przez Ciebie utworzony klaster Cassandra, możesz go usunąć w normalny sposób.

Cloud Bigtable

Jeśli tabela została utworzona na podstawie istniejącej instancji Cloud Bigtable, możesz ją usunąć za pomocą polecenia cbt

cbt deletetable mobile-time-series

Jeśli korzystasz z emulatora, możesz go po prostu zatrzymać, aby usunąć całą pracę, wpisując CTRL-C w terminalu, w którym została uruchomiona.

Dalsze kroki