Cloud Bigtable pour les utilisateurs de Cassandra

1. Introduction

Cet atelier de programmation est un guide destiné à tous ceux qui migrent des requêtes d'Apache Cassandra vers Google Cloud Bigtable.

Dans cet atelier de programmation, vous allez :

  • Utiliser l'émulateur Cloud Bigtable
  • Explorer un cas d'utilisation de séries temporelles
  • Créer une table et une famille de colonnes
  • Découvrez les équivalents Java de Cloud Bigtable pour les méthodes d'insertion, de mise à jour, de sélection et de suppression CQL

Comment évalueriez-vous votre expérience de l'utilisation de Google Cloud Platform ?

Débutant Intermédiaire Expert

Comment allez-vous utiliser ce tutoriel ?

<ph type="x-smartling-placeholder"></ph> Je vais seulement le lire Je vais le lire et effectuer les exercices
.

2. Configurer

Vous allez examiner un exemple d'ensemble de données ne comportant que quelques lignes pour vous permettre de comprendre rapidement les concepts fondamentaux.

Cassandra

Des requêtes Cassandra équivalentes seront présentes à chaque étape. Vous pouvez donc poursuivre sur un cluster local si vous le souhaitez, ou vous pouvez configurer rapidement un cluster Cassandra de déploiement par clic et vous y connecter via SSH.

Si vous suivez, créez un espace de clés et utilisez-le. La stratégie de réplication n'est pas importante ici.

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

Cloud Bigtable

Vous aurez besoin d'une instance Cloud Bigtable pour votre table. Vous pouvez configurer sans frais une instance locale à l'aide de l'émulateur. Vous n'avez pas besoin de créer d'espace de clés dans Cloud Bigtable. Votre réplication est gérée par la configuration de votre instance.

Exécutez la commande suivante pour démarrer l'émulateur:

gcloud beta emulators bigtable start

Dans une autre fenêtre de l'interface système ou un autre onglet, définissez la variable d'environnement de l'émulateur à l'aide de la commande suivante:

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

Créez ensuite un projet Java que vous utiliserez pour exécuter les exemples de code, puis importez le client Cloud Bigtable avec Maven, Gradle ou SBT. Ensuite, dans un nouveau fichier Java, créez une connexion au client de données.

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. Création de tables

Dans les tables Cassandra et Cloud Bigtable, chaque ligne est associée à une clé. Les clés Cassandra possèdent une clé de partitionnement et une colonne de clustering qui peuvent être séparées ou se chevaucher. L'intégralité des clés Cloud Bigtable est utilisée pour les divisions (partitions) et l'ordre. Ces deux systèmes sont incroyablement similaires en ce qui concerne la construction de clés primaires/clés de ligne. Les deux systèmes sont essentiellement des listes triées de manière lexicographique, où les clés agissent comme la principale forme de distribution des lignes entre les nœuds. Dans la plupart des cas, vous pouvez réutiliser la même clé pour Cloud Bigtable.

Dans cet atelier de programmation, vous allez utiliser Cloud Bigtable pour stocker des données de séries temporelles concernant des téléphones mobiles et des tablettes (à ne pas confondre avec les tablettes Bigtable). Vous trouverez ci-dessous les instructions pour créer la table.

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

Vous pouvez créer une table et une famille de colonnes à l'aide du client Java, mais il est plus facile d'utiliser la commande suivante avec l'outil cbt:

cbt createtable mobile-time-series families=stats_summary

Cloud Bigtable est une base de données NoSQL. Vous n'avez donc pas besoin de définir un schéma lors de la création de la table, mais vous devez réfléchir aux requêtes que vous allez exécuter et optimiser la clé de ligne pour celles-ci.

La stratégie la plus courante pour migrer des clés consiste simplement à rassembler toutes les clés de partitionnement et les colonnes de clustering pour former une chaîne représentant la clé de ligne Cloud Bigtable. Nous recommandons généralement d'utiliser des clés basées sur des chaînes, car elles facilitent le débogage de la distribution des clés via Key Visualizer. Vous pouvez utiliser un séparateur comme le signe dièse (#) entre les valeurs des colonnes pour améliorer la lisibilité.

Dans cet exemple, nous utiliserons la clé de ligne "[DEVICE_TYPE]#[DEVICE_ID]#[AAAAMMJJ]".

4. Code inséré

Les insertions sont assez similaires dans Cassandra et Cloud Bigtable. Ici, vous allez insérer une ligne, puis plusieurs lignes en utilisant la clé de ligne "[DEVICE_TYPE]#[DEVICE_ID]#[AAAAMMJJ]".

