Migre do DynamoDB para o Spanner

Este tutorial descreve como migrar do Amazon DynamoDB para o Spanner. Destina-se principalmente a proprietários de apps que pretendam migrar de um sistema NoSQL para o Spanner, um sistema de base de dados SQL totalmente relacional, tolerante a falhas e altamente escalável que suporta transações. Se tiver uma utilização consistente da tabela do Amazon DynamoDB, em termos de tipos e esquema, o mapeamento para o Spanner é simples. Se as suas tabelas do Amazon DynamoDB contiverem tipos de dados e valores arbitrários, pode ser mais simples mudar para outros serviços NoSQL, como o Datastore ou o Firestore.

Este tutorial pressupõe que tem conhecimentos sobre esquemas de bases de dados, tipos de dados, os fundamentos do NoSQL e sistemas de bases de dados relacionais. O tutorial baseia-se na execução de tarefas predefinidas para realizar uma migração de exemplo. Após o tutorial, pode modificar o código e os passos fornecidos para corresponderem ao seu ambiente.

O diagrama de arquitetura seguinte descreve os componentes usados no tutorial para migrar dados:

Diagrama arquitetónico dos componentes de migração

Objetivos

  • Migre dados do Amazon DynamoDB para o Spanner.
  • Crie uma base de dados do Spanner e uma tabela de migração.
  • Mapear um esquema NoSQL para um esquema relacional.
  • Crie e exporte um conjunto de dados de exemplo que use o Amazon DynamoDB.
  • Transfira dados entre o Amazon S3 e o Cloud Storage.
  • Use o Dataflow para carregar dados no Spanner.

Custos

Este tutorial usa os seguintes componentes faturáveis do Google Cloud:

As cobranças do Spanner baseiam-se na quantidade de capacidade de computação na sua instância e na quantidade de dados armazenados durante o ciclo de faturação mensal. Durante o tutorial, usa uma configuração mínima destes recursos, que são limpos no final. Para cenários do mundo real, estime os seus requisitos de débito e armazenamento e, em seguida, use a documentação de instâncias do Spanner para determinar a quantidade de capacidade de computação de que precisa.

Além dos Google Cloud recursos, este tutorial usa os seguintes recursos dos Amazon Web Services (AWS):

  • AWS Lambda
  • Amazon S3
  • Amazon DynamoDB

Estes serviços só são necessários durante o processo de migração. No final do tutorial, siga as instruções para limpar todos os recursos e evitar cobranças desnecessárias. Use a calculadora de preços da AWS para estimar estes custos.

Para gerar uma estimativa de custos com base na sua utilização projetada, use a calculadora de preços.

