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

时间:2015-02-05 16:10:25

标签: cassandra cassandra-2.0

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

3 个答案:

答案 0 :(得分:36)

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

客户

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

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

  • UnavailableException - 没有足够的节点可以使用指定的批次CL
  • 完成任何更新
  • WriteTimeoutException - 写入批处理日志或应用批处理中的任何更新时超时。可以通过阅读例外的writeType值(BATCH_LOGBATCH)来检查。

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

协调员

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

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

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

让我们总结一下协调员在批量执行过程中所做的事情:

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

批量日志副本节点

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

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

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

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

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

原子性保证

让我们回到原子批次"原子批次"并检查原子(source)究竟是什么意思:

  

"(注意,我们的意思是数据库中的“原子”意义,如果有的话   批次成功,所有这一切都将成功。没有暗示其他保证;   特别是没有孤立;其他客户将能够   从批处理中读取第一个更新的行,而其他行则在   。进展"

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

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

答案 1 :(得分:1)

批处理文档(doc):

  

在Cassandra 1.2及更高版本中,默认情况下批次是原子的。在Cassandra批处理操作的上下文中,atomic表示如果任何批处理成功,则所有批处理都将成功。为了实现原子性,Cassandra首先将序列化批处理写入批处理系统表,该表使用序列化批处理作为blob数据。成功编写并保留(或提示)批处理中的行后,将删除批处理日志数据。原子性会降低性能。如果您不想承担此罚款,请阻止Cassandra使用UNLOGGED选项写入批处理日志系统:BEGIN UNLOGGED BATCH

答案 2 :(得分:1)

Cassandra批次: -

http://docs.datastax.com/en/cql/3.1/cql/cql_reference/batch_r.html

添加以上答案: - 使用Cassandra 2.0,您可以编写批处理语句+ LWT。但限制是所有DML必须位于同一分区