因果集群常见问题解答(针对高负载)
从节点实例滞后及其原因是什么?
从节点滞后的主要原因是高度并发和持续的读/写工作负载。这可能导致实例不堪重负,从而在将数据传播到从节点时产生一些额外延迟(主要是由于缺少可用线程来执行此操作)。
我对延迟有什么一般预期?
我们没有具体的数字,也没有工具来预测预期延迟(时间),因为这取决于多种因素的组合,例如事务大小、并发性、工作负载量、硬件、网络延迟等。几乎不可能将所有这些因素关联起来,从而得出关于延迟的普遍预期。
我们使用事务ID来确定从节点与主节点之间的距离(以事务数量计)。您可以查阅这篇知识库文章:如何监控从节点是否与主节点同步
因果集群依赖 Raft 协议来确保数据在确认事务提交之前是安全持久的。实际上,这意味着集群中的大多数核心服务器将已经(接受)该事务,因此由于 Raft 协议的性质,它在同步方面更接近主节点(您可以查看此链接:http://thesecretlivesofdata.com/raft/,它以交互方式解释了 Raft 协议)。 |
衡量滞后的一种方法是设置一个简单的测试用例:在重负载下,使用两个客户端并利用书签。该测试用例将让客户端 1 向数据库写入数据并使用书签,记录提交时间;然后让客户端 2 尝试使用相同的书签读取数据,并记录数据可用所需的时间。通过不同工作负载进行测量,您将了解预期的结果以及该值如何随负载变化。
您可以在以下链接中阅读有关特定驱动程序因果链和书签的更多信息:JAVA 文档 JavaScript 文档 Go 文档 .NET 文档 Python 文档 |
我是否应该考虑将主节点用于只读事务?
这个问题出现的原因是,为了将请求直接路由到主节点并更快地获取最新数据,有人会将显式写入事务用于读取操作。
虽然这看起来是解决延迟问题的一种方法,但我们的最佳实践在这方面非常明确:写入操作使用写入事务;读取操作使用读取事务。将写入事务用于读取操作意味着主节点被用于处理您的大部分(甚至所有!)请求。这将给主节点带来更大的压力,从而增加主节点不堪重负的可能性,最终导致从节点上出现更严重的滞后。
如果您的主节点始终处于持续重负载之下,仅这一点就可能增加延迟。推荐的方法是在集群中分发负载。主节点的工作量越少,它向集群中其他实例传播数据的速度就越快。这意味着从节点将更快地获得数据,从而使得将从节点用于读取操作、主节点仅用于写入操作成为可行——这符合最佳实践。
如何最大限度地减少滞后对从节点的影响?
为了最大限度地减少滞后,您应该着重做以下两件事:
-
降低并发事务的数量,因为这正是导致从节点滞后的原因。
-
减小事务大小。显然,更大的事务需要更长的提交时间,不仅在主节点上,在从节点实例上也是如此,这可能也会导致滞后。
我们一直在努力改进 Neo4j 的各个方面,这一点也不例外。最新版本提供了在重负载情况下改善体验的功能,例如:
-
缓存预热:使实例能够在启动时预热其缓存,防止新实例由于缓存未像主节点一样就绪而在加入集群后立即落后(从而增加查询持续时间和滞后可能性)。
-
Raft 共识改进:这显著提高了集群中大型事务的写入性能。我们现在可以以与处理小型事务相同的速度处理更大的事务。
-
事务状态消耗更少内存(将事务移至堆外,与原生索引协同工作):减轻 JVM 压力,使整个系统更稳定,减少垃圾回收暂停和滞后。
-
Bolt 线程池:限制并回压主节点上的活跃线程数量。这将对这种行为产生更显著的影响,因为这是我们现在限制主节点负载的方式。通过此功能,我们可以调整配置设置,以实现最大可能的吞吐量,而不会使主节点处于无法在整个集群中传播数据的情况。您可以在此处阅读更多关于 Bolt 线程池功能及其配置方法的信息。
我应该使用因果链/书签吗?(及其对传播时间的影响)
为了更好地理解此主题,我们建议您首先查阅我们的文档,特别是Neo4j 因果集群简介。
简单来说,我们可以说,当被调用时,因果一致性确保客户端至少能读取到自己写入的数据。实现这一目标的方法是使用书签,书签在执行事务时发挥作用。客户端可以请求一个书签,然后将其作为参数传递给后续事务。通过使用该书签,集群可以确保只有处理了客户端已标记事务的服务器才会运行其下一个事务。
这不会对数据传播产生影响。您的数据将按照 Raft 协议规则以相同的方式传播(参见上面提到的链接)。话虽如此,根据您的用例要求,您可能需要做出设计选择:
-
如果您绝对需要读取自己写入的数据,使用书签将确保这一点。您的后续请求将由包含与写入时使用的书签对应数据的实例提供服务。您将承担数据访问时间的损失,因为您需要等待信息可用。一个例子是新闻源上的评论:您向数据库写入一条评论,并且您绝对需要该信息立即显示出来。
-
不使用书签意味着后续读取可能无法获取最新数据。您将更快地访问数据,但由于您未提供因果链的手段,您读取的数据可能不是最新的,并且您可能会检索到不想要的结果。一个例子是在线商店的(非实时)推荐系统:系统会根据您过去的购买记录推荐产品,如果您购买了新商品,数据库会更新。然而,新添加的信息只会在未来的购买中用于推荐产品。
您需要决定您的用例是需要这种因果链来确保真正一致的结果,还是需要最快的数据访问,即使它可能不是最新的?或者,某些客户端是否需要比其他客户端更强的一致性?如上所述,这是一个设计选择,必须选择最适合用例的方案。
此页面有帮助吗?