Antes de começar

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  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 (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 Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. 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 (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 Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  8. Quando terminar as tarefas descritas neste documento, pode evitar a faturação contínua eliminando os recursos que criou. Para mais informações, consulte o artigo Limpe.

    Prepare o seu ambiente

    Neste tutorial, executa comandos no Cloud Shell. O Cloud Shell dá-lhe acesso à linha de comandos no Google Cloude inclui a CLI gcloud e outras ferramentas de que precisa para o Google Cloud desenvolvimento. O Cloud Shell pode demorar vários minutos a ser inicializado.

    1. In the Google Cloud console, activate Cloud Shell.

      Activate Cloud Shell

      At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

    2. Defina a zona predefinida do Compute Engine. Por exemplo, us-central1-b. gcloud config set compute/zone us-central1-b
    3. Clone o repositório do GitHub que contém o código de exemplo. git clone https://github.com/GoogleCloudPlatform/dynamodb-spanner-migration.git
    4. Aceda ao diretório clonado. cd dynamodb-spanner-migration
    5. Crie um ambiente virtual do Python. pip3 install virtualenv virtualenv env
    6. Ative o ambiente virtual. source env/bin/activate
    7. Instale os módulos Python necessários. pip3 install -r requirements.txt
    8. Configure o acesso à AWS

      Neste tutorial, vai criar e eliminar tabelas do Amazon DynamoDB, contentores do Amazon S3 e outros recursos. Para aceder a estes recursos, tem de criar primeiro as autorizações necessárias da gestão de identidade e de acesso (IAM) da AWS. Pode usar uma conta de teste ou sandbox da AWS para evitar afetar os recursos de produção na mesma conta.

      Crie uma função de IAM do AWS para o AWS Lambda

      Nesta secção, cria uma função de IAM do AWS que o AWS Lambda usa num passo posterior no tutorial.

      1. Na consola da AWS, aceda à secção IAM, clique em Funções e, de seguida, selecione Criar função.
      2. Em Tipo de entidade fidedigna, certifique-se de que Serviço AWS está selecionado.
      3. Em Exemplo de utilização, selecione Lambda e, de seguida, clique em Seguinte.
      4. Na caixa de filtro Políticas de autorização, introduza AWSLambdaDynamoDBExecutionRole e prima Return para pesquisar.
      5. Selecione a caixa de verificação AWSLambdaDynamoDBExecutionRole e, de seguida, clique em Seguinte.
      6. Na caixa Nome da função, introduza dynamodb-spanner-lambda-role e, de seguida, clique em Criar função.

      Crie um utilizador do IAM da AWS

      Siga estes passos para criar um utilizador do IAM da AWS com acesso programático aos recursos da AWS, que são usados ao longo do tutorial.

      1. Enquanto estiver na secção IAM da consola da AWS, clique em Utilizadores e, de seguida, selecione Adicionar utilizadores.
      2. Na caixa Nome de utilizador, introduza dynamodb-spanner-migration.
      3. Em Tipo de acesso, selecione a caixa de verificação à esquerda de Chave de acesso - Acesso programático.

      4. Clique em Seguinte: autorizações.

      5. Clique em Anexe políticas existentes diretamente e, na caixa Pesquisar, para filtrar, selecione a caixa de verificação junto a cada uma das seguintes três políticas:

        • AmazonDynamoDBFullAccess
        • AmazonS3FullAccess
        • AWSLambda_FullAccess
      6. Clique em Seguinte: etiquetas e Seguinte: revisão e, de seguida, clique em Criar utilizador.

      7. Clique em Mostrar para ver as credenciais. O ID da chave de acesso e a chave de acesso secreta são apresentados para o utilizador recém-criado. Deixe esta janela aberta por agora, porque as credenciais são necessárias na secção seguinte. Armazene estas credenciais em segurança, uma vez que, com elas, pode fazer alterações à sua conta e afetar o seu ambiente. No final deste tutorial, pode eliminar o utilizador do IAM.

      Configure a interface de linhas de comando da AWS

      1. No Cloud Shell, configure a interface de linhas de comando (CLI) da AWS.

        aws configure
        

        É apresentado o seguinte resultado:

        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]:
        
        • Introduza o ACCESS KEY ID e o SECRET ACCESS KEY da conta do AWS IAM que criou.
        • No campo Nome da região predefinida, introduza us-west-2. Deixe os outros campos com os respetivos valores predefinidos.
      2. Feche a janela da consola do AWS IAM.

      Compreenda o modelo de dados

      A secção seguinte descreve as semelhanças e as diferenças entre os tipos de dados, as chaves e os índices do Amazon DynamoDB e do Spanner.

      Tipos de dados

      O Spanner usa tipos de dados GoogleSQL. A tabela seguinte descreve como os tipos de dados do Amazon DynamoDB são mapeados para os tipos de dados do Spanner.

      Amazon DynamoDB Spanner
      Número Consoante a precisão ou a utilização pretendida, pode ser mapeado para INT64, FLOAT64, TIMESTAMP ou DATE.
      String String
      Booleano BOOL
      Nulo Nenhum tipo explícito. As colunas podem conter valores nulos.
      Binário Bytes
      Conjuntos Matriz
      Mapa e lista Struct se a estrutura for consistente e puder ser descrita através da sintaxe DDL de tabelas.

      Chave principal

      Uma chave primária do Amazon DynamoDB estabelece a unicidade e pode ser uma chave hash ou uma combinação de uma chave hash e uma chave de intervalo. Este tutorial começa por demonstrar a migração de uma tabela do Amazon DynamoDB cuja chave principal é uma chave hash. Esta chave hash torna-se a chave principal da sua tabela do Spanner. Mais tarde, na secção sobre tabelas intercaladas, modela uma situação em que uma tabela do Amazon DynamoDB usa uma chave principal composta por uma chave de hash e uma chave de intervalo.

      Índices secundários

      O Amazon DynamoDB e o Spanner suportam a criação de um índice num atributo de chave não principal. Tome nota de todos os índices secundários na sua tabela do Amazon DynamoDB para que os possa criar na sua tabela do Spanner, o que é abordado numa secção posterior deste tutorial.

      Tabela de exemplo

      Para facilitar este tutorial, migra a seguinte tabela de exemplo do Amazon DynamoDB para o Spanner:

      Amazon DynamoDB Spanner
      Nome da tabela Migration Migration
      Chave principal "Username" : String "Username" : STRING(1024)
      Tipo de chave Hash N/A
      Outros campos Zipcode: Number Subscribed: Boolean ReminderDate: String PointsEarned: Number Zipcode: INT64 Subscribed: BOOL ReminderDate: DATE PointsEarned: INT64

      Prepare a tabela do Amazon DynamoDB

      Na secção seguinte, cria uma tabela de origem do Amazon DynamoDB e preenche-a com dados.

      1. No Cloud Shell, crie uma tabela do Amazon DynamoDB que use os atributos da tabela de exemplo.

        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. Verifique se o estado da tabela é ACTIVE.

        aws dynamodb describe-table --table-name Migration \
            --query 'Table.TableStatus'
        
      3. Preencha a tabela com dados de exemplo.

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

      Crie uma base de dados do Spanner

      Cria uma instância do Spanner com a capacidade de computação mais pequena possível: 100 unidades de processamento. Esta capacidade de computação é suficiente para o âmbito deste tutorial. Para uma implementação de produção, consulte a documentação sobre as instâncias do Spanner para determinar a capacidade de computação adequada para cumprir os requisitos de desempenho da base de dados.

      Neste exemplo, cria um esquema de tabela ao mesmo tempo que a base de dados. Também é possível, e comum, fazer atualizações do esquema depois de criar a base de dados.

      1. Crie uma instância do Spanner na mesma região onde definiu a zona predefinida do Compute Engine. Por exemplo, us-central1.

        gcloud beta spanner instances create spanner-migration \
            --config=regional-us-central1 --processing-units=100 \
            --description="Migration Demo"
        
      2. Crie uma base de dados na instância do Spanner juntamente com a tabela de exemplo.

        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)"
        

      Prepare a migração

      As secções seguintes mostram como exportar a tabela de origem do Amazon DynamoDB e definir a replicação do Pub/Sub para captar quaisquer alterações à base de dados que ocorram enquanto a exporta.

      Transmita alterações para o Pub/Sub

      Usa uma função AWS Lambda para transmitir alterações da base de dados para o Pub/Sub.

      1. No Cloud Shell, ative as streams do Amazon DynamoDB na tabela de origem.

        aws dynamodb update-table --table-name Migration \
            --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES
        
      2. Configure um tópico Pub/Sub para receber as alterações.

        gcloud pubsub topics create spanner-migration
        

        É apresentado o seguinte resultado:

        Created topic [projects/your-project/topics/spanner-migration].
        
      3. Crie uma conta de serviço do IAM para enviar atualizações de tabelas para o tópico do Pub/Sub.

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

        É apresentado o seguinte resultado:

        Created service account [spanner-migration].
        
      4. Crie uma associação de políticas de IAM para que a conta de serviço tenha autorização para publicar no Pub/Sub. Substitua GOOGLE_CLOUD_PROJECT pelo nome do seu Google Cloud projeto.

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

        É apresentado o seguinte resultado:

        bindings:
        (...truncated...)
        - members:
          - serviceAccount:spanner-migration@solution-z.iam.gserviceaccount.com
          role: roles/pubsub.publisher
        
      5. Crie credenciais para a conta de serviço.

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

        É apresentado o seguinte resultado:

        created key [5e559d9f6bd8293da31b472d85a233a3fd9b381c] of type [json] as [credentials.json] for [spanner-migration@your-project.iam.gserviceaccount.com]
        
      6. Prepare e embale a função AWS Lambda para enviar alterações da tabela do Amazon DynamoDB para o tópico do 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. Crie uma variável para capturar o Nome do recurso da Amazon (ARN) da função de execução do Lambda que criou anteriormente.

        LAMBDA_ROLE=$(aws iam list-roles \
            --query 'Roles[?RoleName==`dynamodb-spanner-lambda-role`].[Arn]' \
            --output text)
        
      8. Use o pacote pubsub-lambda.zip para criar a função 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}"
        

        É apresentado o seguinte resultado:

        {
            "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. Crie uma variável para capturar o ARN da stream do Amazon DynamoDB para a sua tabela.

        STREAMARN=$(aws dynamodb describe-table \
            --table-name Migration \
            --query "Table.LatestStreamArn" \
            --output text)
        
      10. Associe a função Lambda à tabela do Amazon DynamoDB.

        aws lambda create-event-source-mapping --event-source ${STREAMARN} \
            --function-name dynamodb-spanner-lambda --enabled \
            --starting-position TRIM_HORIZON
        
      11. Para otimizar a capacidade de resposta durante os testes, adicione --batch-size 1 ao final do comando anterior, o que aciona a função sempre que cria, atualiza ou elimina um item.

        Vai ver um resultado semelhante ao seguinte:

        {
            "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...
        

      Exporte a tabela do Amazon DynamoDB para o Amazon S3

      1. No Cloud Shell, crie uma variável para um nome de contentor que usa em várias das secções seguintes.

        BUCKET=${DEVSHELL_PROJECT_ID}-dynamodb-spanner-export
        
      2. Crie um contentor do Amazon S3 para receber a exportação do DynamoDB.

        aws s3 mb s3://${BUCKET}
        
      3. Na AWS Management Console, aceda a DynamoDB e clique em Tables.

      4. Clique na tabela Migration.

      5. No separador Exportações e stream, clique em Exportar para o S3.

      6. Ative a point-in-time-recovery (PITR) se lhe for pedido.

      7. Clique em Procurar S3 para escolher o contentor S3 que criou anteriormente.

      8. Clique em Exportar.

      9. Clique no ícone Atualizar para atualizar o estado da tarefa de exportação. A tarefa demora vários minutos a concluir a exportação.

        Quando o processo terminar, consulte o contentor de saída.

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

        Este passo deve demorar cerca de 5 minutos. Após a conclusão, vê um resultado semelhante ao seguinte:

        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
        

      Faça a migração

      Agora que a entrega do Pub/Sub está implementada, pode avançar com quaisquer alterações à tabela que tenham ocorrido após a exportação.

      Copie a tabela exportada para o Cloud Storage

      1. No Cloud Shell, crie um contentor do Cloud Storage para receber os ficheiros exportados do Amazon S3.

        gcloud storage buckets create gs://${BUCKET}
        
      2. Sincronize os ficheiros do Amazon S3 para o Cloud Storage. Para a maioria das operações de cópia, o comando rsync é eficaz. Se os seus ficheiros de exportação forem grandes (vários GB ou mais), use o serviço de transferência do Cloud Storage para gerir a transferência em segundo plano.

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

      Importe os dados em lote

      1. Para escrever os dados dos ficheiros exportados na tabela do Spanner, execute uma tarefa do Dataflow com código de exemplo do 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. Para monitorizar o progresso da tarefa de importação, na Google Cloud consola, aceda ao Dataflow.

          Aceda ao Dataflow

        2. Enquanto a tarefa está em execução, pode ver o gráfico de execução para examinar os registos. Clique na tarefa que mostra o Estado de Em execução.

          Executar tarefa de importação

      2. Clique em cada fase para ver quantos elementos foram processados. A importação fica concluída quando todas as fases indicam Êxito. O mesmo número de elementos criados na sua tabela do Amazon DynamoDB é apresentado como processado em cada fase.

        Fases de êxito da tarefa de importação

      3. Verifique se o número de registos na tabela do Spanner de destino corresponde ao número de itens na tabela do DynamoDB da Amazon.

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

        É apresentado o seguinte resultado:

        $ 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. Examine aleatoriamente algumas entradas em cada tabela para se certificar de que os dados são consistentes.

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

        É apresentado o seguinte resultado:

         Username: aadams4495
         PointsEarned: 5247
         ReminderDate: 2022-03-14
         Subscribed: True
         Zipcode: 58057
        
      5. Consulte a tabela do Amazon DynamoDB com o mesmo Username que foi devolvido pela consulta do Spanner no passo anterior. Por exemplo, aallen2538. O valor é específico dos dados de amostra na sua base de dados.

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

        Os valores dos outros campos devem corresponder aos da saída do Spanner. É apresentado o seguinte resultado:

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

      Replique novas alterações

      Quando a tarefa de importação em lote estiver concluída, configura uma tarefa de streaming para escrever atualizações contínuas da tabela de origem no Spanner. Subscreva os eventos do Pub/Sub e escreva-os no Spanner

      A função Lambda que criou está configurada para capturar alterações à tabela do Amazon DynamoDB de origem e publicá-las no Pub/Sub.

      1. Crie uma subscrição para o tópico Pub/Sub para o qual o AWS Lambda envia eventos.

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

        É apresentado o seguinte resultado:

        Created subscription [projects/your-project/subscriptions/spanner-migration].
        
      2. Para transmitir as alterações que chegam ao Pub/Sub para escrever na tabela do Spanner, execute a tarefa do Dataflow a partir do 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. Semelhante ao passo de carregamento em lote, para ver o progresso da tarefa, na Google Cloud consola, aceda ao Dataflow.

          Aceda ao Dataflow

        2. Clique na tarefa com o Estado Em execução.

          Tarefa em execução

          O gráfico de processamento mostra uma saída semelhante à anterior, mas cada item processado é contabilizado na janela de estado. O tempo de atraso do sistema é uma estimativa aproximada do atraso esperado antes de as alterações aparecerem na tabela do Spanner.

          Processos em execução devido ao tempo de atraso

      A tarefa do Dataflow que executou na fase de carregamento em lote foi um conjunto finito de entradas, também conhecido como um conjunto de dados limitado. Esta tarefa do Dataflow usa o Pub/Sub como uma origem de streaming e é considerada ilimitada. Para mais informações sobre estes dois tipos de origens, reveja a secção sobre PCollections no guia de programação do Apache Beam. A tarefa do Dataflow neste passo destina-se a permanecer ativa, pelo que não termina quando estiver concluída. A tarefa de streaming do Dataflow permanece no estado Em execução, em vez do estado Concluído.

      Valide a replicação

      Faz algumas alterações à tabela de origem para verificar se as alterações são replicadas para a tabela do Spanner.

      1. Consultar uma linha inexistente no Spanner.

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

        A operação não devolve resultados.

      2. Crie um registo no Amazon DynamoDB com a mesma chave que usou na consulta do Spanner. Se o comando for executado com êxito, não é apresentado nenhum resultado.

        aws dynamodb put-item \
            --table-name Migration \
            --item '{"Username" : {"S" : "my-test-username"}, "Subscribed" : {"BOOL" : false}}'
        
      3. Execute novamente essa mesma consulta para verificar se a linha está agora no Spanner.

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

        O resultado mostra a linha inserida:

        Username: my-test-username
        PointsEarned: None
        ReminderDate: None
        Subscribed: False
        Zipcode:
        
      4. Altere alguns atributos no item original e atualize a tabela do 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
        

        Vai ver um resultado semelhante ao seguinte:

        {
            "Attributes": {
                "Username": {
                    "S": "my-test-username"
                },
                "PointsEarned": {
                    "N": "4500"
                },
                "Subscribed": {
                    "BOOL": true
                }
            }
        }
        
      5. Verifique se as alterações são propagadas para a tabela do Spanner.

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

        O resultado é apresentado da seguinte forma:

        Username          PointsEarned  ReminderDate  Subscribed  Zipcode
        my-test-username  4500          None          True
        
      6. Elimine o item de teste da tabela de origem do Amazon DynamoDB.

        aws dynamodb delete-item \
            --table-name Migration \
            --key '{"Username": {"S":"my-test-username"}}'
        
      7. Verifique se a linha correspondente é eliminada da tabela do Spanner. Quando a alteração é propagada, o seguinte comando devolve zero linhas:

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

      Use tabelas intercaladas

      O Spanner suporta o conceito de tabelas intercaladas. Este é um modelo de design em que um item de nível superior tem vários itens aninhados que se relacionam com esse item de nível superior, como um cliente e as respetivas encomendas, ou um jogador e as respetivas pontuações no jogo. Se a tabela de origem do Amazon DynamoDB usar uma chave principal composta por uma chave hash e uma chave de intervalo, pode modelar um esquema de tabela intercalado, conforme mostrado no diagrama seguinte. Esta estrutura permite-lhe consultar de forma eficiente a tabela intercalada enquanto junta campos na tabela principal.

      Tabela de utilizadores comparada com a tabela de encomendas

      Aplique índices secundários

      É uma prática recomendada aplicar índices secundários a tabelas do Spanner depois de carregar os dados. Agora que a replicação está a funcionar, configura um índice secundário para acelerar as consultas. Tal como as tabelas do Spanner, os índices secundários do Spanner são totalmente consistentes. Não são eventualmente consistentes, o que é comum em muitas bases de dados NoSQL. Esta funcionalidade pode ajudar a simplificar o design da sua app

      Execute uma consulta que não use nenhum índice. Procura as N principais ocorrências, dado um valor de coluna específico. Esta é uma consulta comum no Amazon DynamoDB para a eficiência da base de dados.

      1. Aceda ao Spanner.

        Aceda ao Spanner

      2. Clique em Spanner Studio.

        Botão de consulta

      3. No campo Consulta, introduza a seguinte consulta e, de seguida, clique em Executar consulta.

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

        Depois de executar a consulta, clique em Explicação e tome nota das Linhas analisadas em comparação com as Linhas devolvidas. Sem um índice, o Spanner analisa toda a tabela para devolver um pequeno subconjunto de dados que correspondem à consulta.

        Linhas analisadas em comparação com linhas devolvidas

      4. Se isto representar uma consulta que ocorre com frequência, crie um índice composto nas colunas Subscribed e ReminderDate. Na consola do Spanner, selecione Índices no painel de navegação do lado esquerdo e, de seguida, clique em Criar índice.

      5. Na caixa de texto, introduza a definição do índice.

        CREATE INDEX SubscribedDateDesc
        ON Migration (
          Subscribed,
          ReminderDate DESC
        )
        
      6. Para começar a criar a base de dados em segundo plano, clique em Criar.

        Atualização do esquema em curso

      7. Depois de criar o índice, execute a consulta novamente e adicione o índice.

        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
        

        Examine novamente a explicação da consulta. Repare que o número de Linhas analisadas diminuiu. As Linhas devolvidas em cada passo correspondem ao número devolvido pela consulta.

        Explicação da consulta

      Índices intercalados

      Pode configurar índices intercalados no Spanner. Os índices secundários abordados na secção anterior estão na raiz da hierarquia da base de dados e usam índices da mesma forma que uma base de dados convencional. Um índice intercalado está no contexto da respetiva linha intercalada. Consulte as opções de índice para ver mais detalhes sobre onde aplicar índices intercalados.

      Ajuste-as ao seu modelo de dados

      Para adaptar a parte de migração deste tutorial à sua situação, modifique os ficheiros de origem do Apache Beam. É importante que não altere o esquema de origem durante a janela de migração real. Caso contrário, pode perder dados.

      1. Para analisar o JSON recebido e criar mutações, use o GSON. Ajuste a definição de JSON para corresponder aos seus dados.

        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. Ajuste o mapeamento JSON correspondente.

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

      Nos passos anteriores, modificou o código fonte do Apache Beam para a importação em massa. Modifique o código-fonte da parte de streaming do pipeline de forma semelhante. Por fim, ajuste os scripts de criação de tabelas, os esquemas e os índices da base de dados de destino do Spanner.

      Limpar

      Para evitar incorrer em custos na sua Google Cloud conta pelos recursos usados neste tutorial, elimine o projeto que contém os recursos ou mantenha o projeto e elimine os recursos individuais.

      Elimine o projeto

      1. In the Google Cloud console, go to the Manage resources page.

        Go to Manage resources

      2. In the project list, select the project that you want to delete, and then click Delete.
      3. In the dialog, type the project ID, and then click Shut down to delete the project.

      Elimine recursos da AWS

      Se a sua conta da AWS for usada fora deste tutorial, tenha cuidado quando eliminar os seguintes recursos:

      1. Elimine a tabela do DynamoDB denominada Migration.
      2. Elimine o contentor do Amazon S3 e a função Lambda que criou durante os passos de migração.
      3. Por último, elimine o utilizador do IAM do AWS que criou durante este tutorial.

      O que se segue?