使用时间点恢复 (PITR)

本页介绍如何使用时间点恢复 (PITR) 来保留和恢复 Datastore 模式 Firestore 中的数据。

如需了解 PITR 概念,请参阅时间点恢复

权限

如需获取管理 PITR 设置所需的权限,请让管理员向您授予您想要启用 PITR 设置的项目的 Cloud Datastore Owner (roles/datastore.owner) IAM 角色。 如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限

此预定义角色包含管理 PITR 设置所需的权限。如需查看所需的确切权限,请展开所需权限部分:

所需权限

您需要具备以下权限才能管理 PITR 设置:

  • 如需在创建数据库时启用 PITR,请执行以下操作: datastore.databases.create
  • 如需更新现有数据库上的 PITR 设置: datastore.databases.update,datastore.databases.list
  • 如需从 PITR 数据进行读取: datastore.databases.get,datastore.entities.get,datastore.entities.list,datastore.namespaces.get,datastore.namespaces.list,datastore.statistics.get,datastore.statistics.list
  • 如需导出 PITR 数据,请执行以下操作: datastore.databases.export
  • 如需导入 PITR 数据: datastore.databases.import

您也可以使用自定义角色或其他预定义角色来获取这些权限。

准备工作

在开始使用 PITR 之前,请注意以下几点:

  • 启用 PITR 后,您无法立即开始读取过去 7 天内的数据。
  • 如果您要在创建数据库时启用 PITR,必须使用 gcloud firestore databases create 命令。使用 Google Cloud 控制台创建数据库时不支持启用 PITR。
  • 启用 PITR 后,Datastore 模式会立即开始保留版本。
  • 停用 PITR 后,您将无法在 PITR 窗口中读取 PITR 数据。
  • 如果您在停用 PITR 后立即将其重启,则过去的 PITR 数据将不再可用。系统将在 PITR 失效日期之后删除停用 PITR 之前创建的任何 PITR 数据。
  • 如果您在过去一小时内不小心删除了数据并停用了 PITR,则可以在删除后的一小时内启用 PITR,从而恢复数据。
  • 对已过期的 PITR 数据执行的任何读取操作都会失败。

启用 PITR

在使用 PITR 之前,请为 Google Cloud 项目启用结算功能。只有启用了结算功能的 Google Cloud 项目才能使用 PITR 功能。

如需为数据库启用 PITR,请执行以下操作:

控制台

  1. 在 Google Cloud 控制台中,转到数据库页面。

    前往“数据库”

  2. 从数据库列表中选择所需的数据库。

  3. 在导航菜单中,点击灾难恢复

  4. 点击修改以修改设置。

  5. 选中启用时间点恢复复选框,然后点击保存

启用 PITR 会产生存储费用。如需了解详情,请参阅价格

如需停用 PITR,请在 Google Cloud 控制台的“灾难恢复”页面中取消选中启用时间点恢复复选框。

gcloud

可以使用 gcloud firestore databases create 命令在创建数据库期间启用 PITR,如下所示:

gcloud firestore databases create\
  --location=LOCATION\
  [--database=DATABASE_ID; default="(default)"]\
  [--type=TYPE; default="firestore-native"]\
  --enable-pitr

替换各值,如下所示:

  • LOCATION - 要在其中创建数据库的位置。
  • DATABASE_ID - 设置为数据库 ID 或(使用默认值)。
  • TYPE - 设为 datastore-mode。

您可以使用 gcloud firestore databases update 命令停用 PITR,如下所示:

gcloud firestore databases update\
  [--database=DATABASE_ID; default="(default)"]\
  --no-enable-pitr

替换各值,如下所示:

  • DATABASE_ID - 设置为数据库 ID 或(使用默认值)。

获取保留期限和最早版本时间

