乐趣区

关于数据库设计:集群通信从心跳说起

本文首发 Nebula Graph 官网:https://nebula-graph.com.cn/posts/cluster-communication-heartbeat/

在用户应用 Nebula Graph 的过程中,常常会遇到各种问题,通常咱们都会倡议先通过 show hosts 查看集群状态。能够说,整个 Nebula Graph 的集群状态都是靠心跳机制来构建的。本文将从心跳说起,帮忙你理解 Nebula Graph 集群各个节点之间通信的机制。

什么是心跳?有什么作用?

Nebula Graph 集群个别蕴含三种节点,graphd 作为查问节点,storaged 作为存储节点,metad 作为元信息节点。本文说的心跳,次要是指 graphd 和 storaged 定期向 metad 上报信息的这个心跳,借助心跳,整个集群实现了以下性能。(相干参数是 heartbeat_interval_secs

在 Nebula Graph 中常常提及的 raft 心跳则是用于领有同一个 partition 的多个 storaged 之间的心跳,和本文提的心跳并不相同。

1. 服务发现

当咱们启动一个 Nebula Graph 集群时,须要在对应的配置文件中填写 meta_server_addrs。graphd 和 storaged 在启动之后,就会通过这个 meta_server_addrs 地址,向对应的 metad 发送心跳。通常来说,graphd 和 storaged 在连贯上 metad 前是无奈对外进行服务的。当 metad 收到心跳后,会保留相干信息(见下文第 2 点),此时就可能通过 show hosts 看到对应的 storaged 节点,在 2.x 版本中,也可能通过 show hosts graph 看到 graphd 节点。

2. 上报节点信息

在 metad 收到心跳时,会将心跳中的 ip、port、节点类型、心跳工夫等等信息保留,以供后续应用(见下文)。

除此以外 storaged 在本身 leader 数量变动的时候也会上报 leader 信息,在 show hosts 中看到的 Leader count 和 Leader distribution 就是通过心跳汇报的。

3. 更新元信息

当客户通过 console 或者各种客户端,对集群的元信息进行更改之后(例如 create/drop spacecreate/alter/drop tag/edgeupdate configs 等等),通常在几秒之内,整个集群就都会更新元数据。

每次 graphd 和 storaged 在心跳的响应中会蕴含一个 last_update_time,这个工夫是由 metad 返回给各个节点的,用于告知 metad 本身最初一次更新元信息的工夫。当 graphd 或者 storaged 发现 metad 的元信息有更新,就会向 metad 获取相应信息(例如 space 信息、schema 信息、配置更改等等)。

咱们以创立一个 tag 为例,如果在 graphd/storaged 获取到新创建的这个 tag 信息之前,咱们无奈插入这个 tag 数据(会报相似 No schema found 这样的谬误)。而当通过心跳获取到对应信息并保留至本地缓存后,就可能失常写入数据了。

心跳上报的信息有什么用?

  • how hostsshow parts 这类命令都是通过 metad 中保留的各个节点心跳信息,组合显示进去的。
  • balance databalance leader 等运维命令,须要通过获取以后集群内哪些 storaged 节点是在线状态,理论也是通过 metad 判断最近一次心跳工夫是否在阈值之内。
  • create space,当用户创立一个 space 时,metad 也须要获取 storaged 的状态,将这个 space 的各个 partition 调配到在线的 storaged 中。

以用户容易遇到的问题为例:如果咱们启动一个 storaged 后,关掉并批改端口号,而后再启动 storaged。如果这个过程足够快,那么通过 show hosts 能看到两个在线的 storaged。此时,如果新建一个 space,例如 CREATE space test(partition_num=10, replica_factor=1),这个 test space 就会散布在前后启动的两个 storage 上。但如果等到在 show hosts 中看到其中一个离线后,再执行 CREATE space test(partition_num=10, replica_factor=1),即使离线的 storaged 再启动,也只有一个 storaged 领有这个 space(创立 test space 时 online 的那个 storaged)。

心跳的演变历史

在 18-19 年的时候,过后的心跳机制没有这么欠缺。一方面,无论元信息是否更改,都会从 metad 获取最新的元信息。而通常来说,元信息改变不会很频繁,定期获取元信息有肯定的资源节约。另一方面,想要将一个 storaged 节点退出和移除都是通过相似 add/delete hosts 这样的命令,采取的是相似白名单的机制。对于其余没有认证过的节点,都无奈对外服务,这样做诚然也有一些劣势,带来的最大问题就是不够敌对。

因而,在 19 年底开始,咱们对心跳做了一系列的改变,特地鸣谢社区用户 @zhanggguoqing。通过一段时间的验证踩坑后,根本就造成了当初的模式。

额定的补充

无关心跳还有一个波及到的问题就是 cluster.id 这个文件。它理论是为了避免 storaged 与谬误的 metad 通信,大抵原理如下:

  • 首先,metad 在启动的时候会依据 meta_server_addrs 这个参数,生成一个 hash 值并保留在本地 kv 中。
  • storaged 在启动的时候会尝试从 cluster.id 这个文件中获取对应 metad 的 hash 值,并附送在心跳中发送(如果文件不存在,则第一次应用 0 代替。收到心跳响应时,将 metad 的 hash 值保留在 cluster.id 这个文件中,后续始终应用该值)。
  • 在心跳解决中,metad 会比拟本地 hash 值和来自 storaged 心跳申请中的 hash 值,如果不匹配则回绝。此时,storaged 是无奈对外服务的,也就是 Reject wrong cluster host 这个日志的由来。

以上就是心跳机制大抵的介绍,感兴趣的你能够参考下源码实现,GitHub 传送门:https://github.com/vesoft-inc/nebula-graph。

举荐浏览

  • 分布式图数据库 Nebula Graph 的 Index 实际
  • 分布式图数据库 Nebula Graph 中的集群快照实际
退出移动版