Esegui la migrazione da DynamoDB a Spanner

Questo tutorial descrive come migrare da Amazon DynamoDB a Spanner. È pensato principalmente per i proprietari di app che desiderano migrare da un sistema NoSQL a Spanner, un sistema di database SQL completamente relazionale, a tolleranza di errore, altamente scalabile e che supporta le transazioni. Se utilizzi in modo coerente le tabelle Amazon DynamoDB, in termini di tipi e layout, la mappatura a Spanner è semplice. Se le tue tabelle Amazon DynamoDB contengono tipi di dati e valori arbitrari, potrebbe essere più semplice passare ad altri servizi NoSQL, come Datastore o Firestore.

Questo tutorial presuppone che tu abbia familiarità con gli schemi di database, i tipi di dati, i fondamenti di NoSQL e i sistemi di database relazionali. Il tutorial si basa sull'esecuzione di attività predefinite per realizzare una migrazione di esempio. Dopo il tutorial, puoi modificare il codice e i passaggi forniti per adattarli al tuo ambiente.

Il seguente diagramma architetturale illustra i componenti utilizzati nel tutorial per la migrazione dei dati:

Schema architettonico delle componenti della migrazione

Obiettivi

  • Migrare i dati da Amazon DynamoDB a Spanner.
  • Creare un database Spanner e una tabella di migrazione.
  • Mappa uno schema NoSQL a uno schema relazionale.
  • Crea ed esporta un set di dati di esempio che utilizza Amazon DynamoDB.
  • Trasferisci dati tra Amazon S3 e Cloud Storage.
  • Utilizza Dataflow per caricare i dati in Spanner.

Costi

Questo tutorial utilizza i seguenti componenti fatturabili di Google Cloud:

I costi di Spanner si basano sulla capacità di calcolo della tua istanza e sulla quantità di dati archiviati durante il ciclo di fatturazione mensile. Durante il tutorial, utilizzi una configurazione minima di queste risorse, che vengono pulite alla fine. Per scenari reali, stima i requisiti di throughput e di archiviazione, quindi utilizza la documentazione delle istanze Spanner per determinare la quantità di capacità di calcolo necessaria.

Oltre alle risorse Google Cloud resources, questa esercitazione utilizza le seguenti risorse di Amazon Web Services (AWS):

  • AWS Lambda
  • Amazon S3
  • Amazon DynamoDB

Questi servizi sono necessari solo durante il processo di migrazione. Al termine del tutorial, segui le istruzioni per liberare spazio da tutte le risorse ed evitare addebiti non necessari. Utilizza il calcolatore dei prezzi AWS per stimare questi costi.

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il calcolatore prezzi.

Prima di iniziare

  1. Accedi al tuo account Google Cloud . Se non conosci Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti senza costi per l'esecuzione, il test e il deployment dei carichi di lavoro.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the Spanner, Pub/Sub, Compute Engine, and Dataflow APIs.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  6. Verify that billing is enabled for your Google Cloud project.

  7. Enable the Spanner, Pub/Sub, Compute Engine, and Dataflow APIs.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.

    Enable the APIs

Al termine delle attività descritte in questo documento, puoi evitare l'addebito di ulteriori costi eliminando le risorse che hai creato. Per saperne di più, consulta Esegui la pulizia.

prepara l'ambiente

In questo tutorial, esegui i comandi in Cloud Shell. Cloud Shell ti dà accesso alla riga di comando in Google Cloude include la Google Cloud CLI e altri strumenti necessari per Google Cloud sviluppo. L'inizializzazione di Cloud Shell può richiedere diversi minuti.

  1. Nella console Google Cloud , attiva Cloud Shell.

    Attiva Cloud Shell

    Nella parte inferiore della console Google Cloud viene avviata una sessione di Cloud Shell e viene visualizzato un prompt della riga di comando. Cloud Shell è un ambiente shell con Google Cloud CLI già installata e con valori già impostati per il progetto corrente. L'inizializzazione della sessione può richiedere alcuni secondi.

  2. Imposta la zona predefinita di Compute Engine. Ad esempio, us-central1-b. gcloud config set compute/zone us-central1-b
  3. Clona il repository GitHub contenente il codice campione. git clone https://github.com/GoogleCloudPlatform/dynamodb-spanner-migration.git
  4. Accedere alla directory clonata. cd dynamodb-spanner-migration
  5. Crea un ambiente virtuale Python. pip3 install virtualenv virtualenv env
  6. Attiva l'ambiente virtuale: source env/bin/activate
  7. Installa i moduli Python richiesti. pip3 install -r requirements.txt