控制台

  1. 在 Google Cloud 控制台中,转到数据库页面。

    前往“数据库”

  2. 从数据库列表中选择所需的数据库。

  3. 在导航菜单中,点击灾难恢复

  4. 设置部分中,注意保留期限最早版本时间

    • 保留期限:Datastore 模式为数据库保留所有数据版本的时长。如果停用了 PITR,该值为 1 小时;如果启用了 PITR,该值为 7 天。
    • 最早版本时间:可在 PITR 窗口中读取早期版本数据的最早时间戳。该值会由 Datastore 模式不断更新,并且会在查询时过时。如果您使用该值恢复数据,请确保计算从发出查询到查询恢复那一刻这段时间。
    • 时间点恢复:如果启用了 PITR,则显示 Enabled。如果停用了 PITR,您会看到 Disabled

gcloud

运行 gcloud firestore databases describe 命令,如下所示:

gcloud firestore databases describe --database=DATABASE_ID

DATABASE_ID 替换为数据库 ID 或 default

输出如下:

    appEngineIntegrationMode: ENABLED
    concurrencyMode: PESSIMISTIC
    createTime: '2021-03-24T17:02:35.234Z'
    deleteProtectionState: DELETE_PROTECTION_DISABLED
    earliestVersionTime: '2023-06-12T16:17:25.222474Z'
    etag: IIDayqOevv8CMNTvyNK4uv8C
    keyPrefix: s
    locationId: nam5
    name: projects/PROJECT_ID/databases/(default)
    pointInTimeRecoveryEnablement: POINT_IN_TIME_RECOVERY_DISABLED
    type: DATASTORE_MODE
    uid: 5230c382-dcd2-468f-8cb3-2a1acfde2b32
    updateTime: '2021-11-17T17:48:22.171180Z'
    versionRetentionPeriod: 3600s

其中

  • earliestVersionTime - 最早存储的 PITR 数据的时间戳。
  • pointInTimeRecoveryEnablement:如果启用了 PITR,则显示 POINT_IN_TIME_RECOVERY_ENABLED。如果停用了 PITR,您会看到 POINT_IN_TIME_RECOVERY_DISABLED,或者 pointInTimeRecoveryEnablement 字段可能不会显示。
  • versionRetentionPeriod - 保留 PITR 数据的时间段(以毫秒为单位)。如果停用 PITR,该值可能是 1 小时;如果启用了 PITR,则可能是 7 天。

读取 PITR 数据

您可以使用客户端库、REST API 方法或 FirestoreIO Apache Beam 连接器读取 PITR 数据。

客户端库

Java

您必须使用 ReadOption 类中的 readTime 方法来读取 PITR 数据。您无法使用 ReadOnly 事务执行读取操作。如需了解详情,请参阅 ReadOption 示例代码。

  Datastore datastore = ...
  Timestamp timestamp = ...

  // lookup
  Key key = ...
  Entity entity = datastore.get(key, ReadOption.readTime(timestamp));

  // runQuery
  Query<Entity> query = ...
  QueryResults<Entity> queryResult = datastore.run(query, ReadOption.readTime(timestamp));

  // runAggregationQuery
  AggregationQuery countAggregationQuery = ...
  Long count = getOnlyElement(datastore.runAggregation(countAggregationQuery, ReadOption.readTime(timestamp))).get("total_count");

如需查看 readTime 示例的完整列表,请参阅 GitHub 代码库

Python

在 Datastore 模式 Python SDK 中使用 readTime 方法使用 PITR 读取,或将 ReadOnly 事务与 readTime 搭配使用以执行读取。

  from datetime import datetime, timezone

  read_time = datetime.now(tz=timezone.utc)

  key = 
  # read without PITR read time
  entity = client.get(key)

  # read with PITR read time
  entity = client.get(key, read_time=read_time)

  # PITR read using read_only transaction
  with client.transaction(read_only=True, read_time=read_time):
      entity = client.get(key)

  query = client.query
  # run query without PITR read time
  iterator = query.fetch()

  # run query with PITR read time
  iterator = query.fetch(read_time=read_time)

  # PITR read query using read_only transaction
  with client.transaction(read_only=True, read_time=read_time):
      iterator = query.fetch()

