跳至主要内容

ClickHouse Keeper (clickhouse-keeper)

注意

此页面不适用于 ClickHouse Cloud。 此处记录的过程在 ClickHouse Cloud 服务中是自动化的。

ClickHouse Keeper 为数据 复制分布式 DDL 查询执行提供协调系统。 ClickHouse Keeper 与 ZooKeeper 兼容。

实现细节

ZooKeeper 是第一个著名的开源协调系统之一。 它用 Java 实现,并且拥有非常简单而强大的数据模型。 ZooKeeper 的协调算法 ZooKeeper Atomic Broadcast (ZAB) 不会为读取提供线性化保证,因为每个 ZooKeeper 节点都会在本地提供读取服务。 与 ZooKeeper 不同,ClickHouse Keeper 使用 C++ 编写并使用 RAFT 算法 实现。 此算法允许读取和写入的线性化,并且在不同语言中有多种开源实现。

默认情况下,ClickHouse Keeper 提供与 ZooKeeper 相同的保证:线性化写入和非线性化读取。 它具有兼容的客户端-服务器协议,因此可以使用任何标准 ZooKeeper 客户端与 ClickHouse Keeper 交互。 快照和日志的格式与 ZooKeeper 不兼容,但 clickhouse-keeper-converter 工具可以将 ZooKeeper 数据转换为 ClickHouse Keeper 快照。 ClickHouse Keeper 中的服务器间协议也与 ZooKeeper 不兼容,因此混合的 ZooKeeper/ClickHouse Keeper 集群是不可能的。

ClickHouse Keeper 支持访问控制列表 (ACL),与 ZooKeeper 一样。 ClickHouse Keeper 支持相同的权限集并具有相同的内置方案:worldauthdigest。 digest 身份验证方案使用 username:password 对,密码以 Base64 编码。

注意

不支持外部集成。

配置

ClickHouse Keeper 可以用作 ZooKeeper 的独立替代方案,也可以用作 ClickHouse 服务器的内部组成部分。 在这两种情况下,配置几乎都是相同的 .xml 文件。

Keeper 配置设置

ClickHouse Keeper 的主要配置标签是 <keeper_server>,它具有以下参数

参数描述默认值
tcp_port客户端连接的端口。2181
tcp_port_secure客户端与 keeper-server 之间 SSL 连接的安全端口。-
server_id唯一的服务器 ID,ClickHouse Keeper 集群的每个参与者都必须具有唯一的数字(1、2、3 等)。-
log_storage_path协调日志的路径,与 ZooKeeper 一样,最好将日志存储在非繁忙的节点上。-
snapshot_storage_path协调快照的路径。-
enable_reconfiguration通过 reconfig 启用动态集群重新配置。False
max_memory_usage_soft_limitKeeper 最大内存使用量的软限制(字节)。max_memory_usage_soft_limit_ratio * physical_memory_amount
max_memory_usage_soft_limit_ratio如果 max_memory_usage_soft_limit 未设置或设置为零,我们将使用此值来定义默认软限制。0.9
cgroups_memory_observer_wait_time如果 max_memory_usage_soft_limit 未设置或设置为 0,我们将使用此时间间隔来观察物理内存量。 内存量发生变化后,我们将通过 max_memory_usage_soft_limit_ratio 重新计算 Keeper 的内存软限制。15
http_controlHTTP 控制 接口的配置。-
digest_enabled启用实时数据一致性检查True
create_snapshot_on_exit在关闭期间创建快照-
hostname_checks_enabled为集群配置启用健全性主机名检查(例如,如果 localhost 与远程端点一起使用)True

其他常见参数从 ClickHouse 服务器配置(listen_hostlogger 等)继承。

内部协调设置

内部协调设置位于 <keeper_server>.<coordination_settings> 部分,并具有以下参数

参数描述默认值
operation_timeout_ms单个客户端操作的超时时间(毫秒)。10000
min_session_timeout_ms客户端会话的最小超时时间(毫秒)。10000
session_timeout_ms客户端会话的最大超时时间(毫秒)。100000
dead_session_check_period_msClickHouse Keeper 多久检查一次死会话并将其删除(毫秒)。500
heart_beat_interval_msClickHouse Keeper 领导者多久向跟随者发送一次心跳(毫秒)。500
election_timeout_lower_bound_ms如果跟随者在此时间间隔内未收到来自领导者的心跳,则它可以启动领导者选举。 必须小于或等于 election_timeout_upper_bound_ms。 理想情况下,它们不应相等。1000
election_timeout_upper_bound_ms如果跟随者在此时间间隔内未收到来自领导者的心跳,则它必须启动领导者选举。2000
rotate_log_storage_interval在一个文件中存储多少条日志记录。100000
reserved_log_items在压缩之前存储多少条协调日志记录。100000
snapshot_distanceClickHouse Keeper 多久创建一次新快照(以日志中的记录数为单位)。100000
snapshots_to_keep保留多少个快照。3
stale_log_gap领导者将跟随者视为陈旧并向其发送快照而不是日志的阈值(以日志中的记录数为单位)。10000
fresh_log_gap节点变得新鲜的时间。200
max_requests_batch_size在发送到 RAFT 之前,请求计数中的批处理的最大大小。100
force_sync在每次写入协调日志时调用 fsynctrue
quorum_reads通过整个 RAFT 共识以类似速度执行读取请求作为写入。false
raft_logs_level关于协调的文本记录级别(跟踪、调试等)。系统默认值
auto_forwarding允许将写入请求从跟随者转发到领导者。true
shutdown_timeout等待完成内部连接并关闭(毫秒)。5000
startup_timeout如果服务器在指定的时间内未连接到其他仲裁参与者,它将终止(毫秒)。30000
four_letter_word_white_list4lw 命令的白名单。conf, cons, crst, envi, ruok, srst, srvr, stat, wchs, dirs, mntr, isro, rcvr, apiv, csnp, lgif, rqld, ydld
async_replication启用异步复制。 尽管实现了更好的性能,但所有写入和读取保证都得以保留。 设置默认情况下处于禁用状态,以免破坏向后兼容性false
latest_logs_cache_size_threshold最新日志条目内存缓存的最大总大小1GiB
commit_logs_cache_size_threshold用于提交所需下一个日志条目内存缓存的最大总大小500MiB
disk_move_retries_wait_ms在文件在磁盘之间移动时发生的错误后,两次重试之间的等待时间。1000
disk_move_retries_during_init在初始化期间文件在磁盘之间移动时发生的错误后的重试次数。100
experimental_use_rocksdb使用 rocksdb 作为后端存储0

