本文档介绍了如何使用 Terraform 部署 Dataflow 和 Datastream,以在停机时间最短的情况下将来源 MySQL 实例中的数据实时迁移到 Spanner。
执行实时数据迁移并确定所有数据都已转移,已迁移代码和依赖项并完成测试后,您可以将应用切换为使用 Spanner 而不是来源 MySQL 数据库。
创建目标 Spanner 数据库后,您可以执行实时数据迁移。您需要在目标数据库上创建兼容的架构,然后才能迁移数据。
工作原理
实时数据迁移包括以下两个阶段:
- 回填迁移: - 在回填迁移期间,Dataflow 会从来源 MySQL 数据库读取现有数据,并将这些数据迁移到目标 Spanner 数据库。您需要使用批量迁移 Dataflow 模板将数据从来源 MySQL 实例迁移到 Spanner。
- 如果回填迁移无法将某行写入 Spanner,则会将该行写入 Cloud Storage 存储桶中的死信队列目录。您可以让回填迁移重试将这些行写入 Spanner。
 
- 变更数据捕获 (CDC) 迁移: - 此阶段与回填迁移同时运行,可实时捕获来源 MySQL 实例中发生的更改。然后,在回填迁移完成后,这些更改会应用于 Spanner。
- 您需要使用 Datastream 实时捕获来源 MySQL 实例中发生的更改,并将其写入 Cloud Storage 存储桶。
- 回填迁移完成后,您需要使用 Dataflow 将 CDC 从 Cloud Storage 存储桶迁移到 Spanner。如果 Dataflow 因任何原因无法将某行写入 Spanner,则会将该行写入其他 Cloud Storage 存储桶中的死信队列目录。CDC 迁移会自动重试将死信队列目录中的行写入 Spanner。
 
规划实时数据迁移
您需要配置数据在来源 MySQL 实例、Datastream、Dataflow、Cloud Storage 存储桶和目标 Spanner 数据库之间流动所需的网络基础设施。我们建议您配置专用网络连接,以确保迁移安全无虞。根据组织的合规性要求,您可能需要配置公共或专用网络连接。如需详细了解 Datastream 连接,请参阅网络连接选项。
如需规划实时数据迁移,您可能需要组织的网络管理员执行以下任务:
- 使用默认 VPC 或在项目中创建符合以下要求的新 VPC:
- 来源 MySQL 实例必须在此 VPC 上可用。您可能需要在此 VPC 上创建出站流量防火墙规则,并在来源 MySQL 实例所在的 VPC 上创建入站流量防火墙规则。
- Datastream、Dataflow、Cloud Storage 存储桶和目标 Spanner 数据库必须在此 VPC 上可用。
- 您必须在来源 MySQL 实例上创建许可清单,以允许来自 VPC 的连接。
 
- 确定并分配 Datastream 可使用的 VPC 中的 IP 地址范围。
- 在 VPC 中创建一个子网,供 Dataflow 用于完成回填迁移。
- 在 VPC 中创建一个子网,供 Dataflow 稍后用于完成 CDC 迁移。
您可以按照以下步骤执行实时数据迁移:
执行实时数据迁移需要部署和管理大量资源。Spanner 为实时数据迁移的每个阶段提供了两个示例 Terraform 模板。
实时迁移模板分两个阶段执行 CDC 迁移:
- 使用 Datastream 设置 CDC 迁移到 Cloud Storage 存储桶。您可以使用 Terraform 变量来阻止模板创建 Dataflow 作业。
- 使用 Dataflow 将 Cloud Storage 存储桶中的 CDC 迁移到 Spanner。只有在回填迁移 Terraform 模板完成回填迁移后,您才能执行此阶段。
回填迁移 Terraform 模板用于执行从来源 MySQL 实例到 Spanner 的回填迁移。
准备工作
- 确保在本地 shell 上安装了 Terraform。
- 创建一个服务账号以运行实时数据迁移。如需详细了解如何创建服务账号,请参阅创建服务账号。
- 
  
  
  
  
  
  
  
    
    
    
    
    
    
      
      
        
        
      
      
    
      
      
        
        
      
      
    
      
      
        
        
      
      
    
      
      
        
        
      
      
    
      
      
        
        
      
      
    
      
      
        
        
      
      
    
      
      
        
        
      
      
    
      
      
        
        
      
      
    
    
    
    
    
  
  
  
  
  
  
  
    
    
    
    
  
    
    
    
    
      
      
      
      
      
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
        
        
          
        
        
      
      
      
      
      
    
  
  为确保服务账号具有执行实时迁移所需的权限,请让您的管理员为服务账号授予项目的以下 IAM 角色: - 
  
  
    
      Dataflow Admin (roles/dataflow.admin)
