灾难恢复

数据库可能会由于不同系统级别的故障而变得不可用。例如,数据中心故障转移可能会导致多个服务器丢失,从而导致一组数据库变得不可用。数据库也可能由于系统中的严重故障而被隔离,这会导致不可用,即使没有服务器丢失也是如此。

本节包含有关如何恢复不可用数据库的分步指南,这些数据库无法服务写入,但可能仍能服务读取。但是,如果数据库由于其他原因而未按预期执行,本节将无法提供帮助。通过遵循此处概述的步骤,您可以恢复不可用数据库并使其在对集群中的其他数据库造成最少影响的情况下完全投入使用。

如果 Neo4j 集群中的**所有**服务器都在数据中心故障转移中丢失,则无法恢复当前集群。 您必须创建一个新的集群并恢复数据库。 有关更多信息,请参见 部署基本集群播种数据库

集群中的故障

集群中的数据库遵循分配策略。 这意味着它们在集群中以不同的方式分配,并且可能具有不同的主副本和从副本数量。 其结果是,所有服务器在托管的数据库方面都不同。 丢失集群中的服务器可能会导致某些数据库丢失成员,而其他数据库则不受影响。 因此,在多个服务器发生故障的灾难中,一些数据库可能会继续运行,影响很小或没有影响,而其他数据库可能会丢失所有分配的资源。

灾难恢复指南

从灾难中恢复集群主要有三个步骤。 建议完成每个步骤(无论灾难场景如何),以确保集群完全可操作。

  1. 确保 system 数据库在集群中可用。 system 数据库定义了其他数据库的配置; 因此,在执行任何其他操作之前,确保其可用至关重要。

  2. 验证 system 数据库的可用性后,无论是在灾难中恢复还是不受影响,都应恢复丢失的服务器以确保集群拓扑满足要求。

  3. system 数据库可用且集群拓扑满足要求后,您可以管理数据库。

以下部分详细介绍了这些步骤。

在本节中,离线服务器是指未运行但可能可重启的服务器。 但是,丢失服务器是指当前未运行且无法重启的服务器。

灾难有时会影响驱动程序的路由功能,并可能阻止使用 neo4j 模式进行路由。 解决此问题的一种方法是使用 bolt 而不是 neo4j 直接连接到服务器。 有关 bolt 模式的更多信息,请参见 服务器端路由

恢复 system 数据库

恢复的第一步是确保 system 数据库可用。 system 数据库是集群正常运行所必需的。

  1. 启动所有离线服务器。(如果服务器无法启动,请检查日志并联系支持人员。该服务器可能需要被视为永久丢失。)

  2. 验证 system 数据库的可用性。

    1. 运行 SHOW DATABASE system。 如果响应中不包含写入器,则 system 数据库不可用,需要恢复,请继续执行步骤 3。

    2. 或者,您可以创建一个临时用户来验证 system 数据库的可写性,方法是运行 CREATE USER 'temporaryUser' SET PASSWORD 'temporaryPassword'

    3. 通过运行 SHOW USERS 确认临时用户按预期创建,然后继续执行 恢复服务器。 如果没有,请继续执行步骤 3。

  3. 恢复 system 数据库。

    仅当无法通过本节中的前两个步骤验证 system 数据库的可用性时,才执行以下步骤。

    请记住,只要大多数主副本可用,集群就会保持容错性,因此能够提供读写操作。 如果发生影响一个或多个服务器的灾难,但大多数服务器仍然可用,则可以通过将 system 数据库(和任何其他受影响的用户数据库)从一个可用服务器复制到新服务器,将新服务器添加到集群中并恢复其上的 system 数据库(以及任何其他受影响的用户数据库)。 此方法可以防止集群中其他数据库的停机。 如果是这种情况,即如果大多数服务器仍然可用,请按照 恢复服务器 中的说明操作。

    以下步骤从当前 system 数据库的备份创建新的 system 数据库。 这是必需的,因为当前 system 数据库在服务器故障转移中丢失了太多成员。

    1. 关闭所有服务器上的 Neo4j 进程。 请注意,这会导致集群中所有数据库的停机。

    2. 在每个服务器上,运行以下 neo4j-admin 命令 bin/neo4j-admin dbms unbind-system-db 以重置服务器上的 system 数据库状态。 有关更多信息,请参见 neo4j-admin 命令

    3. 在每个服务器上,运行以下 neo4j-admin 命令 bin/neo4j-admin database info system 以找出最新服务器,即具有最高上次提交事务 ID 的服务器。

    4. 在最新的服务器上,通过运行 bin/neo4j-admin database dump system --to-path=[path-to-dump] 对当前 system 数据库进行转储,并将转储存储在可访问的位置。 有关更多信息,请参见 neo4j-admin 命令

    5. 确保有足够的 system 数据库主副本以使用容错性创建新的 system 数据库。 或者

      1. 添加全新的服务器(请参见 将服务器添加到集群),或者

      2. 更改当前 system 数据库的从副本服务器上的 system 数据库模式(server.cluster.system_database_mode),以允许它们成为新 system 数据库的主副本。

    6. 在每个服务器上,运行 bin/neo4j-admin database load system --from-path=[path-to-dump] --overwrite-destination=true 以加载当前 system 数据库转储。

    7. 确保 dbms.cluster.discovery.endpoints 在所有服务器上都设置正确,有关更多信息,请参见 集群服务器发现

    8. 返回步骤 1。

