本文档将指导您在 2 台服务器上手动搭建一个高可用的 ClickHouse 单分片、双副本集群,并集成 ClickHouse Keeper 作为协调服务。我们将涵盖从系统准备、软件安装、详细配置、参数优化到最终验证的完整流程。

1. 集群规划与架构

  • 集群模式:单分片(Shard 1)、双副本(Replica 2)

  • 服务器:

    • 172.21.204.200 (副本 1 + Keeper 节点 1)

    • 172.21.204.201 (副本 2 + Keeper 节点 2)

  • 协调服务:ClickHouse Keeper (集成于 clickhouse-server 内)

  • 网络访问:开启 0.0.0.0 监听,支持跨节点与远程访问

2. 系统环境准备

2.1. 设置主机名与 hosts 解析(两台服务器)

# 在 172.21.204.200 上执行
sudo hostnamectl set-hostname zb-yunweitest-mysql-204-200
sudo vim /etc/hosts

在 /etc/hosts 文件中添加:

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
172.21.204.200 zb-yunweitest-mysql-204-200
172.21.204.201 zb-yunweitest-mysql-204-201
# 在 172.21.204.201 上执行
sudo hostnamectl set-hostname zb-yunweitest-mysql-204-201
# 编辑 /etc/hosts,添加相同内容

2.2. 关闭 SELinux(可选,生产环境请按需配置)

# 临时关闭
sudo setenforce 0

# 永久关闭(需要重启)
sudo vim /etc/selinux/config
# 修改为:SELINUX=disabled

2.3. 配置防火墙规则

# 在两台服务器上执行
# 开放 ClickHouse 及 Keeper 所需端口
sudo firewall-cmd --permanent --add-port=9000/tcp  # ClickHouse TCP 端口
sudo firewall-cmd --permanent --add-port=8123/tcp  # ClickHouse HTTP 端口
sudo firewall-cmd --permanent --add-port=9009/tcp  # ClickHouse 内部通信端口
sudo firewall-cmd --permanent --add-port=9181/tcp  # Keeper 客户端端口
sudo firewall-cmd --permanent --add-port=9234/tcp  # Keeper 内部通信端口
sudo firewall-cmd --reload

# 查看已开放端口
sudo firewall-cmd --list-all

2.4. 系统参数优化

# 调整文件描述符限制
echo "fs.file-max = 1000000" | sudo tee -a /etc/sysctl.conf
echo "vm.max_map_count = 262144" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

# 为 clickhouse 用户设置资源限制
sudo vim /etc/security/limits.d/clickhouse.conf

添加以下内容:

clickhouse soft nofile 262144
clickhouse hard nofile 262144
clickhouse soft nproc 131072
clickhouse hard nproc 131072

3. ClickHouse 软件安装

3.1. 下载安装包

请确保在两台服务器上准备好以下 RPM 包:

  • clickhouse-common-static-*.x86_64.rpm

  • clickhouse-server-*.x86_64.rpm

  • clickhouse-client-*.x86_64.rpm

注意:从 ClickHouse v23.8+ 开始,clickhouse-server 已包含 Keeper 功能,无需单独安装 clickhouse-keeper 包。

3.2. 安装 ClickHouse

# 在两台服务器上执行
cd /path/to/clickhouse-packages/

# 按顺序安装
sudo rpm -ivh clickhouse-common-static-*.x86_64.rpm
sudo rpm -ivh clickhouse-server-*.x86_64.rpm
sudo rpm -ivh clickhouse-client-*.x86_64.rpm

安装过程中会提示设置 default 用户密码,直接回车设置为空密码。

3.3. 创建必要目录并设置权限

# 创建 Keeper 数据目录
sudo mkdir -p /var/lib/clickhouse/coordination/{log,snapshots}

# 调整数据目录(如果使用自定义路径,比如 /data/clickhouse/)
sudo mkdir -p /data/clickhouse/
sudo chown -R clickhouse:clickhouse /data/clickhouse/

# 设置目录权限
sudo chown -R clickhouse:clickhouse /var/lib/clickhouse/
sudo chmod -R 755 /var/lib/clickhouse/

4. ClickHouse 服务配置

4.1. 主配置文件 /etc/clickhouse-server/config.xml

这是最关键的部分,确保 Keeper 和 ClickHouse 都监听 0.0.0.0