- 
  
  
    
      Datastream Admin (roles/datastream.admin)
- 
  
  
    
      Security Admin (roles/iam.securityAdmin)
- 
  
  
    
      Service Account Admin (roles/serviceAccountAdmin)
- 
  
  
    
      Pub/Sub Admin  (roles/pubsub.admin)
- 
  
  
    
      Storage Admin  (roles/storage.admin)
- 
  
  
    
      Compute Network Admin (roles/compute.networkAdmin)
- 
  
  
    
      Viewer (roles/viewer)
 如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限。 这些预定义角色具有执行实时迁移所需的权限。如需查看所需的确切权限,请展开所需权限部分: 所需权限执行实时迁移需要以下权限: - 
                  compute.globalAddresses.create
- 
                  compute.globalAddresses.createInternal
- 
                  compute.globalAddresses.createInternal
- 
                  compute.globalAddresses.delete
- 
                  compute.globalAddresses.deleteInternal
- 
                  compute.globalAddresses.get
- 
                  compute.globalOperations.get
- 
                  compute.networks.addPeering
- 
                  compute.networks.get
- 
                  compute.networks.listPeeringRoutes
- 
                  compute.networks.removePeering
- 
                  compute.networks.use
- 
                  compute.routes.get
- 
                  compute.routes.list
- 
                  compute.subnetworks.get
- 
                  compute.subnetworks.list
- 
                  dataflow.jobs.cancel
- 
                  dataflow.jobs.create
- 
                  dataflow.jobs.updateContents
- 
                  datastream.connectionProfiles.create
- 
                  datastream.connectionProfiles.delete
- 
                  datastream.privateConnections.create
- 
                  datastream.privateConnections.delete
- 
                  datastream.streams.create
- 
                  datastream.streams.delete
- 
                  datastream.streams.update
- 
                  iam.roles.get
- 
                  iam.serviceAccounts.actAs
- 
                  pubsub.subscriptions.create
- 
                  pubsub.subscriptions.delete
- 
                  pubsub.topics.attachSubscription
- 
                  pubsub.topics.create
- 
                  pubsub.topics.delete
- 
                  pubsub.topics.getIamPolicy
- 
                  pubsub.topics.setIamPolicy
- 
                  resourcemanager.projects.setIamPolicy
- 
                  storage.buckets.create
- 
                  storage.buckets.delete
- 
                  storage.buckets.update
- 
                  storage.objects.delete
 