仲裁配置位于 <keeper_server>.<raft_configuration> 部分,并包含服务器描述。

整个仲裁组唯一的参数是secure,它允许仲裁组参与者之间使用加密连接进行通信。如果内部节点之间需要 SSL 连接,可以将此参数设置为true,否则可以不设置。

每个<server>的主要参数是

  • id - 仲裁组中的服务器标识符。
  • hostname - 此服务器所在的 hostname。
  • port - 此服务器监听连接的端口。
  • can_become_leader - 设置为false可将服务器设置为learner。如果省略,则值为true
注意

在 ClickHouse Keeper 集群拓扑发生变化(例如,替换服务器)的情况下,请确保server_idhostname的映射保持一致,并避免为不同的服务器重新排列或重复使用现有的server_id(例如,如果依赖自动化脚本部署 ClickHouse Keeper,则可能会发生这种情况)。

如果 Keeper 实例的主机可以更改,我们建议定义并使用 hostname 而不是原始 IP 地址。更改 hostname 等同于删除并添加服务器,在某些情况下可能无法执行此操作(例如,没有足够的 Keeper 实例形成仲裁组)。

注意

默认情况下async_replication处于禁用状态,以避免破坏向后兼容性。如果您的所有 Keeper 实例都在集群中运行支持async_replication的版本(v23.9+),我们建议启用它,因为它可以在没有任何缺点的情况下提高性能。

带有三个节点的仲裁组配置示例可以在集成测试中找到,这些测试以test_keeper_为前缀。服务器 #1 的配置示例

<keeper_server>
<tcp_port>2181</tcp_port>
<server_id>1</server_id>
<log_storage_path>/var/lib/clickhouse/coordination/log</log_storage_path>
<snapshot_storage_path>/var/lib/clickhouse/coordination/snapshots</snapshot_storage_path>

<coordination_settings>
<operation_timeout_ms>10000</operation_timeout_ms>
<session_timeout_ms>30000</session_timeout_ms>
<raft_logs_level>trace</raft_logs_level>
</coordination_settings>

<raft_configuration>
<server>
<id>1</id>
<hostname>zoo1</hostname>
<port>9234</port>
</server>
<server>
<id>2</id>
<hostname>zoo2</hostname>
<port>9234</port>
</server>
<server>
<id>3</id>
<hostname>zoo3</hostname>
<port>9234</port>
</server>
</raft_configuration>
</keeper_server>

如何运行

ClickHouse Keeper 包含在 ClickHouse 服务器软件包中,只需将<keeper_server>的配置添加到您的/etc/your_path_to_config/clickhouse-server/config.xml并像往常一样启动 ClickHouse 服务器即可。如果要运行独立的 ClickHouse Keeper,您可以通过类似的方式启动它,方法是

clickhouse-keeper --config /etc/your_path_to_config/config.xml

如果您没有符号链接(clickhouse-keeper),您可以创建它或将keeper指定为clickhouse的参数

clickhouse keeper --config /etc/your_path_to_config/config.xml

四字命令

ClickHouse Keeper 还提供 4lw 命令,这些命令与 Zookeeper 几乎相同。每个命令由四个字母组成,例如mntrstat等。还有一些更有趣的命令:stat提供了有关服务器和连接客户端的一些一般信息,而srvrcons则分别提供了有关服务器和连接的详细信息。

4lw 命令有一个白名单配置four_letter_word_white_list,其默认值为conf,cons,crst,envi,ruok,srst,srvr,stat,wchs,dirs,mntr,isro,rcvr,apiv,csnp,lgif,rqld,ydld

您可以通过 telnet 或 nc 在客户端端口向 ClickHouse Keeper 发送命令。

echo mntr | nc localhost 9181

以下是详细的 4lw 命令

  • ruok:测试服务器是否在非错误状态下运行。如果服务器正在运行,它将响应imok。否则,它将根本不响应。imok的响应并不一定表示服务器已加入仲裁组,只是表示服务器进程正在运行并绑定到指定的客户端端口。使用“stat”查看关于与仲裁组和客户端连接信息相关的状态的详细信息。
imok
  • mntr:输出可用于监控集群健康状况的变量列表。
zk_version      v21.11.1.1-prestable-7a4a0b0edef0ad6e0aa662cd3b90c3f4acf796e7
zk_avg_latency 0
zk_max_latency 0
zk_min_latency 0
zk_packets_received 68
zk_packets_sent 68
zk_num_alive_connections 1
zk_outstanding_requests 0
zk_server_state leader
zk_znode_count 4
zk_watch_count 1
zk_ephemerals_count 0
zk_approximate_data_size 723
zk_open_file_descriptor_count 310
zk_max_file_descriptor_count 10240
zk_followers 0
zk_synced_followers 0
  • srvr:列出服务器的完整详细信息。
ClickHouse Keeper version: v21.11.1.1-prestable-7a4a0b0edef0ad6e0aa662cd3b90c3f4acf796e7
Latency min/avg/max: 0/0/0
Received: 2
Sent : 2
Connections: 1
Outstanding: 0
Zxid: 34
Mode: leader
Node count: 4
  • stat:列出服务器和已连接客户端的简要详细信息。
ClickHouse Keeper version: v21.11.1.1-prestable-7a4a0b0edef0ad6e0aa662cd3b90c3f4acf796e7
Clients:
192.168.1.1:52852(recved=0,sent=0)
192.168.1.1:52042(recved=24,sent=48)
Latency min/avg/max: 0/0/0
Received: 4
Sent : 4
Connections: 1
Outstanding: 0
Zxid: 36
Mode: leader
Node count: 4
  • srst:重置服务器统计信息。该命令将影响srvrmntrstat的结果。
Server stats reset.
  • conf:打印有关服务配置的详细信息。
