Cloud Bigtable per gli utenti Cassandra

1. Introduzione

Questo codelab è una guida per chiunque stia eseguendo la migrazione delle query da Apache Cassandra a Google Cloud Bigtable.

In questo codelab

  • Utilizza l'emulatore Cloud Bigtable
  • Esplora un caso d'uso relativo alle serie temporali
  • Crea una famiglia di tabelle e colonne
  • Scopri gli equivalenti Java di Cloud Bigtable per le operazioni di inserimento, aggiornamento, selezione ed eliminazione di CQL

Come giudichi la tua esperienza di utilizzo della piattaforma Google Cloud?

Principiante Livello intermedio Eccellente

Come utilizzerai questo tutorial?

Solo lettura Leggilo e completa gli esercizi

2. Configura

Viene esaminato un set di dati di esempio con solo poche righe per farti capire rapidamente i concetti principali.

Cassandra

In ogni passaggio saranno presenti query equivalenti di Cassandra, quindi puoi continuare a utilizzare un cluster locale, se vuoi, oppure puoi configurare rapidamente un cluster Cassandra click-to-deploy e accedervi tramite SSH.

Se procedi, crea uno spazio delle chiavi e utilizzalo. La strategia di replica non sarà importante in questo caso.

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

Cloud Bigtable

Per la tua tabella, è necessaria un'istanza Cloud Bigtable. Puoi configurare senza costi un'istanza locale utilizzando l'emulatore. Non è necessario creare uno spazio delle chiavi in Cloud Bigtable, perché la replica è gestita dalla configurazione dell'istanza.

Usa questo comando per avviare l'emulatore:

gcloud beta emulators bigtable start

Quindi, in un'altra finestra o scheda della shell, imposta la variabile di ambiente dell'emulatore con questo comando:

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

Quindi crea un progetto Java che utilizzerai per eseguire gli esempi di codice e importa il client Cloud Bigtable con Maven, Gradle o SBT. Quindi, in un nuovo file Java, crea una connessione al client di dati.

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. Creazione della tabella

Nelle tabelle Cassandra e Cloud Bigtable, a ogni riga è associata una chiave. Le chiavi Cassandra hanno una chiave di partizione e una colonna di clustering che possono essere separate o sovrapporsi. L'intera chiave Cloud Bigtable viene utilizzata per le suddivisioni (partizioni) e l'ordinamento. Questi due sistemi sono incredibilmente simili nella costruzione della chiave primaria/di riga. Entrambi i sistemi sono sostanzialmente elenchi ordinati in ordine grammaticale, in cui le chiavi fungono da forma principale di distribuzione delle righe tra i nodi. Nella maggior parte dei casi puoi riutilizzare la stessa chiave per Cloud Bigtable.

In questo codelab, utilizzerai Cloud Bigtable per archiviare i dati delle serie temporali relativi a telefoni cellulari e tablet (da non confondere con i tablet Bigtable). Di seguito sono riportate le istruzioni per creare la tabella.

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

Puoi creare una famiglia di tabelle e colonne utilizzando il client Java, ma è più semplice utilizzare il seguente comando con lo strumento cbt:

cbt createtable mobile-time-series families=stats_summary

Cloud Bigtable è un database NoSQL, quindi non dovrai definire uno schema durante la creazione delle tabelle, ma dovrai pensare alle query che eseguirai e ottimizzare la chiave di riga di conseguenza.

La strategia più comune per la migrazione delle chiavi consiste semplicemente nel prendere tutte le chiavi di partizione e le colonne di clustering e unirle in modo da formare una stringa che rappresenta la chiave di riga di Cloud Bigtable. In genere consigliamo di utilizzare chiavi basate su stringhe perché aiutano a eseguire il debug della distribuzione delle chiavi tramite Key Visualizer. Puoi utilizzare un separatore, come un hash "#" tra i valori della colonna per migliorare la leggibilità.

In questo esempio utilizzeremo la valore rowkey di "[DEVICE_TYPE]#[DEVICE_ID]#[YYYYMMDD]"

4. Inserti

Gli inserti sono abbastanza simili tra Cassandra e Cloud Bigtable. Qui dovrai inserire una riga e poi più righe utilizzando la chiave di riga "[DEVICE_TYPE]#[DEVICE_ID]#[AAAAMMGG]".