- 
  
  
    
      Dataflow Admin (
设置 CDC 迁移
Spanner 提供了一个 Terraform 模板,用于设置 CDC,稍后完成 CDC 迁移。您可以使用 Terraform 变量来禁止该模板创建 Dataflow 作业。Terraform 模板会部署和管理以下资源来设置 CDC 迁移:
- Datastream 专用连接:Datastream 专用连接部署在您配置的 VPC 上。 
- 来源 Datastream 连接配置文件:一种连接配置文件,可让 Datastream 连接到来源 MySQL 实例。 
- Cloud Storage 存储桶:Datastream 将数据写入到的 Cloud Storage 存储桶。 
- 目标 Datastream 连接配置文件:此连接配置文件可让 Datastream 连接到 Cloud Storage 存储桶并将数据写入其中。 
- Datastream 数据流:从来源 MySQL 实例读取数据并写入 Cloud Storage 存储桶的 Datastream 数据流,如连接配置文件中所定义。 
- Pub/Sub 主题和订阅:Cloud Storage 存储桶将对象通知发送到 Pub/Sub 主题,而 Dataflow 使用 Pub/Sub 订阅将数据写入 Spanner。 
- Cloud Storage 存储桶通知:发布到 Pub/Sub 主题的 Cloud Storage 存储桶通知。 
准备 CDC Terraform 配置
您可以准备 Terraform 模板,使其包含 Dataflow 变量配置,但禁止创建 Dataflow 作业:
    common_params = {
      project = "PROJECT_ID"
      region  = "GCP_REGION"
    }
    datastream_params = {
      mysql_host = "MYSQL_HOST_IP_ADDRESS"
      mysql_username = "MYSQL_USERNAME"
      mysql_password = "MYSQL_PASSWORD"
      mysql_port     = 3306
      mysql_database = {
        database = "DATABASE_NAME"
      }
      private_connectivity = {
        vpc_name = "VPC_NAME"
        range = "RESERVED_RANGE"
      }
    }
    dataflow_params = {
      skip_dataflow = false
      enable_backfill = false
      template_params = {
        spanner_database_id = "SPANNER_DATABASE_ID"
        spanner_instance_id = "SPANNER_INSTANCE_ID"
      }
      runner_params = {
        max_workers = 10
        num_workers = 4
        on_delete   = "cancel"
        network     = "VPC_NETWORK"
        subnetwork  = "SUBNETWORK_NAME"
      }
    }
  以下列表介绍了 Terraform 变量:
- project: Google Cloud 项目 ID。
- region: Google Cloud 区域。
- mysql_host:来源 MySQL 实例 IP 地址。
- mysql_username:来源 MySQL 实例用户名。
- mysql_password:来源 MySQL 实例密码。
- mysql_port:来源 MySQL 实例端口号。
- database:实例中的来源 MySQL 数据库名称。
- vpc_name:Datastream 使用的现有 VPC 的名称。
- range:您在 VPC 上预留供 Datastream 使用的 IP 范围。
- skip_dataflow:将此值设置为- true可禁止 Dataflow 创建 Dataflow 作业。
- enable_backfill:将此值设置为- false可禁止 Terraform 模板创建 Dataflow 作业。
- spanner_database_id:目标 Spanner 数据库 ID。
- spanner_instance_id:目标 Spanner 实例 ID。
- max_workers:用于确定 Dataflow 创建的工作器数量上限。
- min_workers:用于确定 Dataflow 创建的工作器数量下限。
- network:Dataflow 将要使用的现有 VPC 的名称。
- subnetwork:VPC 中 Dataflow 可以创建工作器的指定子网的名称。
运行 CDC Terraform 模板
如需执行 CDC 迁移,您需要运行 Terraform 模板:
- 使用以下命令初始化 Terraform: - terraform init 
- 使用以下命令验证 Terraform 文件: - terraform plan --var-file=terraform_simple.tfvars 
- 使用以下命令运行 Terraform 配置: - terraform apply --var-file=terraform_simple.tfvars - Terraform 配置会生成如下所示的输出: - Outputs: resource_ids = { "datastream_source_connection_profile" = "source-mysql-thorough-wombat" "datastream_stream" = "mysql-stream-thorough-wombat" "datastream_target_connection_profile" = "target-gcs-thorough-wombat" "gcs_bucket" = "live-migration-thorough-wombat" "pubsub_subscription" = "live-migration-thorough-wombat-sub" "pubsub_topic" = "live-migration-thorough-wombat" } resource_urls = { "datastream_source_connection_profile" = "https://console.cloud.google.com/datastream/connection-profiles/locations/us-central1/instances/source-mysql-thorough-wombat?project=your-project-here" "datastream_stream" = "https://console.cloud.google.com/datastream/streams/locations/us-central1/instances/mysql-stream-thorough-wombat?project=your-project-here" "datastream_target_connection_profile" = "https://console.cloud.google.com/datastream/connection-profiles/locations/us-central1/instances/target-gcs-thorough-wombat?project=your-project-here" "gcs_bucket" = "https://console.cloud.google.com/storage/browser/live-migration-thorough-wombat?project=your-project-here" "pubsub_subscription" = "https://console.cloud.google.com/cloudpubsub/subscription/detail/live-migration-thorough-wombat-sub?project=your-project-here" "pubsub_topic" = "https://console.cloud.google.com/cloudpubsub/topic/detail/live-migration-thorough-wombat?project=your-project-here" }
Datastream 现在正在将 CDC 流式传输到 Cloud Storage 存储桶。您必须执行回填迁移,并在稍后完成 CDC 迁移。
执行回填迁移
Spanner 提供了一个 Terraform 模板来执行回填迁移。Terraform 模板会部署和管理以下资源:
- Dataflow 作业:从来源 MySQL 实例读取数据并写入目标 Spanner 数据库的 Dataflow 作业。
准备回填迁移 Terraform 配置
    job_name = "JOB_NAME"
    project = "PROJECT_ID"
    region = "GCP_REGION"
    working_directory_bucket = "WORKING_DIRECTORY_BUCKET"
    working_directory_prefix = "WORKING_DIRECTORY_PREFIX"
    source_config_url = "SOURCE_CONFIG_URL"
    username = "USERNAME"
    password = "PASSWORD"
    instance_id = "SPANNER_INSTANCE_ID"
    database_id  = "SPANNER_DATABASE_ID"
    spanner_project_id = "SPANNER_PROJECT_ID"
  以下列表介绍了 Terraform 变量:
- job_name:Dataflow 作业名称。
- project:Dataflow 作业需要在其中运行的 Google Cloud 项目的 ID。
- region: Google Cloud 区域。
- working_directory_bucket:用于上传会话文件和创建输出目录的 Cloud Storage 存储桶。
- working_directory_prefix:Dataflow 工作目录的 Cloud Storage 存储桶前缀。
- source_config_url:来源 MySQL 实例 IP 地址。
- username:来源 MySQL 实例用户名。
- password:来源 MySQL 实例密码。
- instance_id:目标 Spanner 实例 ID。
- database_id:目标 Spanner 数据库 ID。
- spanner_project_id:Spanner 实例所在的项目的 ID。此项目 ID 可以与在其中运行 Dataflow 的项目不同。
运行回填迁移 Terraform 模板
如需执行回填迁移,请执行以下操作:
- 使用以下命令初始化 Terraform: - terraform init 
- 使用以下命令验证 Terraform 文件: - terraform plan --var-file=terraform_simple.tfvars 
- 使用以下命令运行 Terraform 配置: - terraform apply --var-file=terraform_simple.tfvars - Terraform 配置会生成如下所示的输出: - Apply complete! Resources: 1 added, 0 changed, 0 destroyed. Outputs: dataflow_job_id = [ "2024-06-05_00_41_11-4759981257849547781", ] dataflow_job_url = [ "https://console.cloud.google.com/dataflow/jobs/gcp-region/2024-06-05_00_41_11-4759981257849547781", ] 
如果回填迁移无法将某行写入 Spanner,它会将该行写入 Cloud Storage 存储桶中的死信队列目录。
在完成 CDC 迁移之前,您可以重试将这些行从死信队列目录写入 Spanner。
如需在完成 CDC 迁移之前,重试将这些行从死信队列目录写入 Spanner,请运行以下命令:
gcloud dataflow flex-template run JOB_NAME \ --region=GCP_REGION \ --template-file-gcs-location=gs://dataflow-templates/latest/flex/Cloud_Datastream_to_Spanner \ --additional-experiments=use_runner_v2 \ --parameters inputFilePattern=inputFilePattern,streamName="ignore", \ --datastreamSourceType=SOURCE_TYPE\ instanceId=INSTANCE_ID,databaseId=DATABASE_ID,sessionFilePath=SESSION_FILE_PATH, \ deadLetterQueueDirectory=DLQ_DIRECTORY,runMode="retryDLQ"
以下列表介绍了 gcloud CLI 命令变量:
- job_name:Dataflow 作业名称。
- region: Google Cloud 区域。
- inputFilePattern:输入文件模式的 Cloud Storage 存储桶位置。
- datastreamSourceType:来源类型,例如 MySQL。
- instanceId:目标 Spanner 实例 ID。
- databaseId:目标 Spanner 数据库 ID。
- sessionFilePath:会话文件的 Cloud Storage 存储桶路径。
- deadLetterQueueDirectory:DLQ 目录的 Cloud Storage 存储桶路径。
完成 CDC 迁移
回填迁移完成后,您可以使用 Dataflow 将 CDC 迁移到 Spanner。Dataflow 作业会从 Cloud Storage 存储桶中获取更改事件,并将其写入 Spanner。
在 Cloud Storage 存储桶中的几乎所有数据都写入 Spanner 后,停止对来源 MySQL 实例的写入操作,以便将其余的更改写入 Spanner。
这会导致短暂停机,因为 Spanner 需要与来源 MySQL 实例同步。所有更改都写入 Spanner 后,您的应用可以开始使用 Spanner 作为数据库。
如需完成 CDC 迁移,请将 skip_dataflow Terraform 参数的值更改为 false,然后重新运行实时迁移 Terraform 模板。
使用以下命令运行 Terraform 配置:
      terraform apply --var-file=terraform_simple.tfvars