server_id=1
tcp_port=2181
four_letter_word_white_list=*
log_storage_path=./coordination/logs
snapshot_storage_path=./coordination/snapshots
max_requests_batch_size=100
session_timeout_ms=30000
operation_timeout_ms=10000
dead_session_check_period_ms=500
heart_beat_interval_ms=500
election_timeout_lower_bound_ms=1000
election_timeout_upper_bound_ms=2000
reserved_log_items=1000000000000000
snapshot_distance=10000
auto_forwarding=true
shutdown_timeout=5000
startup_timeout=240000
raft_logs_level=information
snapshots_to_keep=3
rotate_log_storage_interval=100000
stale_log_gap=10000
fresh_log_gap=200
max_requests_batch_size=100
quorum_reads=false
force_sync=false
compress_logs=true
compress_snapshots_with_zstd_format=true
configuration_change_tries_count=20
  • cons:列出所有连接到此服务器的客户端的完整连接/会话详细信息。包括有关接收/发送的数据包数量、会话 ID、操作延迟、最后执行的操作等的信息。
 192.168.1.1:52163(recved=0,sent=0,sid=0xffffffffffffffff,lop=NA,est=1636454787393,to=30000,lzxid=0xffffffffffffffff,lresp=0,llat=0,minlat=0,avglat=0,maxlat=0)
192.168.1.1:52042(recved=9,sent=18,sid=0x0000000000000001,lop=List,est=1636454739887,to=30000,lcxid=0x0000000000000005,lzxid=0x0000000000000005,lresp=1636454739892,llat=0,minlat=0,avglat=0,maxlat=0)
  • crst:重置所有连接的连接/会话统计信息。
Connection stats reset.
  • envi:打印有关服务环境的详细信息
Environment:
clickhouse.keeper.version=v21.11.1.1-prestable-7a4a0b0edef0ad6e0aa662cd3b90c3f4acf796e7
host.name=ZBMAC-C02D4054M.local
os.name=Darwin
os.arch=x86_64
os.version=19.6.0
cpu.count=12
user.name=root
user.home=/Users/JackyWoo/
user.dir=/Users/JackyWoo/project/jd/clickhouse/cmake-build-debug/programs/
user.tmp=/var/folders/b4/smbq5mfj7578f2jzwn602tt40000gn/T/
  • dirs:显示快照和日志文件的大小(以字节为单位)
snapshot_dir_size: 0
log_dir_size: 3875
  • isro:测试服务器是否在只读模式下运行。如果服务器处于只读模式,则响应ro;如果服务器不处于只读模式,则响应rw
rw
  • wchs:列出服务器的监视的简要信息。
1 connections watching 1 paths
Total watches:1
  • wchc:按会话列出服务器的监视的详细信息。这将输出一个带有相关监视(路径)的会话(连接)列表。请注意,根据监视的数量,此操作可能很昂贵(会影响服务器性能),谨慎使用。
0x0000000000000001
/clickhouse/task_queue/ddl
  • wchp:按路径列出服务器的监视的详细信息。这将输出一个带有相关会话的路径(znode)列表。请注意,根据监视的数量,此操作可能很昂贵(即,会影响服务器性能),谨慎使用。
/clickhouse/task_queue/ddl
0x0000000000000001
  • dump:列出未完成的会话和临时节点。这仅适用于领导者。
Sessions dump (2):
0x0000000000000001
0x0000000000000002
Sessions with Ephemerals (1):
0x0000000000000001
/clickhouse/task_queue/ddl
  • csnp:安排快照创建任务。如果成功,则返回已安排快照的最后一个提交日志索引;如果失败,则返回Failed to schedule snapshot creation task.。请注意,lgif命令可以帮助您确定快照是否已完成。
100
  • lgif:Keeper 日志信息。first_log_idx:日志存储中的我的第一个日志索引;first_log_term:我的第一个日志任期;last_log_idx:日志存储中的我的最后一个日志索引;last_log_term:我的最后一个日志任期;last_committed_log_idx:状态机中的我的最后一个提交日志索引;leader_committed_log_idx:从我的角度来看领导者的已提交日志索引;target_committed_log_idx:应提交到的目标日志索引;last_snapshot_idx:最后一个快照中最大的已提交日志索引。
first_log_idx   1
first_log_term 1
last_log_idx 101
last_log_term 1
last_committed_log_idx 100
leader_committed_log_idx 101
target_committed_log_idx 101
last_snapshot_idx 50
  • rqld:请求成为新的领导者。如果请求已发送,则返回Sent leadership request to leader.;如果请求未发送,则返回Failed to send leadership request to leader.。请注意,如果节点已经是领导者,则结果与发送请求相同。
Sent leadership request to leader.
  • ftfl:列出所有功能标志以及它们是否已为 Keeper 实例启用。
filtered_list   1
multi_read 1
check_not_exists 0
  • ydld:请求放弃领导权并成为跟随者。如果接收请求的服务器是领导者,它将首先暂停写入操作,等待继任者(当前领导者永远不会是继任者)完成最新日志的追赶,然后辞职。继任者将自动选择。如果请求已发送,则返回Sent yield leadership request to leader.;如果请求未发送,则返回Failed to send yield leadership request to leader.。请注意,如果节点已经是跟随者,则结果与发送请求相同。
Sent yield leadership request to leader.
  • pfev:返回所有已收集事件的值。对于每个事件,它将返回事件名称、事件值和事件的描述。
FileOpen    62  Number of files opened.
Seek 4 Number of times the 'lseek' function was called.
ReadBufferFromFileDescriptorRead 126 Number of reads (read/pread) from a file descriptor. Does not include sockets.
ReadBufferFromFileDescriptorReadFailed 0 Number of times the read (read/pread) from a file descriptor have failed.
ReadBufferFromFileDescriptorReadBytes 178846 Number of bytes read from file descriptors. If the file is compressed, this will show the compressed data size.
WriteBufferFromFileDescriptorWrite 7 Number of writes (write/pwrite) to a file descriptor. Does not include sockets.
WriteBufferFromFileDescriptorWriteFailed 0 Number of times the write (write/pwrite) to a file descriptor have failed.
WriteBufferFromFileDescriptorWriteBytes 153 Number of bytes written to file descriptors. If the file is compressed, this will show compressed data size.
FileSync 2 Number of times the F_FULLFSYNC/fsync/fdatasync function was called for files.
DirectorySync 0 Number of times the F_FULLFSYNC/fsync/fdatasync function was called for directories.
FileSyncElapsedMicroseconds 12756 Total time spent waiting for F_FULLFSYNC/fsync/fdatasync syscall for files.
DirectorySyncElapsedMicroseconds 0 Total time spent waiting for F_FULLFSYNC/fsync/fdatasync syscall for directories.
ReadCompressedBytes 0 Number of bytes (the number of bytes before decompression) read from compressed sources (files, network).
CompressedReadBufferBlocks 0 Number of compressed blocks (the blocks of data that are compressed independent of each other) read from compressed sources (files, network).
CompressedReadBufferBytes 0 Number of uncompressed bytes (the number of bytes after decompression) read from compressed sources (files, network).
AIOWrite 0 Number of writes with Linux or FreeBSD AIO interface
AIOWriteBytes 0 Number of bytes written with Linux or FreeBSD AIO interface
...