Configurare l'accesso AWS

In questa esercitazione, creerai ed eliminerai tabelle Amazon DynamoDB, bucket Amazon S3 e altre risorse. Per accedere a queste risorse, è necessario innanzitutto creare le autorizzazioni AWS Identity and Access Management (IAM) richieste. Puoi utilizzare un account AWS di test o sandbox per evitare di influire sulle risorse di produzione nello stesso account.

Creare un ruolo AWS IAM per AWS Lambda

In questa sezione, creerai un ruolo AWS IAM che AWS Lambda utilizzerà in una fase successiva del tutorial.

  1. Nella console AWS, vai alla sezione IAM, fai clic su Ruoli e poi seleziona Crea ruolo.
  2. In Tipo di entità attendibile, assicurarsi che sia selezionato Servizio AWS.
  3. In Usa caso, seleziona Lambda e poi fai clic su Avanti.
  4. Nella casella del filtro Policy di autorizzazione, inserisci AWSLambdaDynamoDBExecutionRole e premi Return per eseguire la ricerca.
  5. Seleziona la casella di controllo AWSLambdaDynamoDBExecutionRole e poi fai clic su Avanti.
  6. Nella casella Nome ruolo, inserisci dynamodb-spanner-lambda-role e poi fai clic su Crea ruolo.

Crea un utente IAM AWS

Segui questi passaggi per creare un utente AWS IAM con accesso programmatico alle risorse AWS, che verranno utilizzate in tutto il tutorial.

  1. Mentre ti trovi ancora nella sezione IAM della console AWS, fai clic su Utenti e poi seleziona Aggiungi utenti.
  2. Nella casella Nome utente, inserisci dynamodb-spanner-migration.
  3. In Tipo di accesso, selezionare la casella di controllo a sinistra di Chiave di accesso - Accesso programmatico.

  4. Fai clic su Avanti: Autorizzazioni.

  5. Fai clic su Allega direttamente le policy esistenti e, utilizzando la casella Cerca per filtrare, seleziona la casella di controllo accanto a ciascuna delle tre policy seguenti:

    • AmazonDynamoDBFullAccess
    • AmazonS3FullAccess
    • AWSLambda_FullAccess
  6. Fai clic su Avanti: Tag e Avanti: Revisione, quindi fai clic su Crea utente.

  7. Fai clic su Mostra per visualizzare le credenziali. Per l'utente appena creato vengono visualizzati l'ID della chiave di accesso e la chiave di accesso segreta. Lasciate questa finestra aperta per il momento, perché le credenziali saranno necessarie nella sezione successiva. Conserva queste credenziali in un luogo sicuro, perché con esse puoi apportare modifiche al tuo account e influire sul tuo ambiente. Al termine di questo tutorial, puoi eliminare l'utente IAM.

Configurare l'interfaccia a riga di comando AWS

  1. In Cloud Shell, configura l'interfaccia a riga di comando AWS (CLI).

    aws configure
    

    Viene visualizzato il seguente output:

    AWS Access Key ID [None]: PASTE_YOUR_ACCESS_KEY_ID
    AWS Secret Access Key [None]: PASTE_YOUR_SECRET_ACCESS_KEY
    Default region name [None]: us-west-2
    Default output format [None]:
    
    • Inserisci ACCESS KEY ID e SECRET ACCESS KEY dall'account AWS IAM che hai creato.
    • Nel campo Nome regione predefinita, inserire us-west-2. Lascia invariati i valori predefiniti degli altri campi.
  2. Chiudi la finestra della console AWS IAM.

Informazioni sul modello di dati

La sezione seguente illustra le somiglianze e le differenze tra i tipi di dati, le chiavi e gli indici di Amazon DynamoDB e Spanner.

Tipi di dati

Spanner utilizza i tipi di dati GoogleSQL. La tabella seguente descrive come i tipi di dati data di Amazon DynamoDB vengono mappati ai tipi di dati data di Spanner.

Amazon DynamoDB Spanner
Numero A seconda della precisione o dell'utilizzo previsto, potrebbe essere mappato a INT64, FLOAT64, TIMESTAMP o DATE.
Stringa Stringa
Booleano BOOL
Null Nessun tipo esplicito. Le colonne possono contenere valori null.
Binario Byte
Set Array
Mappa e elenco Struttura se la struttura è coerente e può essere descritta utilizzando la sintassi DDL della tabella.

