迁移问题排查

本部分提供了一些提示,可帮助您排查在创建和管理 Datastream 和 Dataflow 流水线时可能出现的常见问题。

排查 Datastream 连接配置文件问题

迁移过程需要您创建两个 Datastream 连接配置文件:一个用于从源 MongoDB 兼容数据库读取数据,另一个用于将数据写入 Cloud Storage 存储桶。

这些步骤使用 gcloud datastream connection-profiles create 命令。 使用此命令创建 Datastream 连接配置文件时,系统会返回类似于以下示例的元数据:

metadata:
  '@type': type.googleapis.com/google.cloud.datastream.v1.OperationMetadata
  apiVersion: v1
  createTime: '2025-05-15T21:49:05.022509533Z'
  requestedCancellation: false
  target: projects/PROJECT_ID/locations/LOCATION/connectionProfiles/SRC_CONNECTION_PROFILE_NAME
  verb: create
name: projects/PROJECT_ID/locations/LOCATION/operations/operation-1747345744961-63533a26d9ee6-b2386fbf-204c28d6

您可以使用以 operation- 开头的突出显示的标识符来检索指定 Datastream 操作的状态。对于上述输出示例,以下 gcloud CLI 命令会检索连接配置文件创建请求的详细信息:

gcloud datastream operations describe \
operation-1747345744961-63533a26d9ee6-b2386fbf-204c28d6 \
--location="$LOCATION"

您可以在 Google Cloud 控制台中检查 Datastream 连接配置文件和其他 Datastream 制品。

在 Google Cloud 控制台中,前往 Datastream 页面:

前往 Datastream

排查 Datastream 数据流问题

使用 gcloud datastream streams create 命令创建 Datastream 流时,系统会返回类似于以下示例的元数据:

metadata:
  '@type': type.googleapis.com/google.cloud.datastream.v1.OperationMetadata
  apiVersion: v1
  createTime: '2025-05-14T19:31:20.209503095Z'
  requestedCancellation: false
  target: projects/PROJECT_ID/locations/LOCATION/streams/DATASTREAM_NAME
  verb: create
  name: projects/PROJECT_ID/locations/LOCATION/operations/operation-1747251080085-6351d97f63eb8-43204f78-35c87474

您可以使用以 operation- 开头的突出显示的标识符来检索指定 Datastream 操作的状态。对于上述输出示例,以下 gcloud CLI 命令会检索有关数据流创建请求的详细信息:

gcloud datastream operations describe \
operation-1747345744961-63533a26d9ee6-b2386fbf-204c28d6 \
--location="$LOCATION"

如需查找现有直播的状态,请使用以下命令:

gcloud datastream streams describe $DATASTREAM_NAME --location=$LOCATION

您可以在 Google Cloud 控制台中检查 Datastream 流和其他 Datastream 制品。

在 Google Cloud 控制台中,前往 Datastream 页面:

前往 Datastream

排查 Dataflow 流水线问题

您可以在 Google Cloud 控制台中监控 Dataflow 流水线的执行情况。

在 Google Cloud 控制台中,前往 Dataflow 页面:

转到 Dataflow

排查可重试错误

可重试错误是最终会成功的暂时性错误。常见的可重试错误包括:

  • 网络或连接问题
  • 交易争用
  • 因负载均衡而关闭的连接

因出现错误而无法写入目标位置的文档将存储在 Cloud Storage 存储桶中,存储位置由 Dataflow 模板的 deadLetterQueueDirectory 参数指定。默认情况下,可重试的错误最多会重试 dlqMaxRetryCount 参数指定的次数。

通过前往 DLQ_LOCATION 环境变量中指定的路径,可以直接从 Cloud Storage 检查死信队列 (DLQ)。该路径将包含一个时间戳文件夹层次结构,其中包含无法写入与 MongoDB 兼容的 Firestore 数据库的文档和更新的 JSON 记录。

假设死信队列仅包含因可重试错误而失败的文档,您可以尝试以仅对该队列运行的模式运行 Dataflow 模板,从而清空该队列。为此,请将 runMode 参数设置为 retryDLQ,如以下示例所示:

DLQ_START_TIME="$(date +'%Y%m%d%H%M%S')"

gcloud dataflow flex-template run "dataflow-mongodb-to-firestore-$DLQ_START_TIME" \
--template-file-gcs-location gs://dataflow-templates-us-central1/latest/flex/Cloud_Datastream_MongoDB_to_Firestore \
--region $LOCATION \
--num-workers $NUM_WORKERS \
--temp-location $TEMP_OUTPUT_LOCATION \
--additional-user-labels "" \
--parameters inputFilePattern=$INPUT_FILE_LOCATION,\
inputFileFormat=avro,\
fileReadConcurrency=10,\
connectionUri=$FIRESTORE_CONNECTION_URI,\
databaseName=$FIRESTORE_DATABASE_NAME,\
shadowCollectionPrefix=shadow_,\
batchSize=500,\
deadLetterQueueDirectory=$DLQ_LOCATION,\
dlqRetryMinutes=10,\
dlqMaxRetryCount=500,\
processBackfillFirst=false,\
runMode=retryDLQ,\
directoryWatchDurationInMinutes=10,\
streamName=$DATASTREAM_NAME,\
stagingLocation=$STAGING_LOCATION,\
autoscalingAlgorithm=THROUGHPUT_BASED,\
maxNumWorkers=$MAX_WORKERS,\
workerMachineType=$WORKER_TYPE

