cassandra - 原子批处理在Cassandra中如何工作?

标签 cassandra cassandra-2.0

原子批处理如何保证单个批处理中的所有语句都将执行或不执行?

最佳答案

为了了解批处理在后台的工作方式,有助于查看批处理执行的各个阶段。

客户端

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

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

  • UnavailableException- Activity 的节点不足,无法使用指定的批处理CL来完成任何更新
  • WriteTimeoutException-写入批处理日志或应用批处理中的任何更新时超时。可以通过读取异常的writeType值(BATCH_LOGBATCH)进行检查。

  • 在批处理日志阶段失败的写入将由Java驱动程序中的DefaultRetryPolicy自动添加为retried once。批处理日志的创建对于确保协调员在操作中失败时始终能够完成批处理至关重要。继续阅读以了解原因。

    协调器

    客户端发送的所有批处理将由协调器执行,就像执行任何写操作一样。与正常的写操作不同的是,Cassandra还将利用专用日志,该日志将包含当前正在执行的所有挂起的批处理(称为batchlog)。该日志将存储在本地系统键空间中,并由每个节点单独管理。每个批处理的执行都从在协调器以外的两个节点上创建具有完整批处理的日志条目开始。协调器能够在其他节点上创建批处理日志后,它将开始执行批处理中的实际语句。

    批处理中的每个语句将使用整个批处理的CL和时间戳记写入副本。除此之外,此时没有什么特别的写操作发生。还可以提示写操作或抛出WriteTimeoutException,可以由客户端处理(请参见上文)。

    执行批处理后,可以安全地删除所有创建的批处理日志。因此,协调器将在成功执行后向以前已接收到该批处理日志的节点发送一个批处理日志删除消息。这是在后台发生的,一旦失败就不会引起注意。

    让我们总结一下批处理执行期间协调器的工作:
  • 将batchlog发送到其他两个节点(最好在不同的机架中)
  • 以批处理方式执行所有语句
  • 在成功执行批处理之后再次从节点删除批处理日志

  • 批处理日志副本节点

    如上所述,批处理日志将在批处理执行之前在其他两个节点之间复制(如果集群大小允许的话)。这个想法是,如果协调器在完成该批处理中的所有语句之前发生故障,则这些节点中的任何一个都将能够提取未决的批处理。

    让人觉得有点复杂的是,这些节点不会注意到协调器不再存在。批处理日志节点将使用批处理执行的当前状态更新的唯一时间是协调器发出删除消息以指示批处理已成功执行时。万一此类消息未到达,由于某些原因,batchlog节点将假定未执行该批处理,然后从日志中重播该批处理。

    Batchlog重放可能每分钟发生一次,即。这是节点将检查本地批处理日志中是否有尚未被-可能杀死的协调员删除的未决批处理的时间间隔。为了使协调员在批处理日志创建和实际执行之间有一段时间,使用了固定的宽限期(write_request_timeout_in_ms * 2,默认为4秒)。如果4秒钟后批处理日志仍然存在,则将重播该批处理日志。

    就像在Cassandra中进行任何写操作一样,可能会发生超时。在这种情况下,节点将回退为超时操作编写提示。副本超时后,写操作可以从提示中恢复。无论是否启用hinted_handoff_enabled,似乎都不会影响此行为。还有一个与该提示相关联的TTL值,该值将导致该提示在更长的时间(所有涉及的CF的最小GCGraceSeconds)之后被丢弃。

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

    原子性保证

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

    "(Note that we mean “atomic” in the database sense that if any part of the batch succeeds, all of it will. No other guarantees are implied; in particular, there is no isolation; other clients will be able to read the first updated rows from the batch, while others are in progress."



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

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

    关于cassandra - 原子批处理在Cassandra中如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28348717/

    相关文章:

    java - Cassandra 的读取性能在复制过程中几乎保持不变

    ubuntu - E : Package 'cassandra' has no installation candidate

    cassandra-2.0 - 为什么 Cassandra UPDATE 不违反写前不读规则

    cassandra - 如何在没有 now() 函数的情况下将自定义 timeuuid 插入 cassandra?

    Cassandra 版本从 2.0.9 升级到 2.2

    cassandra - 配置多个目录后,cassandra如何拆分键空间数据?

    cassandra - 如何使用更新查询更新 cassandra 中的聚类键?

    amazon-s3 - 使用 Spark 将 Cassandra 数据持久化到 S3 的最简单方法

    Hive 查询执行错误,从 MapredLocalTask​​ 返回代码 3

    java - Cassandra中的Hadoop身份验证不起作用