部署高可用模式

此文档主要介绍了高可用模式的原理、准备工作、以及服务器的操作说明

1.原理

TuGraph 通过多机热备份来提供高可用(HA)模式。在高可用模式下,对数据库的写操作会被同步到所有服务器(非witness)上,这样即使有部分服务器宕机也不会影响服务的可用性。

高可用模式启动时,多个 TuGraph 服务器组成一个备份组,即高可用集群。每个备份组由三个或更多 TuGraph 服务器组成,其中某台服务器会作为leader,而其他复制组服务器则作为follower。写入请求由leader 提供服务,该leader将每个请求复制同步到follower,并在请求同步到服务器后才能响应客户端。这样,如果任何服务器发生故障,其他服务器仍将具有到目前为止已写入的所有数据。如果leader 服务器发生故障,其他服务器将自动选择出新的leader

TuGraph的高可用模式提供两种类型的节点:replica节点和witness节点。其中,replica节点是普通节点,有日志有数据,可对外提供服务。 而witness节点是一种只接收心跳和日志但不保存数据的节点。根据部署需求,leader节点和follower节点可以灵活的部署为replica节点或witness节点。 基于此,TuGraph高可用模式的部署方式有两种:一是普通部署模式,二是带witness的简约部署模式。

对于普通部署模式,leader和所有follower均为replica类型的节点。写入请求由leader提供服务,该leader将每个请求复制同步到follower, 并在请求同步到超过半数的服务器后才能响应客户端。这样,如果少于半数的服务器发生故障,其他服务器仍将具有到目前为止已写入的所有数据。如果leader 服务器发生故障,其他服务器将自动选举出新的leader,通过这种方式保证数据的一致性和服务的可用性。

然而,在用户服务器资源不够或者发生网络分区时,不能建立正常的HA集群。此时,由于witness节点没有数据,对资源占用小,可以将witness节点和replica节点部署在一台机器上。 例如,当只有2台机器的情况下,可以在一台机器上部署replica节点,在另一台机器上部署replica节点和witness节点,不仅节省资源,而且不需要把日志应用到状态机上, 也不需要生成和安装快照,因此响应请求的速度很快,可以在集群崩溃或网络分区时协助快速选举出新的leader,这就是TuGraph HA集群的简约部署模式。 尽管witness节点有诸多好处,但是由于没有数据,集群实际上增加了一个不能成为leader的节点,因此可用性会略有降低。为提高集群的可用性, 可通过指定ha_enable_witness_to_leader参数为true,允许witness节点临时当主。witness节点在把新日志同步到其他节点之后, 会将leader角色主动切换到有最新日志的节点。

v3.6及以上版本支持此功能。

2.准备工作

要启用高可用模式,用户需要:

  • 三台及以上的 TuGraph 服务器实例。

  • 在启动 lgraph_server 时打开高可用模式,可以使用配置文件或者命令行将enable_ha选项设置为true

  • 设置正确的rpc_port,可通过配置文件或者命令行设置。

3.启动初始备份组

安装好TuGraph之后,可以使用lgraph_server命令在不同的机器上启动高可用集群。本节主要讲解高可用集群的启动方式,启动之后的集群状态管理参见lgraph_peer工具

3.1.初始数据一致

当启动时所有服务器中的数据相同或没有数据时,用户可以通过指定--ha_conf host1:port1,host2:port2启动服务器。 这种方式可以将准备好的所有TuGraph实例一次性加入初始备份组,由备份组中的所有服务器根据raft协议选举出leader,并将其他服务器以follower的角色加入备份组。

启动初始备份组的命令示例如下所示:

$ ./lgraph_server -c lgraph.json --rpc_port 9090 --enable_ha true --ha_conf 172.22.224.15:9090,172.22.224.16:9090,172.22.224.17:9090

3.2.初始数据不一致

如果第一台服务器中已有数据(以lgraph_import工具导入或从非高可用模式的服务器传输得到), 并且之前并未在高可用模式下使用,则用户应使用boostrap方式启动。 以ha_bootstrap_role参数为1在bootstrap模式下启动有数据的服务器,并通过ha_conf参数指定本机为leader。 在bootstrap模式下,服务器在将新加入的服务器添加到备份组之前会将自己的 数据复制到新服务器中,以使每个服务器中的数据保持一致。

启动有数据服务器的命令示例如下所示:

$ ./lgraph_server -c lgraph.json --rpc_port 9090 --enable_ha true --ha_conf 172.22.224.15:9090,172.22.224.16:9090,172.22.224.17:9090 --ha_bootstrap_role 1

其他无数据的服务器需要指定ha_bootstrap_role参数为2,并通过ha_conf参数指定leader即可,命令示例如下所示

$ ./lgraph_server -c lgraph.json --rpc_port 9090 --enable_ha true --ha_conf 172.22.224.15:9090,172.22.224.16:9090,172.22.224.17:9090 --ha_bootstrap_role 2

使用bootstrap启动HA集群时需要注意两点:

  1. 需要等待leader节点生成snapshot并且成功启动之后再加入follower节点,否则follower节点可能加入失败。在启动follower节点时可以将ha_node_join_group_s参数配置的稍大,以在加入HA集群时多次等待和超时重试。

  2. HA集群只有在第一次启动时可以使用bootstrap模式,后续再启动时只能使用普通模式(见3.1节)启动,尤其不能让同一个集群的多个节点以bootstrap模式启动,否则可能产生数据不一致的情况

4.启动witness节点

4.1.不允许witness节点成为leader

witness节点的启动方式和普通节点的启动方式一致,只需要设置ha_is_witness参数为true即可。需注意,witness节点的数量应少于集群节点总数量的一半。