HTTP 控制

ClickHouse Keeper 提供了一个 HTTP 接口来检查副本是否已准备好接收流量。它可以在云环境中使用,例如Kubernetes.

启用/ready端点的配置示例

<clickhouse>
<keeper_server>
<http_control>
<port>9182</port>
<readiness>
<endpoint>/ready</endpoint>
</readiness>
</http_control>
</keeper_server>
</clickhouse>

功能标志

Keeper 与 ZooKeeper 及其客户端完全兼容,但它还引入了一些 ClickHouse 客户端可以使用的一些独特功能和请求类型。由于这些功能可能会引入向后不兼容的更改,因此大多数功能默认情况下处于禁用状态,可以使用keeper_server.feature_flags配置启用。
所有功能都可以显式禁用。
如果要为 Keeper 集群启用新功能,我们建议您首先将集群中的所有 Keeper 实例更新到支持该功能的版本,然后启用该功能本身。

禁用multi_read并启用check_not_exists的功能标志配置示例

<clickhouse>
<keeper_server>
<feature_flags>
<multi_read>0</multi_read>
<check_not_exists>1</check_not_exists>
</feature_flags>
</keeper_server>
</clickhouse>

以下功能可用

multi_read - 支持读取多个请求。默认:1
filtered_list - 支持过滤结果的列表请求(按节点类型过滤:临时节点或持久节点)。默认:1
check_not_exists - 支持CheckNotExists请求,该请求断言节点不存在。默认:0
create_if_not_exists - 支持CreateIfNotExists请求,该请求将尝试创建节点(如果它不存在)。如果它存在,则不会应用任何更改,并返回ZOK。默认:0

从 ZooKeeper 迁移

无法从 ZooKeeper 无缝迁移到 ClickHouse Keeper。您必须停止 ZooKeeper 集群、转换数据,然后启动 ClickHouse Keeper。clickhouse-keeper-converter工具允许将 ZooKeeper 日志和快照转换为 ClickHouse Keeper 快照。它仅适用于 ZooKeeper > 3.4。迁移步骤

  1. 停止所有 ZooKeeper 节点。

  2. 可选但建议:找到 ZooKeeper 领导者节点,启动并停止它。这将强制 ZooKeeper 创建一致的快照。

  3. 例如,在领导者上运行clickhouse-keeper-converter

clickhouse-keeper-converter --zookeeper-logs-dir /var/lib/zookeeper/version-2 --zookeeper-snapshots-dir /var/lib/zookeeper/version-2 --output-dir /path/to/clickhouse/keeper/snapshots
  1. 将快照复制到配置了keeper的 ClickHouse 服务器节点上,或者启动 ClickHouse Keeper 而不是 ZooKeeper。快照必须持久化到所有节点上,否则空节点可能会更快,其中一个节点可能会成为领导者。
注意

keeper-converter工具不可从 Keeper 独立二进制文件获得。
如果您安装了 ClickHouse,您可以直接使用二进制文件

clickhouse keeper-converter ...

否则,您可以下载二进制文件并像上面描述的那样运行该工具,而无需安装 ClickHouse。

在失去仲裁组后恢复

由于 ClickHouse Keeper 使用 Raft,因此它可以容忍一定数量的节点崩溃,具体取决于集群大小。例如,对于一个 3 节点集群,如果只有一个节点崩溃,它将继续正常工作。

集群配置可以动态配置,但有一些限制。重新配置也依赖于 Raft,因此要从集群中添加/删除节点,您需要拥有仲裁组。如果您同时在集群中丢失了太多节点,并且没有任何机会重新启动它们,Raft 将停止工作,并且不允许您使用传统方式重新配置集群。

但是,ClickHouse Keeper 具有恢复模式,允许您只使用一个节点强行重新配置集群。如果无法重新启动节点或在同一端点上启动新实例,则应在万不得已的情况下执行此操作。

继续之前需要注意的重要事项

  • 确保失败的节点无法再次连接到集群。
  • 在步骤中指定之前,不要启动任何新节点。

确保上述事项为真后,您需要执行以下操作

  1. 选择一个 Keeper 节点作为新的领导者。请注意,该节点的数据将用于整个集群,因此我们建议使用状态最新更新的节点。
  2. 在执行任何其他操作之前,请备份所选节点的log_storage_pathsnapshot_storage_path文件夹。
  3. 在您想要使用的所有节点上重新配置集群。
  4. 向您选择的节点发送四个字母的命令rcvr,这将使节点进入恢复模式或停止选定节点上的 Keeper 实例,并使用--force-recovery参数重新启动它。
  5. 一个接一个地,在新节点上启动 Keeper 实例,确保在启动下一个实例之前,mntr返回follower作为zk_server_state
  6. 在恢复模式下,领导节点将为mntr命令返回错误消息,直到它与新节点建立一致,并拒绝来自客户端和跟随者的任何请求。
  7. 在达成一致后,领导节点将返回正常运行模式,使用 Raft 验证接受所有请求,mntr应该返回leader作为zk_server_state

使用带 Keeper 的磁盘

Keeper 支持用于存储快照、日志文件和状态文件的外部磁盘的子集。

支持的磁盘类型为

  • s3_plain
  • s3
  • local

以下是配置中包含的磁盘定义示例。

<clickhouse>
<storage_configuration>
<disks>
<log_local>
<type>local</type>
<path>/var/lib/clickhouse/coordination/logs/</path>
</log_local>
<log_s3_plain>
<type>s3_plain</type>
<endpoint>https://some_s3_endpoint/logs/</endpoint>
<access_key_id>ACCESS_KEY</access_key_id>
<secret_access_key>SECRET_KEY</secret_access_key>
</log_s3_plain>
<snapshot_local>
<type>local</type>
<path>/var/lib/clickhouse/coordination/snapshots/</path>
</snapshot_local>
<snapshot_s3_plain>
<type>s3_plain</type>
<endpoint>https://some_s3_endpoint/snapshots/</endpoint>
<access_key_id>ACCESS_KEY</access_key_id>
<secret_access_key>SECRET_KEY</secret_access_key>
</snapshot_s3_plain>
<state_s3_plain>
<type>s3_plain</type>
<endpoint>https://some_s3_endpoint/state/</endpoint>
<access_key_id>ACCESS_KEY</access_key_id>
<secret_access_key>SECRET_KEY</secret_access_key>
</state_s3_plain>
</disks>
</storage_configuration>
</clickhouse>