如需查看 readTime 示例的完整列表,请参阅 GitHub 代码库。

REST API

Datastore 模式 V1 读取方法(即 lookuprunQueryrunAggregationQuery)支持 PITR 读取。

如需使用 REST 方法执行读取操作,请尝试以下方法之一:

  1. 在读取方法请求中,将 readTime 值作为支持的 PITR 时间戳传递给 readOptions 方法。PITR 时间戳可以是过去一小时内的微秒精度时间戳,也可以是过去一小时之前的完整一分钟时间戳,但不得早于 earliestVersionTime

  2. readTime 参数与 BeginTransaction 方法一起使用,作为 ReadOnly 事务的一部分以用于多次 PITR 读取。

Apache Beam

使用 Datastore 模式 IO Apache Beam 连接器可以通过 Dataflow 大规模读取或写入 Datastore 模式数据库中的实体。

DatastoreV1.Read 对象上指定 withReadTime(Instant readTime) 方法。使用 DatastoreV1.Read 对象进行的所有后续读取都从同一 readTime 读取。

Java

以下代码展示了如何使用 withReadTime 方法进行 PITR 读取。

  com.google.datastore.v1.Query query = ...
    Instant readTime = Instant.ofEpochSecond(1684098540L);

    DatastoreV1.Read read =
            DatastoreIO.v1()
                .read()
                .withProjectId(project)
                .withQuery(query)
                .withNamespace(namespace)
                .withReadTime(readTime);

    PCollection<Entity> entities = pipeline.apply(read);
    ...

如需查看 withReadTime 示例的完整列表,请参阅 GitHub 代码库。

从 PITR 数据导出和导入

您可以使用 gcloud firestore export 命令将数据库从 PITR 数据导出到 Cloud Storage。您可以导出 PITR 数据,其中时间戳为过去七天内的整分钟时间戳,但不早于 earliestVersionTime。如果指定的时间戳已不存在数据,导出操作将失败。

PITR 导出操作支持所有过滤条件,包括导出所有实体和导出特定种类或命名空间。

  1. 导出数据库,将 snapshot-time 参数指定为所需的恢复时间戳。

    gcloud

    运行以下命令,将数据库导出到存储桶。

    gcloud firestore export gs://[BUCKET_NAME_PATH] \
        --snapshot-time=[PITR_TIMESTAMP] \
        --collection-ids=[COLLECTION_IDS] \
        --namespace-ids=[NAMESPACE_IDS]
    

    其中:

    • BUCKET_NAME_PATH - 有效的 Cloud Storage 存储桶(包含可选路径前缀),用于存储导出文件。
    • PITR_TIMESTAMP - 分钟粒度的 PITR 时间戳,例如 2023-05-26T10:20:00.00Z2023-10-19T10:30:00.00-07:00
    • COLLECTION_IDS - 集合 ID 或集合组 ID 的列表,例如 'specific collection group1','specific collection group2'
    • NAMESPACE_IDS - 命名空间 ID 的列表,例如 'customer''orders'

    还支持使用实体过滤条件导出种类和/或命名空间的特定子集

    在导出 PITR 数据之前,请注意以下几点:

    • RFC 3339 格式指定时间戳。例如 2023-05-26T10:20:00.00Z2023-10-19T10:30:00.00-07:00
    • 请确保您指定的时间戳是过去七天内的整分钟时间戳,但不早于 earliestVersionTime。如果指定时间戳下数据不再存在,您将收到错误消息。时间戳必须是整分钟,即使指定的时间在过去一小时内也是如此。
    • 您无需为失败的 PITR 导出付费。
  2. 导入到数据库。

    按照导入所有实体中的步骤导入您导出的数据库。如果数据库中已有任何实体,这类实体将会被覆盖。还支持使用实体过滤条件导入种类和/或命名空间的特定子集