Chiave primaria

Una chiave primaria di Amazon DynamoDB garantisce l'unicità dei dati e può essere una chiave hash o una combinazione di una chiave hash e una chiave di intervallo. Questo tutorial inizia mostrando la migrazione di una tabella Amazon DynamoDB la cui chiave primaria è una chiave hash. Questa chiave hash diventa la chiave primaria della tabella Spanner. Più avanti, nella sezione sulle tabelle interleaved, modellerai una situazione in cui una tabella Amazon DynamoDB utilizza una chiave primaria composta da una chiave hash e una chiave di intervallo.

Indici secondari

Sia Amazon DynamoDB che Spanner supportano la creazione di un indice su un attributo di chiave non primaria. Prendi nota di eventuali indici secondari nella tua tabella Amazon DynamoDB in modo da poterli creare sulla tua tabella Spanner, che è trattato in unsezione successiva di questo tutorial.

Tabella di esempio

Per facilitare questo tutorial, migrerai la seguente tabella di esempio da Amazon DynamoDB a Spanner:

Amazon DynamoDB Spanner
Nome tabella Migration Migration
Chiave primaria "Username" : String "Username" : STRING(1024)
Tipo di chiave Hash n/a
Altri campi Zipcode: Number Subscribed: Boolean ReminderDate: String PointsEarned: Number Zipcode: INT64 Subscribed: BOOL ReminderDate: DATE PointsEarned: INT64

Prepara la tabella Amazon DynamoDB

Nella sezione seguente, creerete una tabella sorgente Amazon DynamoDB e la popolerete con i dati.

  1. In Cloud Shell, crea una tabella Amazon DynamoDB che utilizzi gli attributi sample table.

    aws dynamodb create-table --table-name Migration \
        --attribute-definitions AttributeName=Username,AttributeType=S \
        --key-schema AttributeName=Username,KeyType=HASH \
        --provisioned-throughput ReadCapacityUnits=75,WriteCapacityUnits=75
    
  2. Verificare che lo stato della tabella sia ACTIVE.

    aws dynamodb describe-table --table-name Migration \
        --query 'Table.TableStatus'
    
  3. Inserisci i dati di esempio nella tabella.

    python3 make-fake-data.py --table Migration --items 25000
    

Creazione di un database Spanner

Si crea un'istanza di Spanner con la capacità di calcolo minima possibile: 100 unità di elaborazione. Questa capacità di calcolo è sufficiente per gli scopi di questo tutorial. Per un deployment di produzione, consulta la documentazione relativa alle istanze Spanner per determinare la capacità di calcolo appropriata per soddisfare i requisiti di prestazioni del database.

In questo esempio, si crea lo schema della tabella contemporaneamente al database. È anche possibile, e comune, eseguire aggiornamenti dello schema dopo aver creato il database.

  1. Crea un'istanza di Spanner nella stessa regione in cui hai impostato la zona predefinita di Compute Engine. Ad esempio, us-central1.

    gcloud beta spanner instances create spanner-migration \
        --config=regional-us-central1 --processing-units=100 \
        --description="Migration Demo"
    
  2. Crea un database nell'istanza di Spanner insieme alla tabella di esempio.

    gcloud spanner databases create migrationdb \
        --instance=spanner-migration \
        --ddl "CREATE TABLE Migration ( \
                Username STRING(1024) NOT NULL, \
                PointsEarned INT64, \
                ReminderDate DATE, \
                Subscribed BOOL, \
                Zipcode INT64, \
             ) PRIMARY KEY (Username)"
    

Preparare la migrazione

Le sezioni successive mostrano come esportare la tabella sorgente di Amazon DynamoDB e configurare la replica Pub/Sub per acquisire tutte le modifiche al database che si verificano durante l'esportazione.

Il flusso di modifiche passa a Pub/Sub

