集群通讯:从心跳提及

本文首发 Nebula Graph 官网:nebula-graph.com.cn/posts/clust…git

在用户使用 Nebula Graph 的过程当中,常常会遇到各类问题,一般咱们都会建议先经过 show hosts 查看集群状态。能够说,整个 Nebula Graph 的集群状态都是靠心跳机制来构建的。本文将从心跳提及,帮助你了解 Nebula Graph 集群各个节点之间通讯的机制。github

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

metad storaged graphd 通讯

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 节点。markdown

2. 上报节点信息

在 metad 收到心跳时,会将心跳中的 ip、port、节点类型、心跳时间等等信息保存,以供后续使用(见下文)。运维

除此之外 storaged 在自身 leader 数量变化的时候也会上报 leader 信息,在 show hosts 中看到的 Leader count 和 Leader distribution 就是经过心跳汇报的。分布式

3. 更新元信息

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

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

咱们以建立一个 tag 为例,若是在 graphd/storaged 获取到新建立的这个 tag 信息以前,咱们没法插入这个 tag 数据(会报相似 No schema found 这样的错误)。而当经过心跳获取到对应信息并保存至本地缓存后,就可以正常写入数据了。spa

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

  • 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 传送门:github.com/vesoft-inc/…

推荐阅读

相关文章
相关标签/搜索