Cassandra

Single

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

Single

Créez une mutation avec la clé de ligne et les données que vous souhaitez utiliser, puis appliquez-la avec le client de données. Vous allez ajouter une ligne de données pour un téléphone avec des informations sur sa connexion cellulaire et son système d'exploitation.

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

Définissez plusieurs mutations sur un objet BulkMutation, puis utilisez le client de données pour appliquer toutes les mutations avec un seul appel d'API. Ajoutez quelques jours de données sur le nom et la version du système d'exploitation d'une tablette mobile.

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. Mises à jour

Ici, vous allez mettre à jour une cellule qui n'a pas encore été écrite, puis écrire une nouvelle valeur dans une cellule tout en conservant les versions précédentes.

Cassandra

Ajouter des cellules

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

Mettre à jour des cellules

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

Dans Cloud Bigtable, vous pouvez traiter les mises à jour de la même manière que les écritures.

Ajouter des cellules

Cela revient à écrire des cellules. Il vous suffit de fournir une colonne dans laquelle vous n'avez pas encore écrit de données. Ajoutez le nom du système d'exploitation sur la ligne du téléphone.

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

Mise à jour des cellules

Vous allez ajouter ici de nouvelles données sur l'état de la connexion cellulaire du téléphone. Vous pouvez utiliser des versions de cellule pour stocker facilement une partie des données de vos séries temporelles. Il vous suffit de fournir un code temporel pour votre écriture et vous ajouterez une nouvelle version à la cellule. Pour nettoyer vos données, vous pouvez utiliser la récupération de mémoire afin de supprimer des versions après un certain nombre ou une certaine durée.

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. Sélectionne

Maintenant, vous allez récupérer les données que vous avez écrites dans la table. Lors de la migration des instructions de sélection CQL, vous devez prendre en compte plusieurs aspects des instructions SELECT, telles que les colonnes, le filtrage des clauses WHERE, ainsi que les fonctions de limite et d'agrégation telles que "Grouper par". Ici, vous allez simplement examiner deux instructions SELECT simples pour avoir l'idée de base, mais vous pouvez consulter la documentation pour plus d'informations sur la sélection. Dans Cloud Bigtable, il existe deux types d'opérations de récupération: Get et Scan. "Get" récupère une ligne, tandis que l'analyse récupère la plage de lignes.

Cassandra

Single

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

Multiples

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

Cloud Bigtable

Célibataires

Effectuez une recherche par ligne pour obtenir les données d'un téléphone spécifique à la date spécifiée, le tout sur une seule ligne. Cela renverra chaque version horodatée des valeurs, vous devriez donc voir deux lignes pour Connected_cell à des horodatages différents.

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

Plusieurs

Effectuez une analyse de plage pour consulter les données d'un mois spécifique pour une tablette mobile spécifique, réparties sur plusieurs lignes. Vous pouvez utiliser un filtre avec ces filtres pour n'obtenir que certaines versions des données ou filtrer les valeurs.

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

Cette option vous permet de supprimer les données que vous avez ajoutées à votre tableau. Vous supprimerez d'abord une ligne individuelle, puis plusieurs lignes.

Le langage CQL de Cassandra permet de supprimer une seule ligne ou des plages lorsque toutes les colonnes principales sont spécifiées. Pour ce faire, avec Bigtable, vous pouvez analyser une plage, puis effectuer des suppressions au niveau des lignes. Notez que vous obtiendrez le même résultat, mais avec plus d'opérations, car chaque suppression sera une opération distincte.

Cassandra

Single

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

Multiples

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

Cloud Bigtable

Single

Vous supprimerez ici les données pour un numéro de téléphone et une date spécifiques. Utilisez la clé de ligne pour supprimer une ligne à la fois.

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

Multiples

Vous allez supprimer toutes les données d'une tablette mobile spécifique. Pour migrer une requête CQL en supprimant plusieurs lignes, vous devez effectuer une analyse, puis supprimer chaque ligne à l'aide de l'ensemble de clés de ligne obtenu.

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. Pour terminer

Nettoyage

Cassandra

Si vous avez créé un cluster Cassandra pour poursuivre, n'hésitez pas à le supprimer comme vous le feriez normalement.

Cloud Bigtable

Si vous avez créé votre table sur une instance Cloud Bigtable existante, vous pouvez la supprimer à l'aide de la commande cbt

cbt deletetable mobile-time-series

Si vous avez utilisé l'émulateur, vous pouvez simplement l'arrêter pour effacer tout le travail en appuyant sur CTRL-C dans le terminal dans lequel vous l'avez démarré.

Étapes suivantes