要将磁盘用于日志,keeper_server.log_storage_disk配置应设置为磁盘的名称。
要将磁盘用于快照,keeper_server.snapshot_storage_disk配置应设置为磁盘的名称。
此外,可以通过分别使用keeper_server.latest_log_storage_diskkeeper_server.latest_snapshot_storage_disk,为最新日志或快照使用不同的磁盘。
在这种情况下,Keeper 将在创建新的日志或快照时自动将文件移到正确的磁盘。要将磁盘用于状态文件,keeper_server.state_storage_disk配置应设置为磁盘的名称。

在磁盘之间移动文件是安全的,如果 Keeper 在传输过程中停止,不会丢失数据。在文件完全移到新磁盘之前,它不会从旧磁盘中删除。

keeper_server.coordination_settings.force_sync设置为true(默认情况下为true)的 Keeper 无法为所有类型的磁盘满足某些保证。
目前,只有local类型的磁盘支持持久同步。
如果使用force_sync,如果未使用latest_log_storage_disklog_storage_disk应该是local磁盘。
如果使用latest_log_storage_disk,它应该始终是local磁盘。
如果禁用了force_sync,所有类型的磁盘都可以在任何设置中使用。

Keeper 实例的可能存储设置如下

<clickhouse>
<keeper_server>
<log_storage_disk>log_s3_plain</log_storage_disk>
<latest_log_storage_disk>log_local</latest_log_storage_disk>

<snapshot_storage_disk>snapshot_s3_plain</snapshot_storage_disk>
<latest_snapshot_storage_disk>snapshot_local</latest_snapshot_storage_disk>
</keeper_server>
</clickhouse>

此实例将所有日志(最新日志除外)存储在log_s3_plain磁盘上,而最新日志将存储在log_local磁盘上。
快照也是同样的逻辑,所有快照(最新快照除外)将存储在snapshot_s3_plain上,而最新快照将存储在snapshot_local磁盘上。

更改磁盘设置

信息

在应用新的磁盘设置之前,请手动备份所有 Keeper 日志和快照。

如果定义了分层磁盘设置(为最新文件使用单独的磁盘),Keeper 将尝试在启动时自动将文件移到正确的磁盘。
与之前相同,在文件完全移到新磁盘之前,不会从旧磁盘中删除,因此可以安全地执行多次重新启动。

如果需要将文件移到全新的磁盘(或从双磁盘设置移到单磁盘设置),可以使用keeper_server.old_snapshot_storage_diskkeeper_server.old_log_storage_disk的多个定义。

以下配置显示了如何从之前的双磁盘设置移到全新的单磁盘设置

<clickhouse>
<keeper_server>
<old_log_storage_disk>log_local</old_log_storage_disk>
<old_log_storage_disk>log_s3_plain</old_log_storage_disk>
<log_storage_disk>log_local2</log_storage_disk>

<old_snapshot_storage_disk>snapshot_s3_plain</old_snapshot_storage_disk>
<old_snapshot_storage_disk>snapshot_local</old_snapshot_storage_disk>
<snapshot_storage_disk>snapshot_local2</snapshot_storage_disk>
</keeper_server>
</clickhouse>

在启动时,所有日志文件将从log_locallog_s3_plain移到log_local2磁盘。
此外,所有快照文件将从snapshot_localsnapshot_s3_plain移到snapshot_local2磁盘。

配置日志缓存

为了最大程度地减少从磁盘读取的数据量,Keeper 将日志条目缓存在内存中。
如果请求很大,日志条目将占用太多内存,因此缓存日志的数量会有上限。
限制由以下两个配置控制

  • latest_logs_cache_size_threshold - 存储在缓存中的最新日志的总大小
  • commit_logs_cache_size_threshold - 接下来需要提交的后续日志的总大小

如果默认值太大,可以通过减小这两个配置来减少内存使用量。

注意

可以使用pfev命令检查从每个缓存和文件读取的日志数量。
您还可以使用 Prometheus 端点中的指标来跟踪两个缓存的当前大小。

Prometheus

Keeper 可以公开指标数据,以便从 Prometheus 刮取。
配置方式与ClickHouse 的配置方式相同。

ClickHouse Keeper 用户指南

本指南提供简单的最小设置,用于配置 ClickHouse Keeper,并提供一个有关如何测试分布式操作的示例。此示例使用 Linux 上的 3 个节点执行。