排查不可重试的错误

常见的不可重试的错误包括:

  • 不支持的 BSON 类型
  • 用作 _id 的 BSON 类型不受支持
  • 不支持 0L 作为 _id
  • 文档大小超过 Firestore 的 4MB 上限

不可重试的错误将存储在 Cloud Storage 存储桶中,存储位置由 Dataflow 模板的 deadLetterQueueDirectory 参数指定。

检查死信队列 (DLQ)

在所有处理停止后(这意味着没有正在处理的有效流量,也没有正在重试的错误事件),错误事件会持久保存到 Cloud Storage。

您可以检查事务性写入事件,确认没有处理吞吐量,并且没有生成新的日志条目,从而验证处理是否已停止。

您可以直接从 Cloud Storage 检查 DLQ:

  1. 导航到 DLQ_LOCATION 环境变量中指定的 Cloud Storage 位置。
  2. 在根据时间戳构建的嵌套文件夹树中,展开文件夹以查看队列中的最新内容。文件可能已分片,如下例所示:

    DLQ 中的文件

  3. 检查每个文件,以查看未应用于目标数据库的文档和更新。每条消息都将包含原始事件和发生的异常的载荷。

    出现可重试错误的几率非常低,尤其是在使用了较低的 dlqMaxRetryCount 参数值的情况下,但一般来说,最终进入 DLQ 的事件将因之前描述的原因而无法重试。

  4. 您可以选择中止迁移并恢复应用流量到源数据库,解决源数据库中的 Firestore 数据限制,然后重新运行整个迁移过程;也可以针对每个 DLQ 事件解决数据问题,然后重试处理这些事件。

对于每个 DLQ 文件中的每一行,您可以执行以下操作:

  • 通过修改文档载荷,将不受支持的数据类型转换为替代数据类型。文档载荷将采用规范的扩展 JSON 格式。以规范的扩展 JSON 格式表示新数据类型。

  • 将 0L 文档 _id 重新分配给新的 Long 或其他数据类型(例如 String)。如果现有代码预期 _id 全部为 Long,则重新分配为其他数据类型可能需要更改应用逻辑。

  • 如果文档超过 Firestore 的 4MB 限制,可以将其拆分为较小的文档,也可以压缩其内容。不过,这需要更改应用逻辑来处理数据。

  • 通过从 DLQ 文件中删除相应行来忽略该事件。

如需修改 DLQ 文件,您必须先将 .json 文件下载到本地,修改其内容,然后重新上传到同一 Cloud Storage 位置,覆盖原始文件。如果文件中的所有引用文档都可以安全地从迁移中排除,则可以删除整个文件。

对 DLQ 文件进行修改后,您可以通过迁移 Dataflow 模板以 retryDLQ 模式重新运行这些事件。

以下命令会启动新的 Dataflow 流水线,该流水线只会处理 Dead Letter Queue 中的项:

DLQ_START_TIME="$(date +'%Y%m%d%H%M%S')"

gcloud dataflow flex-template run "dataflow-mongodb-to-firestore-$DLQ_START_TIME" \
--template-file-gcs-location gs://dataflow-templates-us-central1/latest/flex/Cloud_Datastream_MongoDB_to_Firestore \
--region $LOCATION \
--num-workers $NUM_WORKERS \
--temp-location $TEMP_OUTPUT_LOCATION \
--additional-user-labels "" \
--parameters inputFilePattern=$INPUT_FILE_LOCATION,\
inputFileFormat=avro,\
fileReadConcurrency=10,\
connectionUri=$FIRESTORE_CONNECTION_URI,\
databaseName=$FIRESTORE_DATABASE_NAME,\
shadowCollectionPrefix=shadow_,\
batchSize=500,\
deadLetterQueueDirectory=$DLQ_LOCATION,\
dlqRetryMinutes=10,\
dlqMaxRetryCount=500,\
processBackfillFirst=false,\
runMode=retryDLQ,\
directoryWatchDurationInMinutes=10,\
streamName=$DATASTREAM_NAME,\
stagingLocation=$STAGING_LOCATION,\
autoscalingAlgorithm=THROUGHPUT_BASED,\
maxNumWorkers=$MAX_WORKERS,\
workerMachineType=$WORKER_TYPE

后续步骤