Si utilizza una funzione AWS Lambda per trasmettere in streaming le modifiche al database al sistema Pub/Sub.

  1. In Cloud Shell, abilita i flussi Amazon DynamoDB sulla tua tabella di origine.

    aws dynamodb update-table --table-name Migration \
        --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES
    
  2. Configura un argomento Pub/Sub per ricevere le modifiche.

    gcloud pubsub topics create spanner-migration
    

    Viene visualizzato il seguente output:

    Created topic [projects/your-project/topics/spanner-migration].
    
  3. Crea un account di servizio IAM per inviare gli aggiornamenti delle tabelle all'argomento Pub/Sub.

    gcloud iam service-accounts create spanner-migration \
        --display-name="Spanner Migration"
    

    Viene visualizzato il seguente output:

    Created service account [spanner-migration].
    
  4. Crea un binding di policy IAM in modo che il account di servizio abbia l'autorizzazione a pubblicare su Pub/Sub. Sostituisci GOOGLE_CLOUD_PROJECT con il nome del tuo Google Cloud progetto.

    gcloud projects add-iam-policy-binding GOOGLE_CLOUD_PROJECT \
        --role roles/pubsub.publisher \
        --member serviceAccount:spanner-migration@GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com
    

    Viene visualizzato il seguente output:

    bindings:
    (...truncated...)
    - members:
      - serviceAccount:spanner-migration@solution-z.iam.gserviceaccount.com
      role: roles/pubsub.publisher
    
  5. Creare le credenziali per l'account di servizio.

    gcloud iam service-accounts keys create credentials.json \
        --iam-account spanner-migration@GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com
    

    Viene visualizzato il seguente output:

    created key [5e559d9f6bd8293da31b472d85a233a3fd9b381c] of type [json] as [credentials.json] for [spanner-migration@your-project.iam.gserviceaccount.com]
    
  6. Prepara e impacchetta la funzione AWS Lambda per inviare le modifiche alle tabelle di Amazon DynamoDB all'argomento Pub/Sub.

    pip3 install --ignore-installed --target=lambda-deps google-cloud-pubsub
    cd lambda-deps; zip -r9 ../pubsub-lambda.zip *; cd -
    zip -g pubsub-lambda.zip ddbpubsub.py
  7. Crea una variabile per acquisire l'Amazon Resource Name (ARN) del ruolo di esecuzione Lambda che hai creato in precedenza.

    LAMBDA_ROLE=$(aws iam list-roles \
        --query 'Roles[?RoleName==`dynamodb-spanner-lambda-role`].[Arn]' \
        --output text)
    
  8. Utilizza il pacchetto pubsub-lambda.zip per creare la funzione AWS Lambda.

    aws lambda create-function --function-name dynamodb-spanner-lambda \
        --runtime python3.9 --role ${LAMBDA_ROLE} \
        --handler ddbpubsub.lambda_handler --zip fileb://pubsub-lambda.zip \
        --environment Variables="{SVCACCT=$(base64 -w 0 credentials.json),PROJECT=GOOGLE_CLOUD_PROJECT,TOPIC=spanner-migration}"
    

    Viene visualizzato il seguente output:

    {
        "FunctionName": "dynamodb-spanner-lambda",
        "LastModified": "2022-03-17T23:45:26.445+0000",
        "RevisionId": "e58e8408-cd3a-4155-a184-4efc0da80bfb",
        "MemorySize": 128,
    ... truncated output... "PackageType": "Zip", "Architectures": [ "x86_64" ] }
  9. Crea una variabile per acquisire l'ARN del flusso Amazon DynamoDB per la tua tabella.

    STREAMARN=$(aws dynamodb describe-table \
        --table-name Migration \
        --query "Table.LatestStreamArn" \
        --output text)
    
  10. Collega la funzione Lambda alla tabella Amazon DynamoDB.

    aws lambda create-event-source-mapping --event-source ${STREAMARN} \
        --function-name dynamodb-spanner-lambda --enabled \
        --starting-position TRIM_HORIZON
    
  11. Per ottimizzare la reattività durante i test, aggiungi --batch-size 1 alla fine del comando precedente, in modo che la funzione venga attivata ogni volta che crei, aggiorni o elimini un elemento.

    Vedrai un output simile al seguente:

    {
        "UUID": "44e4c2bf-493a-4ba2-9859-cde0ae5c5e92",
        "StateTransitionReason": "User action",
        "LastModified": 1530662205.549,
        "BatchSize": 100,
        "EventSourceArn": "arn:aws:dynamodb:us-west-2:accountid:table/Migration/stream/2018-07-03T15:09:57.725",
        "FunctionArn": "arn:aws:lambda:us-west-2:accountid:function:dynamodb-spanner-lambda",
        "State": "Creating",
        "LastProcessingResult": "No records processed"
    ... truncated output...
    

Esporta la tabella Amazon DynamoDB su Amazon S3

  1. In Cloud Shell, crea una variabile per il nome del bucket che utilizzerai in diverse delle sezioni seguenti.

    BUCKET=${DEVSHELL_PROJECT_ID}-dynamodb-spanner-export
    
  2. Crea un bucket Amazon S3 per ricevere l'esportazione di DynamoDB.

    aws s3 mb s3://${BUCKET}
    
  3. Nella console di gestione AWS, vai a DynamoDB e fai clic su Tabelle.

  4. Fai clic sulla tabella Migration.

  5. Nella scheda Esportazioni e stream, fai clic su Esporta in S3.

  6. Abilita point-in-time-recovery (PITR) se richiesto.

  7. Fai clic su Sfoglia S3 per scegliere il bucket S3 creato in precedenza.

  8. Fai clic su Esporta.

  9. Fai clic sull'icona Aggiorna icon per aggiornare lo stato del processo di esportazione. L'esportazione richiede diversi minuti.

    Al termine del processo, esamina il bucket di output.

    aws s3 ls --recursive s3://${BUCKET}
    

    Questa fase richiederà circa 5 minuti. Al termine del processo, verrà visualizzato un output simile al seguente:

    2022-02-17 04:41:46          0 AWSDynamoDB/01645072900758-ee1232a3/_started
    2022-02-17 04:46:04     500441 AWSDynamoDB/01645072900758-ee1232a3/data/xygt7i2gje4w7jtdw5652s43pa.json.gz
    2022-02-17 04:46:17        199 AWSDynamoDB/01645072900758-ee1232a3/manifest-files.json
    2022-02-17 04:46:17         24 AWSDynamoDB/01645072900758-ee1232a3/manifest-files.md5
    2022-02-17 04:46:17        639 AWSDynamoDB/01645072900758-ee1232a3/manifest-summary.json
    2022-02-17 04:46:18         24 AWSDynamoDB/01645072900758-ee1232a3/manifest-summary.md5
    

Eseguire la migrazione

Ora che la distribuzione Pub/Sub è attiva, è possibile applicare tutte le modifiche alle tabelle avvenute dopo l'esportazione.

Copia la tabella esportata in Cloud Storage

  1. In Cloud Shell, crea un bucket Cloud Storage per ricevere i file esportati da Amazon S3.

    gcloud storage buckets create gs://${BUCKET}
    
  2. Sincronizzazione trasferire i file da Amazon S3 a Cloud Storage. Per la maggior parte delle operazioni di copia, il comando rsync è efficace. Se i file da esportare sono di grandi dimensioni (diversi GB o più), utilizza il servizio di trasferimento di Cloud Storage per gestire il trasferimento in background.

    gcloud storage rsync s3://${BUCKET} gs://${BUCKET} --recursive --delete-unmatched-destination-objects
    

Importare i dati in batch

  1. Per scrivere i dati dai file esportati nella tabella Spanner, esegui un job Dataflow con il codice di esempio di Apache Beam.

    cd dataflow
    mvn compile
    mvn exec:java \
    -Dexec.mainClass=com.example.spanner_migration.SpannerBulkWrite \
    -Pdataflow-runner \
    -Dexec.args="--project=GOOGLE_CLOUD_PROJECT \
                 --instanceId=spanner-migration \
                 --databaseId=migrationdb \
                 --table=Migration \
                 --importBucket=$BUCKET \
                 --runner=DataflowRunner \
                 --region=us-central1"
    
    1. Per monitorare l'avanzamento del processo di importazione, nella console Google Cloud , vai a Dataflow.

      Vai a Dataflow

    2. Mentre il processo è in esecuzione, è possibile monitorare il grafico di esecuzione per esaminare i log. Fai clic sul lavoro che mostra lo Stato di In esecuzione.

      Esecuzione del processo di importazione

  2. Fai clic su ciascuna fase per vedere quanti elementi sono stati elaborati. L'importazione è completa quando tutte le fasi indicano Riuscito. Il numero di elementi creati nella tabella Amazon DynamoDB visualizzati corrisponde a quelli elaborati in ciascuna fase.

    Fasi di successo del lavoro di importazione

  3. Verifica che il numero di record nella tabella Spanner di destinazione corrisponda al numero di elementi nella tabella Amazon DynamoDB.

    aws dynamodb describe-table --table-name Migration --query Table.ItemCount
    gcloud spanner databases execute-sql migrationdb \ --instance=spanner-migration --sql="select count(*) from Migration"

    Viene visualizzato il seguente output:

    $ aws dynamodb describe-table --table-name Migration --query Table.ItemCount
    25000
    $ gcloud spanner databases execute-sql migrationdb --instance=spanner-migration --sql="select count(*) from Migration"
    25000
    
  4. Prelevare campioni casuali da ciascuna tabella per assicurarsi che i dati siano coerenti.

    gcloud spanner databases execute-sql migrationdb \
        --instance=spanner-migration \
        --sql="select * from Migration limit 1"
    

    Viene visualizzato il seguente output:

     Username: aadams4495
     PointsEarned: 5247
     ReminderDate: 2022-03-14
     Subscribed: True
     Zipcode: 58057
    
  5. Esegui una query sulla tabella Amazon DynamoDB con lo stesso Username restituito dalla query Spanner nel passaggio precedente. Ad esempio, aallen2538. Il valore è specifico dei dati di esempio presenti nel database.

    aws dynamodb get-item --table-name Migration \
        --key '{"Username": {"S": "aadams4495"}}'
    

    I valori degli altri campi devono corrispondere a quelli dell'output di Spanner. Viene visualizzato il seguente output:

    {
        "Item": {
            "Username": {
                "S": "aadams4495"
            },
            "ReminderDate": {
                "S": "2018-06-18"
            },
            "PointsEarned": {
                "N": "1606"
            },
            "Zipcode": {
                "N": "17303"
            },
            "Subscribed": {
                "BOOL": false
            }
        }
    }
    

Replica le nuove modifiche

Al termine del job di importazione batch, configura un job di streaming per scrivere gli aggiornamenti continui dalla tabella di origine in Spanner. Puoi iscriverti agli eventi di Pub/Sub e scriverli a Spanner

La funzione Lambda che hai creato è configurata per acquisire le modifiche alla tabella sorgente Amazon DynamoDB e pubblicarle su Pub/Sub.

  1. Crea un abbonamento all'argomento Pub/Sub a cui AWS Lambda invia gli eventi.

    gcloud pubsub subscriptions create spanner-migration \
        --topic spanner-migration
    

    Viene visualizzato il seguente output:

    Created subscription [projects/your-project/subscriptions/spanner-migration].
    
  2. Per trasmettere in streaming le modifiche in arrivo in Pub/Sub per scriverle nella tabella Spanner, esegui il job Dataflow da Cloud Shell.

    mvn exec:java \
    -Dexec.mainClass=com.example.spanner_migration.SpannerStreamingWrite \
    -Pdataflow-runner \
    -Dexec.args="--project=GOOGLE_CLOUD_PROJECT \
                 --instanceId=spanner-migration \
                 --databaseId=migrationdb \
                 --table=Migration \
                 --experiments=allow_non_updatable_job \
    --subscription=projects/GOOGLE_CLOUD_PROJECT/subscriptions/spanner-migration \
    --runner=DataflowRunner \
    --region=us-central1"
    
    1. Analogamente al passaggio batch load, per monitorare l'avanzamento del lavoro, nella Google Cloud console, vai a Dataflow.

      Vai a Dataflow

    2. Fai clic sul job con Stato In esecuzione.

      Job in esecuzione

      Il grafico di elaborazione mostra un output simile a quello precedente, ma ogni elemento elaborato viene conteggiato nella finestra di stato. Il tempo di latenza del sistema è una stima approssimativa del ritardo previsto prima che le modifiche vengano visualizzate nella tabella Spanner.

      Processi in esecuzione a causa del tempo di ritardo

Il job Dataflow eseguito nella fase di caricamento batch era un insieme finito di input, noto anche come dataset bounded. Questo job Dataflow utilizza Pub/Sub come sorgente di streaming ed è considerato illimitato. Per ulteriori informazioni su questi due tipi di sorgenti, consultare la sezione relativa alle PCollections nella guida di programmazione di Apache Beam. Il processo Dataflow in questa fase è progettato per rimanere attivo, quindi non termina al termine dell'esecuzione. Il job Dataflow di streaming rimane nello stato In esecuzione anziché nello stato Riuscito.

Verifica la replica

Si apportano alcune modifiche alla tabella di origine per verificare che le modifiche vengano replicate nella tabella Spanner.

  1. Eseguire una query su una riga inesistente in Spanner.

    gcloud spanner databases execute-sql migrationdb \
        --instance=spanner-migration \
        --sql="SELECT * FROM Migration WHERE Username='my-test-username'"
    

    L'operazione non produrrà alcun risultato.

  2. Crea un record in Amazon DynamoDB con la stessa chiave che hai utilizzato nella query Spanner. Se il comando viene eseguito correttamente, non viene restituito alcun output.

    aws dynamodb put-item \
        --table-name Migration \
        --item '{"Username" : {"S" : "my-test-username"}, "Subscribed" : {"BOOL" : false}}'
    
  3. Esegui di nuovo la stessa query per verificare che la riga sia ora in Spanner.

    gcloud spanner databases execute-sql migrationdb \
        --instance=spanner-migration \
        --sql="SELECT * FROM Migration WHERE Username='my-test-username'"
    

    L'output mostra la riga inserita:

    Username: my-test-username
    PointsEarned: None
    ReminderDate: None
    Subscribed: False
    Zipcode:
    
  4. Modifica alcuni attributi nell'elemento originale e aggiorna la tabella Amazon DynamoDB.

    aws dynamodb update-item \
        --table-name Migration \
        --key '{"Username": {"S":"my-test-username"}}' \
        --update-expression "SET PointsEarned = :pts, Subscribed = :sub" \
        --expression-attribute-values '{":pts": {"N":"4500"}, ":sub": {"BOOL":true}}'\
        --return-values ALL_NEW
    

    Vedrai un output simile al seguente:

    {
        "Attributes": {
            "Username": {
                "S": "my-test-username"
            },
            "PointsEarned": {
                "N": "4500"
            },
            "Subscribed": {
                "BOOL": true
            }
        }
    }
    
  5. Verifica che le modifiche vengano propagate alla tabella Spanner.

    gcloud spanner databases execute-sql migrationdb \
        --instance=spanner-migration \
        --sql="SELECT * FROM Migration WHERE Username='my-test-username'"
    

    L'output appare come segue:

    Username          PointsEarned  ReminderDate  Subscribed  Zipcode
    my-test-username  4500          None          True
    
  6. Elimina l'elemento di prova dalla tabella sorgente di Amazon DynamoDB.

    aws dynamodb delete-item \
        --table-name Migration \
        --key '{"Username": {"S":"my-test-username"}}'
    
  7. Verifica che la riga corrispondente sia eliminata dalla tabella Spanner. Una volta propagata la modifica, il seguente comando restituisce zero righe:

    gcloud spanner databases execute-sql migrationdb \
        --instance=spanner-migration \
        --sql="SELECT * FROM Migration WHERE Username='my-test-username'"
    

Utilizzare tabelle con interfoliazione

Spanner supporta il concetto di tabelle interleaved. Si tratta di un modello di progettazione in cui un elemento di primo livello ha diversi elementi nidificati correlati a quell'elemento di primo livello, ad esempio un cliente e i suoi ordini o un giocatore e i suoi punteggi di gioco. Se la tabella di origine Amazon DynamoDB utilizza una chiave primaria composta da una chiave hash e una chiave di intervallo, puoi modellare uno schema di tabella interleaved come mostrato nel seguente diagramma. Questa struttura consente di interrogare in modo efficiente la tabella interlacciata, unendo al contempo i campi della tabella principale.

Tabella degli utenti rispetto alla tabella degli ordini

Applicare indici secondari

È una best practice applicare gli indici secondari alle tabelle Spanner dopo aver caricato i dati. Ora che la replica funziona, si imposta un indice secondario per velocizzare le query. Come le tabelle Spanner, anche gli indici secondari Spanner sono completamente coerenti. Non sono eventualmente coerenti, il che è comune in molti database NoSQL. Questa funzionalità può aiutarti a semplificare la progettazione della tua app

Esegui una query che non utilizza alcun indice. Stai cercando le prime N occorrenze, dato un particolare valore di colonna. Questa è una query comune in Amazon DynamoDB per ottimizzare l'efficienza del database.

  1. Vai a Spanner.

    Vai a Spanner

  2. Fai clic su Spanner Studio.

    Pulsante di interrogazione

  3. Nel campo Query, inserisci la seguente query e poi fai clic su Esegui query.

    SELECT Username,PointsEarned
      FROM Migration
     WHERE Subscribed=true
       AND ReminderDate > DATE_SUB(DATE(current_timestamp()), INTERVAL 14 DAY)
     ORDER BY ReminderDate DESC
     LIMIT 10
    

    Dopo l'esecuzione della query, fai clic su Spiegazione e prendi nota delle Righe analizzate rispetto alle Righe restituite. Senza un indice, Spanner analizza l'intera tabella per restituire un piccolo sottoinsieme di dati che corrispondono alla query.

    Righe scansionate rispetto alle righe restituite

  4. Se questa query si verifica di frequente, crea un indice composito sulle colonne Subscribed e ReminderDate. Nella console Spanner, seleziona Indici nel riquadro di navigazione a sinistra, quindi fai clic su Crea indice.

  5. Nella casella di testo, inserisci la definizione dell'indice.

    CREATE INDEX SubscribedDateDesc
    ON Migration (
      Subscribed,
      ReminderDate DESC
    )
    
  6. Per iniziare a creare il database in background, fai clic su Crea.

    Aggiornamento dello schema in corso…

  7. Dopo aver creato l'indice, esegui nuovamente la query e aggiungi l'indice.

    SELECT Username,PointsEarned
      FROM Migration@{FORCE_INDEX=SubscribedDateDesc}
     WHERE Subscribed=true
       AND ReminderDate > DATE_SUB(DATE(current_timestamp()), INTERVAL 14 DAY)
     ORDER BY ReminderDate DESC
     LIMIT 10
    

    Esamina nuovamente la spiegazione della query. Si noti che il numero di Righe scansionate è diminuito. ILRighe restituite ad ogni passaggio corrisponde al numero restituito dalla query.

    Spiegazione della query

Indici intercalati

In Spanner è possibile impostare indici interlacciati. Gli indici secondari discussi nella sezione precedente si trovano alla radice della gerarchia del database e utilizzano gli indici nello stesso modo di un database convenzionale. Un indice interlacciato si trova nel contesto della sua riga interlacciata. Vedi opzioni di indice per maggiori dettagli su dove applicare gli indici interlacciati.

Modificare il modello dei dati

Per adattare la parte relativa alla migrazione di questo tutorial alla tua situazione, modifica i file di origine Apache Beam. È importante non modificare lo schema di origine durante la finestra di migrazione effettiva, altrimenti potresti perdere dati.

  1. Per analizzare il JSON in entrata e creare mutazioni, utilizza GSON. Modifica la definizione JSON in modo che corrisponda ai tuoi dati.

    public static class Record implements Serializable {
    
      private Item Item;
    
    }
    
    public static class Item implements Serializable {
    
      private Username Username;
      private PointsEarned PointsEarned;
      private Subscribed Subscribed;
      private ReminderDate ReminderDate;
      private Zipcode Zipcode;
    
    }
    
    public static class Username implements Serializable {
    
      private String S;
    
    }
    
    public static class PointsEarned implements Serializable {
    
      private String N;
    
    }
    
    public static class Subscribed implements Serializable {
    
      private String BOOL;
    
    }
    
    public static class ReminderDate implements Serializable {
    
      private String S;
    
    }
    
    public static class Zipcode implements Serializable {
    
      private String N;
    
    }
  2. Modifica il mapping JSON corrispondente.

    mutation.set("Username").to(record.Item.Username.S);
    
    Optional.ofNullable(record.Item.Zipcode).ifPresent(x -> {
      mutation.set("Zipcode").to(Integer.parseInt(x.N));
    });
    
    Optional.ofNullable(record.Item.Subscribed).ifPresent(x -> {
      mutation.set("Subscribed").to(Boolean.parseBoolean(x.BOOL));
    });
    
    Optional.ofNullable(record.Item.ReminderDate).ifPresent(x -> {
      mutation.set("ReminderDate").to(Date.parseDate(x.S));
    });
    
    Optional.ofNullable(record.Item.PointsEarned).ifPresent(x -> {
      mutation.set("PointsEarned").to(Integer.parseInt(x.N));
    });

Nei passaggi precedenti, hai modificato il codice sorgente di Apache Beam per l'importazione collettiva. Modifica il codice sorgente per la parte di streaming della pipeline in modo simile. Infine, regola gli script di creazione delle tabelle, gli schemi e gli indici del database di destinazione di Spanner.

Esegui la pulizia

Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.

Elimina il progetto

  1. Nella console Google Cloud , vai alla pagina Gestisci risorse.

    Vai a Gestisci risorse

  2. Nell'elenco dei progetti, seleziona quello che vuoi eliminare, quindi fai clic su Elimina.
  3. Nella finestra di dialogo, digita l'ID progetto, quindi fai clic su Chiudi per eliminare il progetto.

Eliminare le risorse AWS

Se il tuo account AWS viene utilizzato al di fuori di questo tutorial, fai attenzione quando elimini le seguenti risorse:

  1. Elimina la tabella DynamoDB denominata Migration.
  2. Elimina il bucket Amazon S3 e la funzione Lambda che hai creato durante le fasi di migrazione.
  3. Infine, elimina l'utente AWS IAM che hai creato durante questo tutorial.

Passaggi successivi