<?xml version="1.0"?>
<clickhouse>
    <!-- ========== 日志配置 ========== -->
    <logger>
        <level>information</level>
        <log>/var/log/clickhouse-server/clickhouse-server.log</log>
        <errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog>
        <size>1000M</size>
        <count>10</count>
    </logger>

    <!-- ========== 网络监听配置 ========== -->
    <!-- 关键:开启 0.0.0.0 监听,支持远程访问 -->
    <listen_host>0.0.0.0</listen_host>
    <listen_host>::</listen_host>

    <!-- 注释掉默认的本地监听 -->
    <!-- <listen_host>::1</listen_host> -->
    <!-- <listen_host>127.0.0.1</listen_host> -->

    <!-- 服务器间通信的主机名 -->
    <interserver_http_host>172.21.204.200</interserver_http_host>
    <!-- 注意:在 201 服务器上改为 172.21.204.201 -->

    <!-- ========== 端口配置 ========== -->
    <tcp_port>9000</tcp_port>
    <http_port>8123</http_port>
    <mysql_port>9004</mysql_port>
    <postgresql_port>9005</postgresql_port>
    <interserver_http_port>9009</interserver_http_port>

    <!-- ========== Keeper 配置 ========== -->
    <!-- 关键:Keeper 也必须监听 0.0.0.0 -->
    <keeper_server>
        <tcp_port>9181</tcp_port>
        
        <!-- 关键:Keeper 监听所有网络接口 -->
        <listen_host>0.0.0.0</listen_host>
        <listen_host>::</listen_host>
        
        <!-- 服务器ID,每台必须唯一 -->
        <server_id>1</server_id>
        <!-- 注意:在 201 服务器上改为 <server_id>2</server_id> -->
        
        <!-- 日志存储路径 -->
        <log_storage_path>/var/lib/clickhouse/coordination/log</log_storage_path>
        <snapshot_storage_path>/var/lib/clickhouse/coordination/snapshots</snapshot_storage_path>
        
        <!-- Raft 配置 - 定义两个 Keeper 节点 -->
        <raft_configuration>
            <server>
                <id>1</id>
                <hostname>172.21.204.200</hostname>
                <port>9234</port>
            </server>
            <server>
                <id>2</id>
                <hostname>172.21.204.201</hostname>
                <port>9234</port>
            </server>
        </raft_configuration>
        
        <!-- Keeper 协调设置 -->
        <coordination_settings>
            <operation_timeout_ms>10000</operation_timeout_ms>
            <session_timeout_ms>30000</session_timeout_ms>
            <raft_logs_level>information</raft_logs_level>
            <rotate_log_storage_interval>100000</rotate_log_storage_interval>
        </coordination_settings>
    </keeper_server>

    <!-- ========== 性能优化参数 ========== -->
    <max_connections>4096</max_connections>
    <keep_alive_timeout>3</keep_alive_timeout>
    <max_concurrent_queries>100</max_concurrent_queries>
    <uncompressed_cache_size>8589934592</uncompressed_cache_size> <!-- 8GB -->
    <mark_cache_size>5368709120</mark_cache_size> <!-- 5GB -->
    
    <!-- 内存相关优化 -->
    <max_server_memory_usage>0</max_server_memory_usage>
    <max_server_memory_usage_to_ram_ratio>0.9</max_server_memory_usage_to_ram_ratio>
    
    <!-- 数据目录 -->
    <path>/data/clickhouse/</path> <!-- 或使用默认 /var/lib/clickhouse/ -->
    <tmp_path>/var/lib/clickhouse/tmp/</tmp_path>
    <user_files_path>/var/lib/clickhouse/user_files/</user_files_path>
    
    <!-- 用户目录配置 -->
    <user_directories>
        <users_xml>
            <path>users.xml</path>
        </users_xml>
        <local_directory>
            <path>/var/lib/clickhouse/access/</path>
        </local_directory>
    </user_directories>
    
    <!-- 默认设置 -->
    <default_profile>default</default_profile>
    <default_database>default</default_database>
    
    <!-- 分布式DDL配置 -->
    <distributed_ddl>
        <path>/clickhouse/task_queue/ddl</path>
    </distributed_ddl>

    <!-- 查询缓存(可选) -->
    <query_cache>
        <max_size_in_bytes>1073741824</max_size_in_bytes> <!-- 1GB -->
        <max_entries>1024</max_entries>
        <max_entry_size_in_bytes>1048576</max_entry_size_in_bytes>
        <max_entry_size_in_rows>30000000</max_entry_size_in_rows>
    </query_cache>
