Cassandra 文档

版本

您正在查看预发布版本的文档。

提示

提示是在写入操作期间应用的一种数据修复技术。当副本节点由于故障或更常见的例行维护而无法接受变异时,尝试写入这些副本的协调器会在其本地文件系统上存储临时提示,以便稍后应用于不可用的副本。提示是帮助缩短数据不一致持续时间的重要方法。协调器在不可用的副本节点返回环后会快速重播提示。但是,提示是尽力而为的,不能像 反熵修复 一样保证最终一致性。

提示之所以有用,是因为 Apache Cassandra 如何将数据复制以提供容错性、高可用性和持久性。Cassandra 将数据分区到集群中,使用一致性哈希,然后将键复制到哈希环上的多个节点。为了保证可用性,键的所有副本都可以接受变异而无需达成共识,但这意味着一些副本可能会接受变异,而另一些副本则不会。当这种情况发生时,就会引入不一致性。

除了读取修复和完整/增量反熵修复之外,提示是 Cassandra 实现最终一致性保证的三个方法之一,即所有更新最终都会被所有副本接收。提示与读取修复一样,是尽力而为的,不是执行完整修复的替代方法,但它们确实有助于在实践中缩短副本之间不一致的持续时间。

提示传递

提示传递是 Cassandra 将提示应用于不可用节点的过程。

例如,假设要对具有 复制因子3 的键空间进行 一致性级别LOCAL_QUORUM 的变异。通常,客户端会将变异发送到单个协调器,协调器会将变异发送到所有三个副本,当三个副本中的两个确认变异时,协调器会成功地响应客户端。但是,如果副本节点不可用,协调器会在本地文件系统上存储一个提示,以便稍后应用。新的提示将保留最多 max_hint_windowin_ms 的停机时间(默认为 3 小时)。如果不可用的副本在窗口过期之前返回到集群,协调器会将任何待处理的提示变异应用于副本,以确保最终一致性得到维护。

Hinted Handoff in Action
  • (t0):客户端发送写入,协调器将其发送到三个副本。不幸的是,replica_2 正在重启,无法接收变异。

  • (t1):客户端从协调器接收法定人数确认。此时,客户端认为写入是持久的,并且对读取可见(实际上也是如此)。

  • (t2):在写入超时(默认 2 秒)后,协调器确定 replica_2 不可用,并将其提示存储到本地磁盘。

  • (t3):稍后,当 replica_2 启动时,它会向所有节点(包括协调器)发送八卦消息。

  • (t4):协调器重播提示,包括针对 replica_2 的遗漏变异。

如果节点没有及时返回,目标副本将永久性地不同步,直到读取修复或完整/增量反熵修复传播变异。

提示的应用

提示以批量的形式,一次一段,流式传输到目标副本节点,目标节点在本地重播它们。目标节点重播一段后,它会删除该段并接收下一段。此过程会一直持续,直到所有提示都已处理完毕。

提示在磁盘上的存储

提示存储在协调器节点的 $CASSANDRA_HOME/data/hints 目录中的平面文件中。提示包含提示 ID、要存储变异的目标副本节点、无法传递到副本节点的序列化变异(存储为 blob)、变异时间戳以及用于序列化变异的 Cassandra 版本。默认情况下,提示使用 LZ4Compressor 进行压缩。多个提示会追加到同一个提示文件中。

由于提示包含原始未修改的变异时间戳,因此提示应用是幂等的,不会覆盖未来的变异。

写入请求超时的提示

对于超时的写入请求,也会存储提示。cassandra.yaml 中的 write_request_timeout 设置配置了写入请求的超时时间。

write_request_timeout: 2000ms

协调器会等待配置的时间量以完成写入请求,然后它会超时并为超时的请求生成提示。write_request_timeout 的最低可接受值为 10 毫秒。

配置提示

提示默认情况下是启用的,因为它们对于数据一致性至关重要。cassandra.yaml 配置文件提供了几个用于配置提示的设置。

表 1. 提示设置

设置 描述 默认值

hinted_handoff_enabled

启用/禁用提示传递

true

hinted_handoff_disabled_datacenters

不执行提示传递的数据中心的列表,即使启用了传递。示例

