领导权、路由和负载均衡企业版
选举与领导权
集群中的服务器使用 Raft 协议来确保一致性和安全性。Raft 的一个实现细节是使用“领导者”(Leader)角色对底层日志进行排序,其他实例则作为“跟随者”(Follower)来复制领导者的状态。具体到 Neo4j,这意味着对数据库的写入操作由当前担任相应数据库“领导者”角色的服务器进行排序。
只有以主模式(primary mode)承载数据库的服务器才有资格被选为该数据库的领导者,前提是集群中包含多于一台主服务器。如果一个 Neo4j DBMS 集群包含多个数据库,则每个数据库都在逻辑上独立的 Raft 组内运行,因此每个数据库都有各自的领导者。这意味着同一台服务器可能同时担任某些数据库的“领导者”,以及其他数据库的“跟随者”。
如果跟随者在一段时间内未收到领导者的消息,它可以发起选举并尝试成为新的领导者。该跟随者将自己转变为“候选者”(Candidate),并请求其他服务器投票支持。如果它能获得多数票,则承担领导者角色。服务器不会投票给数据比自己旧的候选者。每个数据库在任何时间只能有一个领导者,且该领导者保证拥有最新的日志。
集群在正常运行期间可能会发生选举,这本身不是问题。如果您遇到频繁的重新选举并干扰了集群的运行,则应设法找出原因。常见原因包括环境问题(例如网络不稳定)和工作负载过重(例如并发查询和事务超过了硬件承载能力)。
领导权平衡
写入事务总是被路由到相应数据库的领导者。因此,分布不均的领导权可能导致写入查询不成比例地集中在部分服务器上。默认情况下,Neo4j 会通过自动转移数据库领导权来避免这种情况,以确保它们在整个集群中均匀分布。此外,Neo4j 会自动将数据库领导权从配置为只读的实例中移出,这些配置通过 server.databases.read_only 或类似设置实现。
客户端路由
客户端路由是指数据库客户端掌握向集群中哪个成员发送特定请求的控制权。通常,这是为了确保写入操作被发送到能为目标数据库执行写入的服务器,而读取操作被发送到其他服务器。
客户端路由基于从集群成员获取路由表,然后利用该信息做出路由决策。路由表包含有关特定数据库的写入者(writers)、读取者(readers)和路由者(routers)的信息。通常有一个“写入者”,如果数据库是只读或处于不健康状态,则可能没有。在默认配置下,所有承载数据库的其他服务器都被视为“读取者”,即写入者不在读取者列表中。这是为了让写入者专注于写入负载,而无需处理两种交互。通常,所有承载数据库的服务器都被列为“路由者”,即可以联系这些服务器以获取该数据库的新路由表。
Neo4j 驱动程序在首次尝试连接数据库时检索路由表,并在配置的生存时间(TTL)之后,或者在路由表似乎过期时重新获取。例如,如果路由表列出 server-3 为数据库的写入者,但写入请求因“无法写入”(not able to write)错误而被拒绝,驱动程序可能会决定获取一个新的路由表,因为写入者可能已经变成了另一台服务器。
关于获取路由表的底层详细信息,请参阅 Bolt 协议 > Neo4j 驱动程序 API > 客户端路由。
路由策略
您可以使用 路由策略 来控制服务器提供的路由表。策略根据您定义的规则筛选每个类别的可用服务器集合。例如,这可以用于根据您的策略优先路由到本地数据中心或特定的高性能机器。
服务器端路由
服务器端路由是客户端路由的补充。
在 Neo4j 集群部署中,Cypher 查询可能会被发送到无法执行该查询的集群成员。启用服务器端路由后,此类查询会在内部重新路由到预期能够执行该查询的集群成员。当写事务查询所针对的数据库中,接收该查询的集群成员不是领导者时,就会出现这种情况。
服务器端路由由 DBMS 启用,通过为每个集群成员设置 dbms.routing.enabled=true 来实现。监听地址(server.routing.listen_address)和广播地址(server.routing.advertised_address)也需要为服务器端路由通信进行配置。
客户端连接需要声明应使用服务器端路由,此功能适用于 Neo4j 驱动程序和 HTTP API。
|
Neo4j 驱动程序仅在使用 在集群端,您必须满足以下先决条件才能使用服务器端路由:
最后一个先决条件通过向客户端发送仅包含一个条目的路由表来强制客户端执行服务器端路由。因此, 每个成员的 HTTP API 会自动受益于这些设置。 |