1. 使用 Keeper 设置配置节点

  1. 在 3 个主机(chnode1、chnode2、chnode3)上安装 3 个 ClickHouse 实例。(查看快速入门了解有关安装 ClickHouse 的详细信息。)

  2. 在每个节点上,添加以下条目以允许通过网络接口进行外部通信。

    <listen_host>0.0.0.0</listen_host>
  3. 将以下 ClickHouse Keeper 配置添加到所有三个服务器,并更新每个服务器的<server_id>设置;对于chnode1应该是1chnode2应该是2,依此类推。

    <keeper_server>
    <tcp_port>9181</tcp_port>
    <server_id>1</server_id>
    <log_storage_path>/var/lib/clickhouse/coordination/log</log_storage_path>
    <snapshot_storage_path>/var/lib/clickhouse/coordination/snapshots</snapshot_storage_path>

    <coordination_settings>
    <operation_timeout_ms>10000</operation_timeout_ms>
    <session_timeout_ms>30000</session_timeout_ms>
    <raft_logs_level>warning</raft_logs_level>
    </coordination_settings>

    <raft_configuration>
    <server>
    <id>1</id>
    <hostname>chnode1.domain.com</hostname>
    <port>9234</port>
    </server>
    <server>
    <id>2</id>
    <hostname>chnode2.domain.com</hostname>
    <port>9234</port>
    </server>
    <server>
    <id>3</id>
    <hostname>chnode3.domain.com</hostname>
    <port>9234</port>
    </server>
    </raft_configuration>
    </keeper_server>

    这些是上面使用的基本设置

    参数描述示例
    tcp_portkeeper 客户端使用的端口9181 默认值与 zookeeper 中的 2181 等效
    server_idraft 配置中使用的每个 CLickHouse Keeper 服务器的标识符1
    coordination_settings参数(如超时)的节超时:10000,日志级别:跟踪
    server参与服务器的定义每个服务器定义的列表
    raft_configurationkeeper 集群中每个服务器的设置每个服务器的设置
    idkeeper 服务的服务器的数字 ID1
    hostnamekeeper 集群中每个服务器的主机名、IP 或 FQDNchnode1.domain.com
    port监听用于服务器间 keeper 连接的端口9234
  1. 启用 Zookeeper 组件。它将使用 ClickHouse Keeper 引擎

        <zookeeper>
    <node>
    <host>chnode1.domain.com</host>
    <port>9181</port>
    </node>
    <node>
    <host>chnode2.domain.com</host>
    <port>9181</port>
    </node>
    <node>
    <host>chnode3.domain.com</host>
    <port>9181</port>
    </node>
    </zookeeper>

    这些是上面使用的基本设置

    参数描述示例
    nodeClickHouse Keeper 连接的节点列表每个服务器的设置条目
    host每个 ClickHouse keepr 节点的主机名、IP 或 FQDNchnode1.domain.com
    portClickHouse Keeper 客户端端口9181
  2. 重新启动 ClickHouse 并验证每个 Keeper 实例是否正在运行。在每个服务器上执行以下命令。如果 Keeper 正在运行且运行状况良好,ruok命令将返回imok

    # echo ruok | nc localhost 9181; echo
    imok
  3. system数据库有一个名为zookeeper的表,其中包含 ClickHouse Keeper 实例的详细信息。让我们查看该表

    SELECT *
    FROM system.zookeeper
    WHERE path IN ('/', '/clickhouse')

    该表如下所示

    ┌─name───────┬─value─┬─czxid─┬─mzxid─┬───────────────ctime─┬───────────────mtime─┬─version─┬─cversion─┬─aversion─┬─ephemeralOwner─┬─dataLength─┬─numChildren─┬─pzxid─┬─path────────┐
    │ clickhouse │ │ 124 │ 124 │ 2022-03-07 00:49:34 │ 2022-03-07 00:49:34 │ 0 │ 2 │ 0 │ 0 │ 0 │ 2 │ 5693 │ / │
    │ task_queue │ │ 125 │ 125 │ 2022-03-07 00:49:34 │ 2022-03-07 00:49:34 │ 0 │ 1 │ 0 │ 0 │ 0 │ 1 │ 126 │ /clickhouse │
    │ tables │ │ 5693 │ 5693 │ 2022-03-07 00:49:34 │ 2022-03-07 00:49:34 │ 0 │ 3 │ 0 │ 0 │ 0 │ 3 │ 6461 │ /clickhouse │
    └────────────┴───────┴───────┴───────┴─────────────────────┴─────────────────────┴─────────┴──────────┴──────────┴────────────────┴────────────┴─────────────┴───────┴─────────────┘

2. 在 ClickHouse 中配置集群

  1. 让我们使用 2 个节点上的 2 个分片和仅一个副本配置一个简单的集群。第三个节点将用于满足 ClickHouse Keeper 中的要求的一致性。更新chnode1chnode2上的配置。以下集群在每个节点上定义 1 个分片,总共 2 个分片,没有副本。在此示例中,部分数据将在一个节点上,部分数据将在另一个节点上

        <remote_servers>
    <cluster_2S_1R>
    <shard>
    <replica>
    <host>chnode1.domain.com</host>
    <port>9000</port>
    <user>default</user>
    <password>ClickHouse123!</password>
    </replica>
    </shard>
    <shard>
    <replica>
    <host>chnode2.domain.com</host>
    <port>9000</port>
    <user>default</user>
    <password>ClickHouse123!</password>
    </replica>
    </shard>
    </cluster_2S_1R>
    </remote_servers>
    参数描述示例
    shard集群定义上的副本列表每个分片的副本列表
    replica每个副本的设置列表每个副本的设置条目
    host将托管副本分片的主机名、IP 或 FQDNchnode1.domain.com
    port用于使用本机 tcp 协议进行通信的端口9000
    user将用于对集群实例进行身份验证的用户名default
    password为用户定义的密码,以允许连接到集群实例ClickHouse123!
  1. 重新启动 ClickHouse 并验证集群是否已创建

    SHOW clusters;

    您应该看到您的集群

    ┌─cluster───────┐
    │ cluster_2S_1R │
    └───────────────┘

3. 创建和测试分布式表

  1. chnode1上使用 ClickHouse 客户端在新的集群上创建一个新的数据库。ON CLUSTER子句会自动在两个节点上创建数据库。

    CREATE DATABASE db1 ON CLUSTER 'cluster_2S_1R';
  2. db1数据库上创建一个新表。同样,ON CLUSTER会在两个节点上创建表。

    CREATE TABLE db1.table1 on cluster 'cluster_2S_1R'
    (
    `id` UInt64,
    `column1` String
    )
    ENGINE = MergeTree
    ORDER BY column1
  3. chnode1节点上,添加几行

    INSERT INTO db1.table1
    (id, column1)
    VALUES
    (1, 'abc'),
    (2, 'def')
  4. chnode2节点上添加几行

    INSERT INTO db1.table1
    (id, column1)
    VALUES
    (3, 'ghi'),
    (4, 'jkl')
  5. 请注意,在每个节点上运行SELECT语句只会显示该节点上的数据。例如,在chnode1

    SELECT *
    FROM db1.table1
    Query id: 7ef1edbc-df25-462b-a9d4-3fe6f9cb0b6d

    ┌─id─┬─column1─┐
    │ 1 │ abc │
    │ 2 │ def │
    └────┴─────────┘

    2 rows in set. Elapsed: 0.006 sec.

    chnode2

    SELECT *
    FROM db1.table1
    Query id: c43763cc-c69c-4bcc-afbe-50e764adfcbf

    ┌─id─┬─column1─┐
    │ 3 │ ghi │
    │ 4 │ jkl │
    └────┴─────────┘
  6. 您可以创建一个Distributed表来表示两个分片上的数据。使用Distributed表引擎的表不存储任何自身数据,但允许在多个服务器上进行分布式查询处理。读取命中所有分片,写入可以分布到分片中。在chnode1上运行以下查询

    CREATE TABLE db1.dist_table (
    id UInt64,
    column1 String
    )
    ENGINE = Distributed(cluster_2S_1R,db1,table1)
  7. 请注意,查询dist_table将返回来自两个分片的全部四行数据

    SELECT *
    FROM db1.dist_table
    Query id: 495bffa0-f849-4a0c-aeea-d7115a54747a

    ┌─id─┬─column1─┐
    │ 1 │ abc │
    │ 2 │ def │
    └────┴─────────┘
    ┌─id─┬─column1─┐
    │ 3 │ ghi │
    │ 4 │ jkl │
    └────┴─────────┘

    4 rows in set. Elapsed: 0.018 sec.