hinted_handoff_disabled_datacenters:
  - DC1
  - DC2

未设置

max_hint_window

定义节点在故障后应生成提示的最长时间。

3h

hinted_handoff_throttle

每个传递线程每秒的最大节流值(以 KiB 为单位)。这将根据集群中的节点数量成比例地减少。(如果集群中有两个节点,每个传递线程将使用最大速率;如果有 3 个节点,每个节点将节流到最大速率的一半,因为预计两个节点会同时传递提示。)

1024KiB

max_hints_delivery_threads

用于传递提示的线程数;如果您有多数据中心部署,请考虑增加此数字,因为跨数据中心的传递往往比较慢

2

hints_directory

Cassandra 存储提示的目录。

$CASSANDRA_HOME/data/hints

hints_flush_period

提示从内部缓冲区刷新到磁盘的频率。不会触发 fsync。

10000ms

`max_hints_file_size

单个提示文件的最大大小(以兆字节为单位)。

128MiB

hints_compression

要应用于提示文件的压缩。如果省略,提示文件将以未压缩的方式写入。支持 LZ4、Snappy 和 Deflate 压缩器。

LZ4Compressor

使用 nodetool 在运行时配置提示

nodetool 提供了几个用于配置提示或获取提示相关信息的命令。nodetool 命令会覆盖运行该命令的节点的 cassandra.yaml 中的任何相应设置。

表 2. 用于提示的 Nodetool 命令

命令 描述

nodetool disablehandoff

禁用存储和传递提示

nodetool disablehintsfordc

禁用将提示存储和传递到数据中心

nodetool enablehandoff

重新启用当前节点上未来的提示存储和传递

nodetool enablehintsfordc

启用先前禁用的数据中心的提示

nodetool getmaxhintwindow

打印最大提示窗口(毫秒)。Cassandra 4.0 中的新功能。

nodetool handoffwindow

打印当前的提示切换窗口

nodetool pausehandoff

暂停提示传递过程

nodetool resumehandoff

恢复提示传递过程

nodetool sethintedhandoffthrottlekb

设置提示切换节流,单位为每秒千字节,每个传递线程

nodetool setmaxhintwindow

设置指定的最大提示窗口(毫秒)

nodetool statushandoff

在当前节点上存储未来提示的状态

nodetool truncatehints

截断本地节点上的所有提示,或截断指定端点的提示。

在运行时加快提示播放速度

默认的 1024 kbps 切换节流对于大多数现代网络来说是保守的,在简单的节点重启中,您可能会积累许多千兆字节的提示,这些提示可能需要几个小时才能播放完毕。例如,如果您每个节点的摄取数据量为 100 Mbps,则单个 10 分钟的重启将创建 10 分钟 * (100 兆比特 / 秒) ~= 7 GiB 的数据,以 (1024 KiB / 秒) 的速度播放需要 7.5 GiB / (1024 KiB / 秒) = 2.03 小时。确切的计算取决于负载均衡策略(循环轮询优于令牌感知)、每个节点的令牌数量(更多令牌优于更少令牌),以及集群的写入速率,但无论如何,您可能希望在运行时增加此节流。

如果您遇到这种情况,可以考虑通过 nodetool sethintedhandoffthrottlekb 命令动态提高 hinted_handoff_throttle

允许节点在运行时停机更长时间

有时,节点可能停机时间超过正常的 max_hint_window(默认值为 3 小时),但硬件和数据本身仍然可以访问。在这种情况下,您可以考虑通过 Cassandra 4.0 中添加的 nodetool setmaxhintwindow 命令动态提高 max_hint_window (CASSANDRA-11720)。这将指示 Cassandra 继续为停机的端点保留提示更长的时间。

此命令应应用于集群中可能保留提示的所有节点。如果需要,可以通过在 cassandra.yaml 中设置 max_hint_window 设置,然后进行滚动重启,永久应用此设置。

监控提示传递

Cassandra 4.0 添加了直方图,可用于了解传递提示所需的时间,这对于运营商更好地识别问题非常有用 (CASSANDRA-13234)。

还有一些指标可用于跟踪 提示切换 <handoff-metrics>提示服务 <hintsservice-metrics> 指标。