</clickhouse>

重要:在 172.21.204.201 服务器上需要修改两个地方:

  1. <interserver_http_host>:改为 172.21.204.201

  2. <keeper_server> 中的 <server_id>:改为 2

4.2. 集群配置文件 /etc/clickhouse-server/config.d/metrika.xml

创建集群配置文件(两台服务器内容相同):

sudo vim /etc/clickhouse-server/config.d/metrika.xml
<?xml version="1.0"?>
<yandex>
    <!-- ========== 集群配置 ========== -->
    <remote_servers>
        <!-- 集群名称:cluster_1s2r (1个分片2个副本) -->
        <cluster_1s2r>
            <!-- 分片 1 -->
            <shard>
                <!-- 内部复制:true 表示写入一个副本即可,会自动同步到其他副本 -->
                <internal_replication>true</internal_replication>
                <!-- 副本 1 -->
                <replica>
                    <host>172.21.204.200</host>
                    <port>9000</port>
                    <!-- 可选的优先级设置,值越小优先级越高 -->
                    <!-- <priority>1</priority> -->
                </replica>
                <!-- 副本 2 -->
                <replica>
                    <host>172.21.204.201</host>
                    <port>9000</port>
                    <!-- <priority>2</priority> -->
                </replica>
            </shard>
        </cluster_1s2r>
    </remote_servers>

    <!-- ========== Keeper/ZooKeeper 配置 ========== -->
    <!-- 注意:这里使用 Keeper 的客户端端口 9181 -->
    <zookeeper>
        <node index="1">
            <host>172.21.204.200</host>
            <port>9181</port>
        </node>
        <node index="2">
            <host>172.21.204.201</host>
            <port>9181</port>
        </node>
        <!-- 会话超时设置 -->
        <session_timeout_ms>30000</session_timeout_ms>
        <operation_timeout_ms>10000</operation_timeout_ms>
        <!-- 连接断开时自动重连 -->
        <enable_address_replication>true</enable_address_replication>
    </zookeeper>

    <!-- ========== 宏配置 ========== -->
    <!-- 注意:这部分每台服务器必须不同 -->
    <macros>
        <cluster>cluster_1s2r</cluster>
        <shard>1</shard>
        <replica>replica_200</replica>
    </macros>
    <!-- 在 172.21.204.201 上改为:<replica>replica_201</replica> -->
</yandex>

4.3. 用户配置文件 /etc/clickhouse-server/users.xml

<?xml version="1.0"?>
<yandex>
    <!-- 用户配置 -->
    <users>
        <default>
            <!-- 密码:留空表示无密码,生产环境请设置强密码 -->
            <password></password>
            
            <!-- 网络访问控制:允许所有IP访问 -->
            <networks>
                <ip>::/0</ip>
            </networks>
            
            <!-- 用户配置文件和配额 -->
            <profile>default</profile>
            <quota>default</quota>
            
            <!-- 允许通过HTTP进行DDL/DML查询 -->
            <allow_ddl>1</allow_ddl>
        </default>
    </users>

    <!-- 配置profile -->
    <profiles>
        <default>
            <!-- 最大内存使用 -->
            <max_memory_usage>10000000000</max_memory_usage>
            <max_memory_usage_for_user>20000000000</max_memory_usage_for_user>
            
            <!-- 查询相关设置 -->
            <max_execution_time>300</max_execution_time>
            <max_rows_to_read>1000000000</max_rows_to_read>
            <max_bytes_to_read>100000000000</max_bytes_to_read>
            
            <!-- 是否记录查询日志 -->
            <log_queries>1</log_queries>
            
            <!-- 连接设置 -->
            <connect_timeout_with_failover_ms>1000</connect_timeout_with_failover_ms>
            <connect_timeout_with_failover_secure_ms>1000</connect_timeout_with_failover_secure_ms>
        </default>
        
        <!-- 可添加只读用户profile -->
        <readonly>
            <readonly>1</readonly>
        </readonly>
    </profiles>

    <!-- 配额配置 -->
    <quotas>
        <default>
            <interval>
                <duration>3600</duration>
                <queries>0</queries>
                <errors>0</errors>
                <result_rows>0</result_rows>
                <read_rows>0</read_rows>
                <execution_time>0</execution_time>
            </interval>
        </default>
    </quotas>