总结

本指南演示了如何使用 ClickHouse Keeper 设置集群。使用 ClickHouse Keeper,您可以配置集群并定义可以在分片之间复制的分布式表。

使用唯一路径配置 ClickHouse Keeper

注意

此页面不适用于 ClickHouse Cloud。 此处记录的过程在 ClickHouse Cloud 服务中是自动化的。

描述

本文介绍了如何使用内置的{uuid}宏设置在 ClickHouse Keeper 或 ZooKeeper 中创建唯一条目。在频繁创建和删除表时,唯一路径非常有用,因为这避免了必须等待几分钟才能让 Keeper 垃圾回收删除路径条目,因为每次创建路径时,都会在该路径中使用一个新的uuid;路径永远不会重复使用。

示例环境

一个三节点集群,配置为在所有三个节点上都有 ClickHouse Keeper,并在两个节点上都有 ClickHouse。 这为 ClickHouse Keeper 提供了三个节点(包括一个仲裁节点),以及一个由两个副本组成的单个 ClickHouse 分片。

node描述
chnode1.marsnet.local数据节点 - 集群 cluster_1S_2R
chnode2.marsnet.local数据节点 - 集群 cluster_1S_2R
chnode3.marsnet.localClickHouse Keeper 仲裁节点

集群示例配置

    <remote_servers>
<cluster_1S_2R>
<shard>
<replica>
<host>chnode1.marsnet.local</host>
<port>9440</port>
<user>default</user>
<password>ClickHouse123!</password>
<secure>1</secure>
</replica>
<replica>
<host>chnode2.marsnet.local</host>
<port>9440</port>
<user>default</user>
<password>ClickHouse123!</password>
<secure>1</secure>
</replica>
</shard>
</cluster_1S_2R>
</remote_servers>

使用 {uuid} 设置表的步骤

  1. 在每个服务器上配置宏,例如服务器 1 的示例
    <macros>
<shard>1</shard>
<replica>replica_1</replica>
</macros>
注意

请注意,我们为shardreplica定义了宏,但{uuid}在这里没有定义,它是内置的,不需要定义。

  1. 创建数据库
CREATE DATABASE db_uuid
ON CLUSTER 'cluster_1S_2R'
ENGINE Atomic;
CREATE DATABASE db_uuid ON CLUSTER cluster_1S_2R
ENGINE = Atomic

Query id: 07fb7e65-beb4-4c30-b3ef-bd303e5c42b5

┌─host──────────────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ chnode2.marsnet.local │ 9440 │ 0 │ │ 1 │ 0 │
│ chnode1.marsnet.local │ 9440 │ 0 │ │ 0 │ 0 │
└───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘
  1. 使用宏和{uuid}在集群上创建表
