知识库

针对繁重工作负载的因果集群常见问题解答

从节点(follower)延迟及其原因是什么?

从节点滞后的主要原因是高并发且持续的读/写工作负载。这会导致实例负载过重,从而在向从节点传播数据时产生额外的延迟(主要是由于缺乏可用的线程来执行此操作)。

我该如何对延迟建立一个通用的预期?

我们既没有具体数值,也没有工具来判断预期的延迟(时间维度),因为这取决于多种因素的组合,例如事务大小、并发度、工作负载量、硬件、网络延迟等。几乎不可能将所有这些因素关联起来并得出关于延迟的普遍预期。

我们使用事务 ID 来确定从节点落后于主节点(leader)的程度(以事务编号计)。您可以查看这篇知识库文章:如何监控从节点是否与主节点同步 - 因果集群

因果集群依赖 Raft 协议来确保数据在确认事务提交前是安全持久的。在实践中,这意味着集群中大多数核心服务器(Core Servers)已经(接受了)该事务,因此由于 Raft 协议的本质,从同步角度看,它们非常接近主节点(您可以查看此链接:http://thesecretlivesofdata.com/raft/,它以交互方式解释了 Raft 协议)。

衡量滞后的一种方法是使用书签(bookmarks)在重负载下设置一个简单的测试用例,包含两个客户端。测试用例流程如下:客户端 1 向数据库写入数据并使用书签,记录提交时间;然后让客户端 2 使用相同的书签尝试读取数据,并记录数据可用的时间。在不同的工作负载下进行此测量,将让您了解预期的表现以及该值如何随负载变化。

您可以从以下链接阅读更多关于特定驱动程序的因果链(causal chaining)和书签的信息:JAVA 文档 JavaScript 文档 Go 文档 .NET 文档 Python 文档

我是否应该考虑将主节点用于只读事务?

这个问题之所以出现,是因为有人为了直接路由到主节点从而更快地获取最新数据,而对读取操作使用了显式的写事务。

虽然这看起来像是解决延迟问题的一种方法,但我们在这一方面的最佳实践非常明确:写事务用于写,读事务用于读。将写事务用于读取意味着主节点被用来处理大部分(甚至全部!)请求。这会导致主节点承受更大的压力,从而增加主节点过载的可能性,并最终导致从节点出现更大的延迟。

如果主节点一直处于沉重的负载下,仅这一点就可能增加延迟。推荐的方法是在集群中分配负载。主节点需要做的工作越少,它向集群中其余实例传播数据的速度就越快。这意味着从节点能更及时地获得数据,从而使得按照最佳实践“将从节点用于读取,仅将主节点用于写入”变得可行。

如何尽量减少从节点滞后的影响?

为了尽量减少滞后,您应该着重做好两件事:

  • 降低并发事务的数量,因为这实际上是导致从节点落后的主要原因。

  • 减小事务大小。显而易见,较大的事务不仅在主节点上,而且在从节点实例上提交所需的时间也更长,这同样可能导致滞后。

我们一直在致力于改进 Neo4j 的各个方面,这一点也不例外。近期的发布包含了多项功能,可以改善重负载情况下的体验,例如:

  • 缓存预热(Cache pre-warming):使实例在启动时能够预热缓存,防止新实例在加入集群后立即因为缓存不如主节点准备充分而落后(从而增加查询时长并增大滞后可能性)。

  • Raft 共识机制的改进:这显著提升了整个集群在大事务下的写入性能。我们现在可以以与小事务相同的速度处理大得多的事务。

  • 事务状态消耗更少的内存(将事务移出堆外,并与原生索引协同工作):减轻 JVM 的压力,使整个系统更稳定,且不易出现 GC 暂停和滞后。

  • Bolt 线程池:用于限制和抑制主节点上的活动线程数量。这将对上述行为产生最显著的影响,因为这是我们现在用来对主节点负载进行限流的方法。通过此功能,我们可以调整配置设置以达到最大可能的吞吐量,而不会使主节点陷入甚至无法向集群传播数据的境地。您可以阅读更多关于 Bolt 线程池功能及其配置的信息 在这里

我应该使用因果链/书签吗?(及其对传播时间的影响)

为了更好地理解这个主题,我们建议先浏览我们的文档,即 Neo4j 因果集群简介

简单解释一下:当被调用时,因果一致性确保客户端能够读取到至少是其自身写入的数据。实现这一点的手段是使用书签,并在执行事务时发挥作用。客户端可以请求一个书签,然后将其作为参数提供给后续事务。利用该书签,集群可以确保只有处理了该客户端书签事务的服务器才会运行其下一个事务。

这不会对数据传播产生影响。根据 Raft 协议规则(见上述链接),您的数据仍将以相同的方式进行传播。话虽如此,根据您的用例需求,您可能需要做出设计选择:

  • 如果您绝对需要读取自己的写入内容,使用书签可以确保这一点。您的后续请求将由拥有与写入时所用书签对应数据的实例提供服务。您会牺牲一部分数据访问时间,因为您需要等待信息变得可用。例如新闻提要上的评论:您向数据库写入一条评论,并且您绝对需要该信息在之后立即显示出来。

  • 不使用书签意味着后续读取可能包含也可能不包含最新数据。您的数据访问速度会更快,但由于您没有提供因果链的手段,读取到的数据可能不是最新的,您可能会检索到不需要的结果。例如在线商店的(非实时)推荐系统:您将根据过去的购买记录获得产品推荐,如果您购买了新东西,您会更新数据库。然而,这些新添加的信息仅会用于未来购买的商品推荐。

您需要决定:您的用例是否需要这种因果链来确保完全一致的结果,还是需要最快的数据访问速度,即使它可能不是最新的?或者也许某些客户端比其他客户端需要更强的一致性?如上所述,这是一种设计选择,必须选择最适合用例的方案。

© . This site is unofficial and not affiliated with Neo4j, Inc.