</yandex>

5. 启动与验证服务

5.1. 启动 ClickHouse 服务

# 在两台服务器上都执行
sudo systemctl daemon-reload
sudo systemctl start clickhouse-server
sudo systemctl enable clickhouse-server

# 检查服务状态
sudo systemctl status clickhouse-server

5.2. 验证网络监听

# 检查所有相关端口是否监听在 0.0.0.0 或 ::
sudo netstat -tlnp | grep clickhouse

# 预期输出应该包含:
# tcp   0  0 0.0.0.0:9000    0.0.0.0:*    LISTEN
# tcp   0  0 0.0.0.0:8123    0.0.0.0:*    LISTEN  
# tcp   0  0 0.0.0.0:9181    0.0.0.0:*    LISTEN
# tcp6  0  0 :::9009         :::*         LISTEN
# tcp6  0  0 :::9234         :::*         LISTEN

5.3. 测试 Keeper 连通性

# 在 200 服务器上测试连接 201 的 Keeper
telnet 172.21.204.201 9181
# 输入 stat 查看状态,然后按 Ctrl+] 退出

# 在 201 服务器上测试连接 200 的 Keeper
telnet 172.21.204.200 9181

# 或者使用 echo 命令(如果 nc 可用)
echo "stat" | nc 172.21.204.200 9181
echo "stat" | nc 172.21.204.201 9181

5.4. 验证 ClickHouse 集群

# 连接到任意节点
clickhouse-client

-- 1. 查看集群配置
SELECT * FROM system.clusters WHERE cluster='cluster_1s2r';

-- 2. 查看 Keeper 状态
SELECT * FROM system.zookeeper WHERE path = '/';

-- 3. 测试分布式DDL(在集群上创建数据库)
CREATE DATABASE test_cluster ON CLUSTER cluster_1s2r;

-- 4. 查看所有数据库
SHOW DATABASES;

-- 5. 创建复制表
CREATE TABLE test_cluster.test_replicated ON CLUSTER cluster_1s2r
(
    id Int32,
    name String,
    event_time DateTime
) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/test_replicated', '{replica}')
PARTITION BY toYYYYMM(event_time)
ORDER BY (id)
SETTINGS index_granularity = 8192;

-- 6. 插入测试数据(在任一节点执行)
INSERT INTO test_cluster.test_replicated VALUES 
(1, 'test_data_1', now()),
(2, 'test_data_2', now());

-- 7. 查询数据(在另一节点验证)
SELECT * FROM test_cluster.test_replicated ORDER BY id;

6. 集群管理与监控

6.1. 常用管理命令

# 查看集群中的表状态
clickhouse-client --query "SELECT database, name, engine, is_temporary, 
    data_paths, metadata_path, partition_key, sorting_key 
    FROM system.tables WHERE database NOT IN ('system')"

# 查看副本状态
clickhouse-client --query "SELECT database, table, is_leader, 
    is_readonly, is_session_expired, future_parts, 
    parts_to_check, columns_version, replica_path 
    FROM system.replicas"

# 查看正在执行的查询
clickhouse-client --query "SELECT query_id, user, address, query_start_time, 
    query_duration_ms, read_rows, written_rows, memory_usage 
    FROM system.processes"

6.2. 监控脚本示例

创建监控脚本 /opt/clickhouse-monitor.sh

#!/bin/bash

# ClickHouse 集群健康检查脚本
HOSTS=("172.21.204.200" "172.21.204.201")

echo "=== ClickHouse 集群健康检查 ==="
echo "检查时间: $(date)"
echo ""

for host in "${HOSTS[@]}"; do
    echo "检查节点: $host"
    echo "-------------------"
    
    # 检查服务状态
    ssh $host "systemctl is-active clickhouse-server"
    
    # 检查端口
    echo "端口监听状态:"
    ssh $host "netstat -tln | grep -E ':(9000|8123|9181|9009)'"
    
    # 检查连接数
    echo "连接数统计:"
    ssh $host "clickhouse-client --host localhost --query \"SELECT count() FROM system.processes\" 2>/dev/null || echo '无法连接'"
    
    echo ""
done

# 检查 Keeper 集群状态
echo "=== Keeper 集群状态 ==="
for host in "${HOSTS[@]}"; do
    echo "节点 $host 的 Keeper 状态:"
    echo "stat" | timeout 5 nc $host 9181 2>/dev/null | grep -E "(Mode|Node count|Connections)" || echo "无法连接"
    echo ""
