【图数据库内核】高可用边界:primary / secondary、书签因果一致与只读滞后

💡 原文中文,约6600字,阅读约需16分钟。
📝

内容提要

本文介绍Neo4j集群高可用架构:服务器与数据库角色解耦,primary负责写并靠Raft多数确认,secondary异步复制用于读扩展。因果一致性通过书签保证跨成员读己之写。集群不改变单机隔离级别,默认仍为读已提交。

🔎

延伸解读

角色与服务器解耦的运维含义

文章强调primary/secondary是数据库副本的角色,而非服务器永久身份。一台服务器可对不同数据库担任不同角色,这要求运维在调整拓扑时明确区分服务器级配置(如modeConstraint)与数据库级拓扑(如ALTER DATABASE)。理解这一点有助于避免将服务器故障与数据库角色变化混为一谈,从而更精准地定位高可用问题。

写安全与读扩展的权衡

写安全依赖primary的Raft多数确认,而secondary通过异步复制扩展读能力,但可能滞后。这意味着读扩展并不保证立即可见最新提交,需要借助书签实现因果一致性。工程上应区分两类问题:路径中段被改写(靠锁或重试)与secondary滞后(靠因果链或接受最终可见),避免误用集群机制解决单机事务问题。

集群不改变隔离级别

集群提供容错、读扩展和可选因果链,但默认隔离级别仍是读已提交,锁、死锁等事务语义仍发生在处理写的primary/writer上。将HA视为Serializable替代品会误诊lost update等问题。因此,在集群环境下排查事务异常时,应回归单机事务语义,而非归咎于复制机制。

Q&A

Neo4j集群中,primary和secondary是什么?它们与服务器有什么关系?

在Neo4j集群中,primary和secondary是数据库副本的角色,而不是服务器的永久身份。一台服务器可以对不同的数据库担任不同的角色,例如对数据库A是primary,对数据库B是secondary。primary负责处理写操作,secondary用于扩展只读查询。

Neo4j集群如何保证写操作的安全性?

写操作由primary承担,其中自动选出一个writer。写操作需要同步复制到其他primary,并在收到足够成员(多数)确认后才完成提交。容错模型为M=2F+1,即要容忍F个primary故障,需要M个primary。

Neo4j集群中secondary的作用是什么?它有什么限制?

Secondary通过异步日志传输从primary复制数据,用于扩展只读查询。它可能暂时落后于最新提交,不保证立即可见,但提供耐久性缓冲。丢失secondary不影响库可用性和primary容错,只减少吞吐。

Neo4j集群如何实现因果一致性?书签(bookmark)的作用是什么?

因果一致性通过书签实现:客户端在写事务后获得书签,后续读事务携带该书签,集群确保只让已处理过该书签状态的服务器执行,从而保证跨成员读己之写。书签是客户端与集群之间的契约,用于保证因果链。

Neo4j集群是否提供更强的隔离级别?默认隔离级别是什么?

Neo4j集群不改变单机隔离级别,默认仍为读已提交(read-committed)。集群提供容错、读扩展和可选因果链,但并非更强的隔离级别。将HA视为Serializable替代品会误诊lost update等问题。

Neo4j集群中读写路由是如何工作的?

路由机制包括客户端路由和服务端转发。客户端通过routing table将写路由到writer,读可路由到secondary以分担负载。服务端转发用于写落到非Leader成员时,由服务器内部转发到能写的成员。

Neo4j集群中写延迟和读延迟受哪些因素影响?

写延迟受primary多数确认和跨成员网络约束;读延迟仍受page cache、Expand等内核因素影响,secondary不能解决路径爆炸问题。

🏷️

标签

➡️

继续阅读