原子批如何在Cassandra中起作用?

Ste*_*ski 18 cassandra cassandra-2.0

原子批次如何保证单个批次中的所有语句都可以执行或不执行?

Ste*_*ski 38

为了理解批次如何工作,有助于查看批处理执行的各个阶段.

客户端

使用CQL3或现代Cassandra客户端API 支持批处理.在每种情况下,您都可以指定要作为批处理的一部分执行的语句列表,用于所有语句的一致性级别和可选的时间戳.您将能够批量执行INSERT,DELETE和UPDATE语句.如果您选择不提供时间戳,则会自动使用当前时间并与批次关联.

如果批处理无法成功执行,客户端将必须处理两个异常.

  • UnavailableException - 没有足够的节点可以使用指定的批次CL来完成任何更新
  • WriteTimeoutException - 写入批处理日志或应用批处理中的任何更新时超时.可以通过读取writeType异常的值(BATCH_LOG或者BATCH)来检查.

批处理日志阶段中的写入失败将由Java驱动程序自动重试一次DefaultRetryPolicy.批量日志创建对于确保在协调器中途运行失败时始终完成批处理至关重要.继续阅读以找出原因.

协调员

客户端发送的所有批次都将由协调器执行,就像任何写入操作一样.与正常的写操作不同的是,Cassandra还将使用一个专用日志,该日志将包含当前执行的所有待处理批次(称为批量日志).此日志将存储在本地系统密钥空间中,并由每个节点单独管理.每个批处理执行都是通过创建一个日志条目来开始的,其中完整批处理最好是两个节点而不是协调器.在协调器能够在其他节点上创建批处理日志之后,它将开始执行批处理中的实际语句.

批处理中的每个语句都将使用整批的CL和时间戳写入副本.除此之外,在这一点上发生的写作并没有什么特别之处.写入也可以被暗示或抛出WriteTimeoutException,它可以由客户端处理(见上文).

批处理执行后,可以安全地删除所有创建的批处理日志.因此,协调器将在成功执行之前向已接收批量日志的节点发送批量日志删除消息.这种情况发生在后台,如果失败则不会被注意到.

让我们总结协调器在批处理执行期间所做的事情:

  • 将批日志发送到另外两个节点(最好是在不同的机架中)
  • 批量执行所有语句
  • 批量执行成功后,再次从节点中删除批处理日志

批处理日志副本节点

如上所述,批处理日志将在批处理执行之前跨两个其他节点(如果簇大小允许)进行复制.我们的想法是,如果协调器在完成批处理中的所有语句之前关闭,这些节点中的任何一个都将能够获取待处理批次.

让思考有点复杂的是,这些节点不再会注意到协调器不再存在.使用批处理执行的当前状态更新批处理节点的唯一点是协调器发出指示批处理已成功执行的删除消息.如果这样的消息没有到达,批处理节点将假定由于某些原因尚未执行批处理并从日志中重放批处理.

Batchlog重播可能每分钟都在进行,即.这是节点检查本地批处理日志中是否有任何尚未被-possibly killed-coordinator删除的挂起批次的间隔.为了给协调器在批量日志创建和实际执行之间的某个时间,使用固定的宽限期(write_request_timeout_in_ms * 2默认为4秒).如果批处理日志在4秒后仍然存在,它将被重播.

就像Cassandra中的任何写操作一样,可能会发生超时.在这种情况下,节点将回退为超时操作写入提示.当超时复制副本再次启动时,写入可以从提示中恢复.无论是否hinted_handoff_enabled启用,此行为似乎都不会受到影响.还有一个与提示相关联的TTL值,这将导致提示在较长时间后被丢弃(GCGraceSeconds对于任何涉及的CF而言最小).

现在您可能想知道在两个节点上同时重播批处理是否有潜在危险,这可能发生在两个节点上复制批处理日志.这里要记住的重要一点是,由于支持的操作(更新和删除)类型以及与批处理相关的固定时间戳,每个批处理执行都是幂等的.即使两个节点和协调器同时重试执行批处理也不会有任何冲突.

原子性保证

让我们回到"原子批次"的原子性方面,并回顾一下原子()的确切含义:

"(注意,我们在数据库中的意思是"原子"意味着如果批处理的任何部分成功,则所有部分都将成功.没有暗示其他保证;特别是没有隔离;其他客户端将能够读取第一个批量更新了行,而其他行正在进行中."

所以从某种意义上说,我们得到"全有或全无"的保证.在大多数情况下,协调器只会将批处理中的所有语句写入集群.但是,在写入超时的情况下,我们必须通过读取writeType值来检查超时发生的位置.必须已将批处理写入批处理日志,以确保这些保证仍然适用.此时,其他客户端也可以从批处理中读取部分执行的结果.

回到这个问题,Cassandra如何保证批量中的全部或全部报表都不会被执行?原子批次基本上取决于成功的复制和幂等语句.这不是一个100%保证解决方案在理论上存在可能的方案,将仍然会造成不一致.但是对于Cassandra中的很多用例来说,如果你知道它是如何工作的,它是一个非常有用的工具.

  • 很好的答案,但它应该强调它*仅*指*多分区*批次。单分区批次是一个完全不同的故事,我想在这篇文章中指出:https://inoio.de/blog/2016/01/13/cassandra-to-batch-or-not-to-batch / (2认同)