Cassandra

Singolo

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

Singolo

Crea una mutazione con la chiave di riga e i dati da utilizzare, quindi applicala con il client di dati. Aggiungerai una riga di dati relativi a un telefono con informazioni sulla connessione cellulare e sul sistema operativo.

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

Definisci più mutazioni su un oggetto BulkMutation, quindi utilizza il client di dati per applicare tutte le mutazioni con un'unica chiamata API. Aggiungi alcuni giorni di dati relativi al nome e alla versione del sistema operativo di un tablet 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. Aggiornamenti

Qui aggiorni una cella che non è stata ancora scritta e quindi scrivi un nuovo valore in una cella, conservando anche le versioni precedenti.

Cassandra

Aggiungere celle

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

Aggiornare le celle

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

In Cloud Bigtable, puoi trattare gli aggiornamenti come le scritture.

Aggiungere celle

È come scrivere celle: è sufficiente fornire una colonna in cui non hai scritto in precedenza. Qui devi aggiungere il nome del sistema operativo alla riga del telefono.

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

Aggiornamento delle celle

Qui aggiungerai nuovi dati sullo stato della connessione cellulare del telefono. Puoi utilizzare le versioni delle celle per archiviare facilmente parte dei dati delle serie temporali. Fornisci semplicemente un timestamp per la tua scrittura e aggiungerai una nuova versione per la cella. Per eseguire la pulizia dei dati, puoi utilizzare la garbage collection per eliminare le versioni dopo un determinato numero o un determinato periodo di tempo.

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

A questo punto recupererai i dati scritti nella tabella. Quando esegui la migrazione delle istruzioni CQL select, devi prendere in considerazione diversi aspetti di queste istruzioni, come le colonne, l'applicazione di filtri alle clausole WHERE e la limitazione e l'aggregazione di funzioni come Raggruppa per. In questo caso, basta osservare due semplici istruzioni di selezione per avere un'idea di base, ma è possibile consultare la documentazione per ulteriori informazioni sulla selezione. In Cloud Bigtable esistono due tipi di operazioni di recupero: Get e Scan. Il comando GET recupera una riga, mentre la scansione recupera l'intervallo di righe.

Cassandra

Singolo

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

Più

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

Cloud Bigtable

Single

Utilizza una ricerca per riga per ottenere i dati relativi a uno smartphone specifico nella data specificata, tutto all'interno di una riga. Verrà restituita ogni versione dei valori con timestamp dei valori, quindi dovresti vedere due righe per Connected_cell con timestamp diversi.

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

Multiplo

Utilizza una scansione dell'intervallo per visualizzare i dati di un mese per un tablet mobile specificato distribuiti su più righe. Puoi applicare un filtro con questi valori per visualizzare solo determinate versioni dei dati o filtrare in base ai valori.

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

Qui eliminerai i dati inseriti nella tabella. In primo luogo elimini una singola riga, poi elimini più righe.

La CQL di Cassandra consente l'eliminazione di singole righe e la rimozione di intervalli quando sono specificate tutte le colonne primarie. Puoi farlo con Bigtable analizzando un intervallo ed eseguendo operazioni di eliminazione a livello di riga. Tieni presente che otterrai lo stesso risultato, ma dovrai eseguire più operazioni poiché ogni eliminazione sarà un'operazione indipendente.

Cassandra

Singolo

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

Più

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

Cloud Bigtable

Singolo

Qui puoi eliminare i dati relativi a uno smartphone e una data specifici. Utilizza la chiave di riga per eliminare una riga alla volta.

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

Più

Qui verranno eliminati tutti i dati relativi a un tablet mobile specifico. Per eseguire la migrazione di una query CQL eliminando più righe, devi eseguire una scansione ed eliminare ogni riga utilizzando l'insieme di chiavi di riga risultante.

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

Pulizia

Cassandra

Se hai creato un cluster Cassandra per seguirlo, puoi eliminarlo come faresti normalmente.

Cloud Bigtable

Se hai creato la tabella su un'istanza Cloud Bigtable esistente, puoi eliminarla con il comando cbt

cbt deletetable mobile-time-series

Se hai usato l'emulatore, puoi semplicemente arrestarlo per eliminare tutto il lavoro, digitando Ctrl-C nel terminale in cui l'hai avviato.

Passaggi successivi