灾难恢复企业版
集群中的故障
集群中的数据库可能在集群内有不同的分配方式,并且可能具有不同数量的主副本(primaries)和从副本(secondaries)。
这导致所有服务器承载的数据库可能各不相同。丢失集群中的一台服务器可能导致某些数据库失去一个成员,而其他数据库则不受影响。因此,在发生一台或多台服务器宕机的灾难时,一些数据库可能几乎不受影响地继续运行,而另一些数据库可能会丢失其所有已分配的资源。
图 2 展示了三台服务器丢失时的灾难情况,演示了这种情况对数据库的不同影响。
| 数据库 | 灾难场景 | 恢复策略 |
|---|---|---|
数据库 A |
所有分配均丢失。 |
由于集群中不再有可用的分配,需要从备份中重新创建该数据库。 |
数据库 B |
主分配丢失,从分配可用。 |
由于该数据库丢失了多数主分配,因此无法进行写操作,需要重新创建。但是,重新创建可以基于健康服务器上仍然存在的从分配进行,因此不需要备份。重新创建后的数据库将与灾难发生时从分配的状态保持一致。 |
数据库 C |
丢失两个主分配和一个从分配。 |
由于该数据库丢失了多数主分配,因此无法进行写操作,需要重新创建。但是,重新创建可以基于健康服务器上仍然存在的主、从分配进行,因此不需要备份。重新创建后的数据库将反映出幸存的最新的主分配或从分配的状态。 |
数据库 D |
丢失一个主分配和两个从分配。 |
该数据库仍然可写,允许在丢失的服务器被取消分配(deallocated)后,自动将分配从丢失的服务器移动到可用服务器。因此,即使丢失了一些分配,也不需要重新创建该数据库。 |
数据库 E |
保持不受影响。 |
该数据库的任何分配都没有受到灾难的影响,因此无需采取行动。 |
尽管数据库 C 和 D 共享相同的拓扑结构,但它们的主副本和从副本分配方式不同,因此在此灾难示例中需要不同的恢复策略。
指南概述
|
本指南使用以下术语
|
从灾难中恢复集群共有四个步骤
-
在所有非丢失的服务器上启动 Neo4j 进程。有关更多信息,请参阅启动 Neo4j 进程。
-
使
system数据库能够处理写操作,以便可以修改集群。有关更多信息,请参阅使 system 数据库可写。 -
将任何潜在的丢失服务器从集群中分离并替换为新服务器。有关更多信息,请参阅使服务器可用。
-
通过启动或继续管理数据库来完成灾难恢复,并验证它们是否可写。有关更多信息,请参阅使数据库可写。
每个步骤都在以下三个部分中进行了描述
-
目标 — 集群需要达到的状态,并附有可选的动机说明。
-
验证状态 — 如何验证该状态的示例。
-
实现正确状态的路径 — 为达到正确状态而建议的一系列步骤。
|
建议在继续下一步之前验证每个状态,无论灾难场景如何,这都是为了确保集群完全正常运行。 |
灾难恢复步骤
|
灾难有时会影响驱动程序的路由能力,并可能阻止使用 |
使 system 数据库可写
目标
system 数据库能够处理写操作。
system 数据库包含了集群的视图。这包括哪些服务器和数据库存在、它们位于何处以及它们是如何配置的。在灾难期间,集群视图可能需要更改以反映新的现实,例如移除丢失的服务器。数据库也可能需要重新创建以恢复写能力。由于这两个步骤都是通过修改 system 数据库来执行的,因此使 system 数据库可写是灾难恢复中至关重要的第一步。
验证状态
可以通过使用状态检查过程来验证 system 数据库的写能力。
CALL dbms.cluster.statusCheck(["system"]);
|
状态检查过程无法验证配置为单主副本的数据库的写能力。相反,请运行 |
实现正确状态的路径
如果 system 数据库已丢失,请使用以下步骤恢复其写能力。这些步骤将从集群中能找到的最新 system 数据库副本创建一个新的 system 数据库。尽可能获取最新的 system 数据库非常重要,这样它才能尽可能接近灾难发生前的视图。
|
本节灾难恢复指南使用了 |
-
关闭所有服务器上的 Neo4j 进程。这将导致集群中所有数据库的停机,直到本节末尾重新启动进程。
-
在每台服务器上,运行
bin/neo4j-admin dbms unbind-system-db以重置服务器上的system数据库状态。 -
在每台服务器上,运行
bin/neo4j-admin database info system并比较lastCommittedTransaction,以找出哪台服务器拥有最新的system数据库副本。 -
在拥有最新副本的服务器上,运行
bin/neo4j-admin database dump system --to-path=[path-to-dump]来导出当前的system数据库并将其存储在可访问的位置。 -
对于每台丢失的服务器,根据向集群添加服务器添加一个新的无约束(unconstrained)服务器。新服务器必须是无约束的,否则在指南的下一步中取消分配服务器时可能会被阻塞,即使已经添加了足够的服务器。
在当前示例中,新添加的无约束服务器是在这一步中加入的。
虽然建议这样做,但并非必须在这一步添加新服务器。也可以选择更改从分配上的
system数据库模式 (server.cluster.system_database_mode),使它们成为新system数据库的主分配。所需的主分配数量由dbms.cluster.minimum_initial_system_primaries_count定义。有关更多信息,请参阅配置设置。请注意,不更换服务器可能会在指南的下一步中将数据库从丢失服务器移动到可用服务器时导致集群过载。 -
在每台服务器上,运行
bin/neo4j-admin database load system --from-path=[path-to-dump] --overwrite-destination=true来加载当前的system数据库导出文件。图 3. 添加无约束服务器并恢复system数据库 -
在每台服务器上,确保发现设置是正确的。有关更多信息,请参阅集群服务器发现。
-
在所有服务器上启动 Neo4j 进程。
使服务器可用
目标
集群视图中的所有服务器均处于可用且已启用状态。
丢失的服务器仍会出现在 system 数据库的集群视图中,但处于不可用状态。此外,根据集群视图,这些丢失的服务器仍然托管着它们在丢失前拥有的数据库。因此,仅告知集群哪些服务器丢失是不够的。在移除这些丢失的服务器之前,还必须将它们托管的数据库移动到集群中的可用服务器上。
验证状态
可以通过列出服务器来查看集群的服务器视图。有关更多信息,请参阅列出服务器。如果所有服务器显示的 health = Available 且 status = Enabled,则表示状态已通过验证。
SHOW SERVERS;
实现正确状态的路径
使用以下步骤移除丢失的服务器并向集群添加新服务器。要移除丢失的服务器,它们托管的任何分配必须被移动到集群中的可用服务器。这分两个步骤完成
-
任何无法自行移动的分配都需要重新创建数据库,从而强制它们移动。
-
任何可以移动的分配将被指令执行移动,方式是取消分配该服务器。
-
对于每台
Unavailable(不可用)服务器,在其中一台可用服务器上运行CALL dbms.cluster.cordonServer("unavailable-server-id")。这可以防止新的数据库分配被移动到此服务器。图 4. 隔离(Cordon)不可用服务器图 4 显示新的无约束服务器已经添加。这是在指南的使 system 数据库可写步骤中完成的,此处可能不需要额外的服务器。
-
如果你尚未添加新的无约束服务器,请为每台需要替换的
Cordoned(已隔离)服务器添加一个。有关更多信息,请参阅向集群添加服务器。新服务器必须是无约束的,否则取消分配服务器的操作可能会被阻塞,即使已经添加了足够的服务器。虽然建议这样做,但并非必须在这一步添加新服务器。然而,不添加新服务器会降低集群处理任务的能力。此外,可能需要更改数据库的拓扑结构,才能使取消分配服务器和重新创建数据库成为可能。
-
对于每个已停止的数据库(
currentStatus=offline),通过运行START DATABASE stopped-db来启动它们。这是必须的,因为已停止的数据库无法从服务器上取消分配。这也是状态检查过程准确指出该数据库是否应被重新创建的必要步骤。在移动到下一步之前,请确保所有分配在非丢失的服务器上都处于currentStatus=online。如果数据库启动失败,请将其留待本指南的下一步中重新创建。数据库在启动前可以设置为
READ-ONLY,以避免对数据库进行更新,使用命令:ALTER DATABASE database-name SET ACCESS READ ONLY。 -
在每台服务器上,运行
CALL dbms.cluster.statusCheck([])来检查在此服务器上以主模式运行的所有数据库的写可用性。有关更多信息,请参阅监控复制。状态检查过程无法验证配置为单主副本的数据库的写能力。相反,请运行
SHOW DATABASES来检查主副本是否分配在可用服务器上,且其currentStatus为online。 -
对于每个不可写的数据库,重新创建它以将其从丢失的服务器上移除并恢复写能力。有关重新创建选项的更多信息,请转至重新创建数据库。记得在重新创建之前确保有这些数据库的最新备份。有关更多信息,请参阅在线备份。如果任何数据库在可用服务器上显示
currentStatus=quarantined(已隔离),请使用备份作为种子从备份中重新创建它们。如果你使用未定义服务器或带有回退备份的未定义服务器重新创建数据库,在某些
system数据库已被恢复的边缘情况下,存储可能无法被恢复到尽可能新的状态。图 5. 所有不可写的数据库均已重新创建 -
对于每台
Cordoned(已隔离)服务器,在其中一台可用服务器上运行DEALLOCATE DATABASES FROM SERVER cordoned-server-id。这将把该服务器上的所有数据库分配移动到集群中的可用服务器。图 6. 从不可用服务器中取消分配数据库注意,数据库 D 仍然是可写的,这意味着当丢失的服务器被取消分配时,分配可以从丢失的服务器移动到可用服务器。
如果未向集群添加足够的无约束服务器来替换丢失的服务器,此操作可能会失败。另一个原因是某些可用服务器也处于
Cordoned(已隔离)状态。 -
对于每台正在取消分配或已取消分配的服务器,运行
DROP SERVER deallocated-server-id。这将从集群视图中移除该服务器。图 7. 完全恢复的集群在删除已取消分配的服务器后,你仍然需要确保所有已移动和重新创建的数据库都是可写的。为此,请按照下文中的步骤操作。
-
使数据库可写
目标
所有希望启动的数据库均处于可写状态。
一旦验证了此状态,灾难恢复即告完成。但是,请记住在此过程中可能已经启动了之前已停止的数据库。如果你仍然希望它们处于停止状态,请运行 STOP DATABASE started-db WAIT。
|
请记住,重新创建数据库需要不确定的时间,因为它可能涉及将存储复制到新服务器,如重新创建数据库中所述。因此, |
验证状态
你可以使用状态检查过程来验证所有集群数据库的写可用性。
CALL dbms.cluster.statusCheck([]);
|
状态检查过程无法验证配置为单主副本的数据库的写能力。相反,请运行 |
可以进行更严格的验证,以验证所有数据库在所有服务器上都处于其预期的状态。对于更严格的检查,请运行 SHOW DATABASES 并验证所有服务器上所有数据库分配的 requestedStatus = currentStatus。
实现正确状态的路径
使用以下步骤使集群中的所有数据库重新可写。这些步骤包括重新创建任何不可写的数据库,并识别任何无法完成的重新创建。重新创建可能因多种原因失败,但其中一个例子是不同服务器上相同事务的校验和不匹配。
-
按照此灾难恢复步骤的验证状态部分所述,通过运行
CALL dbms.cluster.statusCheck([])来识别所有不可写的数据库。过滤掉所有希望保持停止的数据库,以免不必要地重新创建它们。 -
重新创建每个不可写且之前未被重新创建的数据库。有关更多信息,请参阅重新创建数据库。记得在重新创建之前确保有这些数据库的最新备份。有关更多信息,请参阅在线备份。如果任何数据库在可用服务器上显示
currentStatus=quarantined(已隔离),请使用备份作为种子从备份中重新创建它们。如果你使用未定义服务器或带有回退备份的未定义服务器重新创建数据库,在某些
system数据库已被恢复的边缘情况下,存储可能无法被恢复到尽可能新的状态。 -
运行
SHOW DATABASES并检查任何不可写的已重新创建数据库。如果消息字段中显示以下任一消息,则数据库的重新创建将无法完成-
Seeders ServerId1 and ServerId2 have different checksums for transaction TransactionId. (种子服务器 ServerId1 和 ServerId2 对事务 TransactionId 的校验和不同。所有种子服务器对于相同的追加索引必须具有相同的校验和。) -
Seeders ServerId1 and ServerId2 have incompatible storeIds. (种子服务器 ServerId1 和 ServerId2 具有不兼容的 storeIds。所有种子服务器必须具有兼容的 storeIds。) -
No store found on any of the seeders ServerId1, ServerId2… (在任何种子服务器 ServerId1, ServerId2... 上未找到存储)
-
-
对于每个无法完成重新创建的数据库,请使用备份作为种子从备份中重新创建它们。