CREATE TABLE db_uuid.uuid_table1 ON CLUSTER 'cluster_1S_2R'
(
id UInt64,
column1 String
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/db_uuid/{uuid}', '{replica}' )
ORDER BY (id);
CREATE TABLE db_uuid.uuid_table1 ON CLUSTER cluster_1S_2R
(
`id` UInt64,
`column1` String
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/db_uuid/{uuid}', '{replica}')
ORDER BY id

Query id: 8f542664-4548-4a02-bd2a-6f2c973d0dc4

┌─host──────────────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ chnode1.marsnet.local │ 9440 │ 0 │ │ 1 │ 0 │
│ chnode2.marsnet.local │ 9440 │ 0 │ │ 0 │ 0 │
└───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘
  1. 创建分布式表
create table db_uuid.dist_uuid_table1 on cluster 'cluster_1S_2R'
(
id UInt64,
column1 String
)
ENGINE = Distributed('cluster_1S_2R', 'db_uuid', 'uuid_table1' );
CREATE TABLE db_uuid.dist_uuid_table1 ON CLUSTER cluster_1S_2R
(
`id` UInt64,
`column1` String
)
ENGINE = Distributed('cluster_1S_2R', 'db_uuid', 'uuid_table1')

Query id: 3bc7f339-ab74-4c7d-a752-1ffe54219c0e

┌─host──────────────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ chnode2.marsnet.local │ 9440 │ 0 │ │ 1 │ 0 │
│ chnode1.marsnet.local │ 9440 │ 0 │ │ 0 │ 0 │
└───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘

测试

  1. 将数据插入第一个节点(例如chnode1
INSERT INTO db_uuid.uuid_table1
( id, column1)
VALUES
( 1, 'abc');
INSERT INTO db_uuid.uuid_table1 (id, column1) FORMAT Values

Query id: 0f178db7-50a6-48e2-9a1b-52ed14e6e0f9

Ok.

1 row in set. Elapsed: 0.033 sec.
  1. 将数据插入第二个节点(例如chnode2
INSERT INTO db_uuid.uuid_table1
( id, column1)
VALUES
( 2, 'def');
INSERT INTO db_uuid.uuid_table1 (id, column1) FORMAT Values

Query id: edc6f999-3e7d-40a0-8a29-3137e97e3607

Ok.

1 row in set. Elapsed: 0.529 sec.
  1. 使用分布式表查看记录
SELECT * FROM db_uuid.dist_uuid_table1;
SELECT *
FROM db_uuid.dist_uuid_table1

Query id: 6cbab449-9e7f-40fe-b8c2-62d46ba9f5c8

┌─id─┬─column1─┐
│ 1 │ abc │
└────┴─────────┘
┌─id─┬─column1─┐
│ 2 │ def │
└────┴─────────┘

2 rows in set. Elapsed: 0.007 sec.

替代方案

默认复制路径可以通过宏提前定义,并使用{uuid}

  1. 在每个节点上设置表的默认值
<default_replica_path>/clickhouse/tables/{shard}/db_uuid/{uuid}</default_replica_path>
<default_replica_name>{replica}</default_replica_name>
小贴士

如果节点用于特定数据库,您也可以在每个节点上定义宏{database}

  1. 创建没有显式参数的表
CREATE TABLE db_uuid.uuid_table1 ON CLUSTER 'cluster_1S_2R'
(
id UInt64,
column1 String
)
ENGINE = ReplicatedMergeTree
ORDER BY (id);
CREATE TABLE db_uuid.uuid_table1 ON CLUSTER cluster_1S_2R
(
`id` UInt64,
`column1` String
)
ENGINE = ReplicatedMergeTree
ORDER BY id

Query id: ab68cda9-ae41-4d6d-8d3b-20d8255774ee

┌─host──────────────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ chnode2.marsnet.local │ 9440 │ 0 │ │ 1 │ 0 │
│ chnode1.marsnet.local │ 9440 │ 0 │ │ 0 │ 0 │
└───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘

2 rows in set. Elapsed: 1.175 sec.
  1. 验证它是否使用了默认配置中使用的设置
SHOW CREATE TABLE db_uuid.uuid_table1;
SHOW CREATE TABLE db_uuid.uuid_table1

Query id: 5925ecce-a54f-47d8-9c3a-ad3257840c9e

┌─statement────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ CREATE TABLE db_uuid.uuid_table1
(
`id` UInt64,
`column1` String
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/db_uuid/{uuid}', '{replica}')
ORDER BY id
SETTINGS index_granularity = 8192 │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

1 row in set. Elapsed: 0.003 sec.

故障排除

获取表信息和 UUID 的示例命令

SELECT * FROM system.tables
WHERE database = 'db_uuid' AND name = 'uuid_table1';

获取上面表在 ZooKeeper 中的表信息和 UUID 的示例命令

SELECT * FROM system.zookeeper
WHERE path = '/clickhouse/tables/1/db_uuid/9e8a3cc2-0dec-4438-81a7-c3e63ce2a1cf/replicas';
注意

数据库必须是Atomic,如果从以前版本升级,default数据库可能是Ordinary类型。

检查:例如,

SELECT name, engine FROM system.databases WHERE name = 'db_uuid';
SELECT
name,
engine
FROM system.databases
WHERE name = 'db_uuid'

Query id: b047d459-a1d2-4016-bcf9-3e97e30e49c2

┌─name────┬─engine─┐
│ db_uuid │ Atomic │
└─────────┴────────┘

1 row in set. Elapsed: 0.004 sec.

ClickHouse Keeper 动态重新配置

注意

此页面不适用于 ClickHouse Cloud。 此处记录的过程在 ClickHouse Cloud 服务中是自动化的。

描述

如果keeper_server.enable_reconfiguration已打开,ClickHouse Keeper 部分支持 ZooKeeper reconfig 命令进行动态集群重新配置。

注意

如果此设置已关闭,您可以通过手动更改副本的raft_configuration部分来重新配置集群。 确保您在所有副本上编辑文件,因为只有领导者会应用更改。 或者,您可以通过任何兼容 ZooKeeper 的客户端发送reconfig查询。

虚拟节点/keeper/config包含以下格式的最后提交的集群配置

server.id = server_host:server_port[;server_type][;server_priority]
server.id2 = ...
...

示例

:) get /keeper/config
server.1=zoo1:9234;participant;1
server.2=zoo2:9234;participant;1
server.3=zoo3:9234;participant;1

您可以使用reconfig命令添加新服务器、删除现有服务器和更改现有服务器的优先级,以下是一些示例(使用clickhouse-keeper-client

# Add two new servers
reconfig add "server.5=localhost:123,server.6=localhost:234;learner"
# Remove two other servers
reconfig remove "3,4"
# Change existing server priority to 8
reconfig add "server.5=localhost:5123;participant;8"

以下是kazoo的示例

# Add two new servers, remove two other servers
reconfig(joining="server.5=localhost:123,server.6=localhost:234;learner", leaving="3,4")

# Change existing server priority to 8
reconfig(joining="server.5=localhost:5123;participant;8", leaving=None)

joining中的服务器应采用上面描述的服务器格式。 服务器条目应以逗号分隔。 在添加新服务器时,您可以省略server_priority(默认值为 1)和server_type(默认值为participant)。

如果要更改现有服务器的优先级,请将其添加到joining中,并使用目标优先级。 服务器主机、端口和类型必须与现有服务器配置相同。

服务器按joiningleaving中出现的顺序添加和删除。 joining中的所有更新将在leaving中的更新之前处理。

Keeper 重新配置实现中有一些注意事项

  • 只支持增量重新配置。 具有非空new_members的请求将被拒绝。

    ClickHouse Keeper 实现依赖于 NuRaft API 来动态更改成员资格。 NuRaft 有一种方法可以一次添加或删除单个服务器。 这意味着配置的每次更改(joining的每个部分,leaving的每个部分)都必须分别决定。 因此,没有批量重新配置可用,因为它对最终用户来说具有误导性。

    更改服务器类型(participant/learner)也不可能,因为它不受 NuRaft 支持,唯一的方法是删除和添加服务器,这同样具有误导性。

  • 您不能使用返回的znodestat值。

  • from_version字段未使用。 所有具有设置from_version的请求都会被拒绝。 这是因为/keeper/config是一个虚拟节点,这意味着它不存储在持久存储中,而是在每次请求时使用指定的节点配置动态生成。 此决定是为了不重复数据,因为 NuRaft 已经存储了此配置。

  • 与 ZooKeeper 不同,无法通过提交sync命令来等待集群重新配置。 新配置将最终应用,但没有时间保证。

  • reconfig命令可能会由于各种原因失败。 您可以检查集群的状态并查看更新是否已应用。

将单节点 Keeper 转换为集群

有时需要将实验性 Keeper 节点扩展为集群。 以下是如何逐步进行 3 节点集群的方案

  • 重要:新节点必须按批次添加,少于当前的仲裁节点数量,否则它们将在它们之间选举领导者。 在此示例中,一个一个地添加。
  • 现有的 Keeper 节点必须启用keeper_server.enable_reconfiguration配置参数。
  • 启动第二个节点,使用 Keeper 集群的完整新配置。
  • 启动后,使用reconfig将其添加到节点 1。
  • 现在,启动第三个节点并使用reconfig将其添加。
  • 通过在其中添加新的 Keeper 节点来更新clickhouse-server配置,然后重新启动它以应用更改。
  • 更新节点 1 的 Raft 配置,并可选择重新启动它。

为了对该过程充满信心,这里有一个沙盒存储库.

不支持的功能

虽然 ClickHouse Keeper 旨在与 ZooKeeper 完全兼容,但目前尚有一些功能未实现(尽管开发正在进行中)