启动witness节点服务器的命令示例如下所示:

$ ./lgraph_server -c lgraph.json --rpc_port 9090 --enable_ha true --ha_conf 172.22.224.15:9090,172.22.224.16:9090,172.22.224.17:9090 --ha_is_witness 1

注:默认不允许witness节点成为leader节点,这可以提高集群的性能,但是在leader节点崩溃时会降低集群的可用性。

4.2.允许witness节点成为leader

可以通过指定ha_enable_witness_to_leader参数为true,使得witness节点可以临时成为leader节点,在将新日志同步完成之后再主动切主

启动允许成为leader节点的witness节点服务器的命令示例如下所示:

$ ./lgraph_server -c lgraph.json --rpc_port 9090 --enable_ha true --ha_conf 172.22.224.15:9090,172.22.224.16:9090,172.22.224.17:9090 --ha_is_witness 1 --ha_enable_witness_to_leader 1

注:尽管允许witness节点成为leader节点可以提高集群的可用性,但是在极端情况下可能会影响数据的一致性。因此一般应保证witness节点数量+1少于集群节点总数量的一半。

5.横向扩展其他服务器

启动初始备份组后,如果想对备份组进行横向扩展,要将新服务器添加到备份组, 应使用--ha_conf HOST:PORT选项,其中HOST可以是该备份组中已有的任何服务器的 IP 地址, 而PORT是其 RPC 端口。例如:

./lgraph_server -c lgraph.json --rpc_port 9090 --enable_ha true --ha_conf 172.22.224.15:9090

此命令将启动一台高可用模式的 TuGraph 服务器,并尝试将其添加到包含服务器172.22.224.15:9090的备份组中。 请注意,加入备份组需要服务器将其数据与备份组的leader服务器同步,此过程可能需要相当长的时间,具体取决于数据的大小。

6.停止服务器

当服务器通过CTRL-C下线时,它将通知当前的leader服务器,告知其从备份组中删除该下线的服务器。如果leader服务器下线, 它将在下线前将leader身份权限传给另一台服务器。

如果服务器被终止或者与备份组中的其他服务器失去连接,则该服务器将被视为失败节点,leader服务器将在特定时限后将其从备份组中删除。

如果任何服务器离开备份组并希望重新加入,则必须从--ha_conf HOST:PORT选项开始,其中HOST是当前备份组中的某台服务器的 IP 地址。

7.重启服务器

不建议重新启动整个备份组,因为它会中断服务。如果需要,可以关闭所有服务器。但在重新启动时, 必须保证关闭时的备份组中至少有N/2+1的服务器能正常启动,否则启动失败。 并且, 无论初始启动复制组时是否指定enable_bootstrap为true,重启服务器时都只需通过 指定--ha_conf host1:port1,host2:port2参数一次性重启所有服务器即可,命令示例如下所示:

$ ./lgraph_server -c lgraph.json --rpc_port 9090 --enable_ha true --ha_conf 172.22.224.15:9090,172.22.224.16:9090,172.22.224.17:9090

8.docker部署高可用集群

在真实业务场景中,很可能遇到在多种操作系统或架构上部署高可用集群的需求。 差异化的环境可能导致编译TuGraph时缺少某些依赖。因此, 在docker中编译软件并部署高可用集群是非常有应用价值的。以centos7版本的docker为例, 部署高可用集群的步骤如下所示。

8.1.安装镜像

使用如下命令下载TuGraph的编译docker镜像环境

docker pull tugraph/tugraph-compile-centos7

然后拉取TuGraph源码并编译安装

8.2.创建容器

使用如下命令创建容器,使用--net=host使得容器运行在host模式,此模式下 docker和宿主机和共享网络namespace,即共用同一个IP。

docker run --net=host -itd -p -v {src_dir}:{dst_dir} --name tugraph_ha tugraph/tugraph-compile-centos7 /bin/bash

8.3.启动服务

在每台服务器上使用如下命令启动服务,因为docker和宿主机共享IP,所以可以直接指定在宿主机IP上启动服务

$ lgraph_server -c lgraph.json --host 172.22.224.15 --rpc_port 9090 --enable_ha true --ha_conf 172.22.224.15:9090,172.22.224.16:9090,172.22.224.17:9090

9.查看服务器状态

备份组的当前状态可以在 TuGraph 可视化工具、REST API 以及 Cypher 查询中获取。

在 TuGraph 可视化工具中,可以在 DBInfo 部分中找到备份组中的服务器及其角色列表。

使用 REST API 时,可以使用GET /info/peers 请求获取信息。

在 Cypher 中,使用CALL dbms.listServers()语句来查询当前备份组的状态信息。

10.高可用模式下数据同步问题

在高可用模式下,同一备份组中的不同服务器可能并不总是处于相同的状态。出于性能原因,如果请求已同步到超过一半的服务器,则leader服务器将认为该请求属于committed状态。尽管其余服务器最终将收到新请求,但服务器的状态不一致将持续一段时间。客户端也可能向刚刚重新启动的服务器发送请求,从而具有较旧的状态。

为了确保客户端看到一致连续的数据,特别是为了摆脱反向时间旅行问题(其中客户端读取比以前看到的状态更旧的状态),每个 TuGraph 服务器都会保持一个单调增加的数据版本号。备份组中数据版本号到数据库状态的映射全局一致,这意味着如果两台服务器具有相同的数据版本号,则它们必须具有相同的数据。响应请求时,服务器在响应中包含了其数据版本号。因此,客户端可以知道它看到了哪个版本。客户端收到旧版本的数据之后可以重新向Leader发送请求,从而获取到最新的数据。