恢复服务器

system 数据库可用后,就可以管理集群。 丢失一个或多个服务器后,必须更新集群对服务器的视图,即用新服务器替换丢失的服务器。 这些步骤将识别丢失的服务器并将其安全地从集群中分离。

  1. 运行 SHOW SERVERS。 如果**所有**服务器都显示健康状态 AVAILABLE 且状态为 ENABLED,请继续执行 恢复数据库

  2. 对于每个 UNAVAILABLE 服务器,在其中一个可用服务器上运行 CALL dbms.cluster.cordonServer("unavailable-server-id")

  3. 对于每个 CORDONED 服务器,在其中一个可用服务器上运行 DEALLOCATE DATABASES FROM SERVER cordoned-server-id

  4. 对于每个未成功取消分配的服务器,并出现以下消息之一

    1. 无法取消分配服务器 'serverId'。 无法重新分配 'DatabaseId.*'。
      需要 'DatabaseId.*' 的拓扑结构为 3 个主副本和 0 个从副本。
      请考虑运行 SHOW SERVERS 以确定解决此问题的合适操作。

      无法取消分配服务器 `serverId。 数据库 [database] 丢失了服务器的仲裁,只找到了 [现有主副本数量] 个主副本(预期为 [预期主副本数量] 个)。 无法安全地重新分配。`

      首先确保有要处理的数据库的备份(请参见 在线备份),然后通过运行 DROP DATABASE database-name 删除该数据库。 返回步骤 3。

    2. 无法取消分配服务器 [server]。 无法更改数据库 [stopped-db] 的分配,因为它已离线。

      尝试通过运行 START DATABASE stopped-db WAIT 启动离线数据库。 如果启动成功,请返回步骤 3。 否则,请确保在使用 DROP DATABASE stopped-db 删除数据库之前对其进行备份。 返回步骤 3。

      可以在启动数据库之前将其设置为 READ-ONLY 模式,以避免对希望停止的数据库进行更新,方法如下:ALTER DATABASE database-name SET ACCESS READ ONLY

    3. 无法取消分配服务器 [server]。 无法重新分配 [database],未找到新的目标。 所有现有服务器: [existing-servers]。 具有 [mode] 模式的实际分配服务器为 [current-hostings]。

      添加新服务器并启用它们,然后返回步骤 3,有关更多信息,请参见 将服务器添加到集群

  5. 一旦所有启用的服务器都托管了请求的数据库(hosting 字段正好包含 requestedHosting 字段中的数据库),请运行 SHOW SERVERS YIELD *,然后继续执行下一步。 请注意,这可能需要几分钟。

  6. 对于每个取消分配的服务器,请运行 DROP SERVER deallocated-server-id

  7. 返回步骤 1。

恢复数据库

system 数据库验证可用且所有服务器联机后,就可以管理数据库。 这些步骤旨在使不可用的数据库可用。

  1. 如果您之前已将数据库作为本指南的一部分删除,请从备份中重新创建每个数据库。 有关如何创建数据库的更多信息,请参见 创建数据库 部分。

  2. 运行 SHOW DATABASES。 如果所有数据库都在所有服务器上的预期状态(requestedStatus=currentStatus),则灾难恢复已完成。