done

7. 故障排查指南

7.1. 常见问题及解决方案

 
问题可能原因解决方案
Keeper 无法连接 1. 监听地址配置错误
2. 防火墙阻止
3. SELinux 限制
1. 检查 listen_host 配置
2. 检查防火墙规则
3. 临时禁用 SELinux 测试
分布式 DDL 失败 1. Keeper 未启动
2. 集群配置错误
3. 网络不通
1. 检查 Keeper 状态
2. 验证 metrika.xml 配置
3. 测试节点间网络
复制表不同步 1. 副本配置错误
2. ZK 路径冲突
3. 网络延迟
1. 检查 macros 配置
2. 检查 ZK 路径唯一性
3. 检查网络连接
内存不足 1. 配置限制过低
2. 查询消耗过大
1. 调整内存相关参数
2. 优化查询语句

7.2. 重要日志文件

# 服务日志
/var/log/clickhouse-server/clickhouse-server.log
/var/log/clickhouse-server/clickhouse-server.err.log

# Keeper 相关日志(在主日志中)
grep -i keeper /var/log/clickhouse-server/clickhouse-server.log

# 查询日志
clickhouse-client --query "SELECT * FROM system.query_log WHERE event_date = today() LIMIT 5"

8. 安全建议

8.1. 生产环境安全配置

<!-- 在 users.xml 中添加安全配置 -->
<users>
    <default>
        <!-- 设置强密码 -->
        <password_sha256_hex>您的密码SHA256哈希值</password_sha256_hex>
        
        <!-- 限制访问IP -->
        <networks>
            <ip>172.21.204.0/24</ip>  <!-- 只允许内网访问 -->
            <ip>127.0.0.1</ip>
            <ip>::1</ip>
        </networks>
    </default>
    
    <!-- 创建只读监控用户 -->
    <monitor>
        <password>监控密码</password>
        <networks>
            <ip>监控服务器IP</ip>
        </networks>
        <profile>readonly</profile>
        <quota>default</quota>
    </monitor>
</users>

8.2. 启用 SSL/TLS(可选)

<!-- 在 config.xml 中启用 HTTPS -->
<https_port>8443</https_port>
<openSSL>
    <server>
        <certificateFile>/etc/clickhouse-server/server.crt</certificateFile>
        <privateKeyFile>/etc/clickhouse-server/server.key</privateKeyFile>
        <verificationMode>none</verificationMode>
    </server>
</openSSL>

9. 性能优化建议

9.1. 根据硬件调整配置

<!-- 根据内存大小调整缓存 -->
<!-- 如果服务器有 32GB 内存: -->
<max_server_memory_usage>25769803776</max_server_memory_usage> <!-- 24GB -->
<max_server_memory_usage_to_ram_ratio>0.75</max_server_memory_usage_to_ram_ratio>

<!-- 调整后台处理线程数 -->
<background_pool_size>16</background_pool_size>
<background_schedule_pool_size>16</background_schedule_pool_size>

9.2. 表引擎优化

-- 创建优化后的复制表
CREATE TABLE optimized_table ON CLUSTER cluster_1s2r
(
    id UInt64,
    timestamp DateTime,
    value Float64,
    tag String
) ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/{shard}/optimized_table', '{replica}')
PARTITION BY toYYYYMM(timestamp)
ORDER BY (tag, timestamp)
SETTINGS 
    index_granularity = 8192,
    use_minimalistic_part_header_in_zookeeper = 1,  -- 减少 ZK 负载
    merge_with_ttl_timeout = 86400;  -- TTL 合并超时

10. 总结

通过以上步骤,您已经成功搭建了一个高可用的 ClickHouse 单分片双副本集群。关键点总结:

  1. 网络配置:确保 listen_host 设置为 0.0.0.0,允许跨节点通信

  2. Keeper 配置:正确配置 server_id 和 raft_configuration

  3. 集群配置:统一 metrika.xml,区分 macros 配置

  4. 安全考虑:生产环境务必设置密码和网络访问控制

  5. 监控维护:建立定期监控和备份机制

此配置适合中小规模的生产环境,如需扩展到更多节点,只需调整 Keeper 配置为 3 节点或 5 节点,并相应增加集群分片配置即可。

 posted on 2025-12-16 17:01  xibuhaohao  阅读(83)  评论(0)    收藏  举报