clickhouse运维篇(三):生产环境一键生成配置并快速部署ck集群

请添加图片描述

前提条件:先了解集群搭建流程是什么样,需要改哪些配置,有哪些环境,这个文章目的是简化部署。

clickhouse运维篇(一):docker-compose 快速部署clickhouse集群
clickhouse运维篇(二):多机器手动部署ck集群

!https://i-blog.csdnimg.cn/direct/7677be0676904a7687c2f4cc8aef0a46.png

项目目录解析:

 $ tree .
.
├── cluster.conf   #集群配置,  集群包含哪些机器、端口分别为多少
├── config  
│   ├── config_node1.xml  # 生成的ck节点配置文件
│   ├── config_node2.xml
│   ├── config_template.xml  # config模版
│   ├── users_node1.xml     # 生成的ck节点用户配置文件
│   ├── users_node2.xml
│   └── users_template.xml   # users模版
├── dep   #下面包含需要的远程依赖, zookeeper、clickhouse、jdk,根据自己的需求更改
├── gen_cluster_config.sh  
├── gen_login_cmd.sh
├── install.conf  # 远程登录的主机conf,需要在跳板机或者中间机器上去ssh、scp使用
└── main.sh   #启动入口

1、main.sh

CUR_FOLDER=$(cd "/Users/admin/scripts/my_app/ckcluster";pwd). ${CUR_FOLDER}/cluster.conf
. ${CUR_FOLDER}/gen_cluster_config.sh
. ${CUR_FOLDER}/gen_login_cmd.shCONFIG_FOLDER="${CUR_FOLDER}/config"
DEP_FOLDER="${CUR_FOLDER}/dep"
TEMPLATE_FILE="${CONFIG_FOLDER}/config_template.xml"if [ ! -d "$CONFIG_FOLDER" ]; thenmkdir -p "$CONFIG_FOLDER"
fiif [ ! -d "$DEP_FOLDER" ]; thenmkdir -p "$DEP_FOLDER"
fizk_index=1
# 首先读取所有节点信息并根据 shard 进行分组
while true; dohost_var="zk_node_${zk_index}_host"# 检查所有变量是否为空,若有一个为空则跳出循环if [ -z "${!host_var}" ]; thenbreakfi# 远程安装jdk、zookeeperinstall_path=$(get_install_path ${!host_var})echo $(get_scp_command ${!host_var} . "${DEP_FOLDER}/jdk-8u202-nonroot.tar.gz ${DEP_FOLDER}/apache-zookeeper-3.7.2-bin.tar.gz")`get_scp_command ${!host_var} . "${DEP_FOLDER}/jdk-8u202-nonroot.tar.gz ${DEP_FOLDER}/apache-zookeeper-3.7.2-bin.tar.gz"`echo $(get_ssh_command ${!host_var} "cd ${install_path};tar -xzvf ${install_path}/jdk-8u202-nonroot.tar.gz")echo $(get_ssh_command ${!host_var} "cd ${install_path};tar -xzvf ${install_path}/apache-zookeeper-3.7.2-bin.tar.gz")`get_ssh_command ${!host_var} "cd ${install_path};tar -xzvf ${install_path}/jdk-8u202-nonroot.tar.gz"``get_ssh_command ${!host_var} "cd ${install_path};tar -xzvf ${install_path}/apache-zookeeper-3.7.2-bin.tar.gz"`zk_index=$((zk_index + 1))
done# 生成ck集群配置文件
gen_config# 远程安装clickhouse
ck_index=1
# 首先读取所有节点信息并根据 shard 进行分组
while true; dohost_var="ck_node_${ck_index}_host"# 检查所有变量是否为空,若有一个为空则跳出循环if [ -z "${!host_var}" ]; thenbreakfi
#     <users_config>/opt/appaduudit/my_app-2.4/clickhouse-23.4.2.9/ck_node_1/config/users_node.xml</users_config>    install_path=$(get_install_path ${!host_var})    `get_scp_command ${!host_var} . "${DEP_FOLDER}/clickhouse-23.4.2.9.tar.gz"`echo $(get_ssh_command ${!host_var} "cd ${install_path};tar -xzvf ${install_path}/clickhouse-23.4.2.9.tar.gz")NODE_CK_PATH="${BASE_CK_PATH}/ck_node_${ck_index}"echo $(get_scp_command ${!host_var} ${NODE_CK_PATH}/config  "${CONFIG_FOLDER}/user_node${ck_index}.xml")`get_scp_command ${!host_var} ${NODE_CK_PATH}/config "${CONFIG_FOLDER}/config_node${ck_index}.xml"``get_scp_command ${!host_var} ${NODE_CK_PATH}/config  "${CONFIG_FOLDER}/users_node${ck_index}.xml"`echo $(get_ssh_command ${!host_var} "${install_path}/clickhouse-23.4.2.9.tar.gz/bin/clickhouse server --config-file  ${install_path}/config_node${ck_index}.xml")`get_ssh_command ${!host_var} "${install_path}/clickhouse-23.4.2.9.tar.gz/bin/clickhouse server --config-file  ${install_path}/config_node${ck_index}.xml"`    ck_index=$((ck_index + 1))
done

2、cluster.conf

# 定义变量
target_install_path="/opt/app/ck_cluster"
BASE_CK_PATH="/opt/app/my_app-2.4/clickhouse-23.4.2.9"
CK_CLUSTER_NAME="my_ck_cluster_test"#port为zk的clientPort
zk_node_1_host=172.168.1.206
zk_node_1_port=8551zk_node_2_host=172.168.1.207
zk_node_2_port=8551zk_node_3_host=172.168.1.208
zk_node_3_port=8551ck_node_1_host=172.168.1.206
ck_node_1_tcp_port=8601
ck_node_1_http_port=8602
ck_node_1_interserver_http_port=8603
ck_node_1_user=default
ck_node_1_password=password
ck_node_1_shard=01
ck_node_1_replica=replica_63ck_node_2_host=172.168.1.207
ck_node_2_tcp_port=8611
ck_node_2_http_port=8612
ck_node_2_interserver_http_port=8613
ck_node_2_user=default
ck_node_2_password=password
ck_node_2_shard=02
ck_node_2_replica=replica_63#ck_node_3_host=ck_host_3
#ck_node_3_tcp_port=ck_tcp_port_3
#ck_node_3_http_port=ck_http_port_3
#ck_node_3_interserver_http_port=ck_interserver_http_port_3
#ck_node_3_user=user3
#ck_node_3_password=password3
#ck_node_3_shard=02
#ck_node_3_replica=replica_209

3、install.conf

ssh.172.168.1.206=root:app:/opt/app/ck_cluste
ssh.172.168.1.207=admin:adminpass:/opt/app/ck_cluste
ssh.172.168.1.208=admin:adminpass:/opt/app/ck_cluste

4、gen_login_cmd.sh

#!/bin/bash
cd /Users/admin/scripts/my_app/ckcluster
# 读取配置文件并解析
CONFIG_FILE="install.conf"
declare -A HOSTSwhile IFS='=' read -r key user_password || [[ -n "$key" ]]; dokey=$(echo "$key" | xargs)user_password=$(echo "$user_password" | xargs)if [[ $key == ssh.* ]]; thenhost=${key#ssh.}HOSTS["$host"]="$user_password"fi
done < "$CONFIG_FILE"# 获取 SSH 命令
get_ssh_command() {local host=$1local cmd=$2local user_password=${HOSTS["$host"]}IFS=':' read -r user password install_path<<< "$user_password"# echo "sshpass -p '$password' ssh $user@$host $cmd"echo "sshpass -p '$password' ssh $user@$host \"$cmd\""}# 获取 SCP 命令
get_scp_command() {local host=$1local extra_dir=$2local files=$3    local user_password=${HOSTS[$host]}# root:idss:/opt/idss/ck_clusteIFS=':' read -r user password install_path<<< "$user_password"if [ "$extra_dir" != "." ]; theninstall_path=$extra_dirfimkdir_cmd=$(get_ssh_command $host "mkdir -p $install_path")eval "$mkdir_cmd"echo "sshpass -p '$password' scp -r $files $user@$host:$install_path"
}get_install_path() {local host=$1local user_password=${HOSTS[$host]}# root:idss:/opt/idss/ck_clusteIFS=':' read -r user password install_path<<< "$user_password"echo $install_path
}
# ssh_command=$(get_scp_command "10.87.102.206" "/Users/admin/scripts/my_app/ckcluster/dep/jdk-8u202-nonroot.tar.gz /Users/admin/scripts/my_app/ckcluster/dep/apache-zookeeper-3.7.2-bin.tar.gz")
# echo $ssh_command
# scp_command=$(get_ssh_command "10.87.102.206" "ls /opt/idss/ck_cluste")
# echo $scp_command
# `$scp_command`

5、gen_cluster_config.sh

#!/bin/bash
# 定义基础路径和模板文件名function gen_config() {# 生成 zookeeper 配置
ZOOKEEPER_CONFIG="<zookeeper>\n"
# 循环遍历 zk_node_*_host 和 zk_node_*_port 变量
zk_index=1
while true; dohost_var="zk_node_${zk_index}_host"port_var="zk_node_${zk_index}_port"# 检查变量是否已定义,如果未定义则跳出循环if [ -z "${!host_var}" ] || [ -z "${!port_var}" ]; thenbreakfiZOOKEEPER_CONFIG+="    <node index=\"${zk_index}\">\n"ZOOKEEPER_CONFIG+="        <host>${!host_var}</host>\n"ZOOKEEPER_CONFIG+="        <port>${!port_var}</port>\n"ZOOKEEPER_CONFIG+="    </node>\n"zk_index=$((zk_index + 1))
done
ZOOKEEPER_CONFIG+="</zookeeper>"# 生成 remote_servers 配置
declare -A shard_nodes config_contentck_index=1
# 首先读取所有节点信息并根据 shard 进行分组
while true; dohost_var="ck_node_${ck_index}_host"tcp_port_var="ck_node_${ck_index}_tcp_port"http_port_var="ck_node_${ck_index}_http_port"interserver_port_var="ck_node_${ck_index}_interserver_http_port"user_var="ck_node_${ck_index}_user"password_var="ck_node_${ck_index}_password"shard_var="ck_node_${ck_index}_shard"replica_var="ck_node_${ck_index}_replica"# 检查所有变量是否为空,若有一个为空则跳出循环if [ -z "${!host_var}" ] || \[ -z "${!tcp_port_var}" ] || \[ -z "${!http_port_var}" ] || \[ -z "${!interserver_port_var}" ] || \[ -z "${!user_var}" ] || \[ -z "${!password_var}" ] || \[ -z "${!shard_var}" ] || \[ -z "${!replica_var}" ]; thenbreakfi# 将当前节点信息存入以 shard 为 key 的数组shard_nodes["${!shard_var}"]+=$(cat <<-NODE<replica><host>${!host_var}</host><port>${!tcp_port_var}</port><user>${!user_var}</user><password>${!password_var}</password></replica>\n
NODE)NODE_CK_PATH="${BASE_CK_PATH}/ck_node_${ck_index}"config_template=$(cat ${CONFIG_FOLDER}/config_template.xml)config_template=$(echo "$config_template" | sed "s|\${BASE_CK_PATH}|${NODE_CK_PATH}|g")config_template=$(echo "$config_template" | sed "s|\${HTTP_PORT}|${!http_port_var}|g")config_template=$(echo "$config_template" | sed "s|\${TCP_PORT}|${!tcp_port_var}|g")config_template=$(echo "$config_template" | sed "s|\${INTERSERVER_HTTP_PORT}|${!interserver_port_var}|g")config_template=$(echo "$config_template" | sed "s|\${MACROS_SHARD}|${!shard_var}|g")config_template=$(echo "$config_template" | sed "s|\${MACROS_REPLICA}|${!replica_var}|g")config_template=$(echo "$config_template" | sed "s|\${CK_PASSWORD}|${!password_var}|g")    config_template=$(echo "$config_template" | sed "s|\${ck_index}|${!ck_index}|g")        # 将生成的配置内容存入字典config_content["config_node${ck_index}"]="$config_template"# users文件生成users_template=$(cat ${CONFIG_FOLDER}/users_template.xml)users_template=$(echo "$users_template" | sed "s|\${CK_PASSWORD}|${!password_var}|g")    echo -e "$users_template" > "${CONFIG_FOLDER}/users_node${ck_index}.xml"ck_index=$((ck_index + 1))
done# 构建最终的 XML 配置
REMOTE_SERVERS_CONFIG="<remote_servers>\n"
REMOTE_SERVERS_CONFIG+="    <${CK_CLUSTER_NAME}>\n"
for shard in "${!shard_nodes[@]}"; doREMOTE_SERVERS_CONFIG+="        <shard>\n"REMOTE_SERVERS_CONFIG+="            <internal_replication>true</internal_replication>  \n"REMOTE_SERVERS_CONFIG+="${shard_nodes[$shard]}"REMOTE_SERVERS_CONFIG+="        </shard>\n"
done
REMOTE_SERVERS_CONFIG+="    </${CK_CLUSTER_NAME}>\n"
REMOTE_SERVERS_CONFIG+="</remote_servers>"# 动态修改配置文件(插入 Zookeeper\CK集群 配置)
for node_config in "${!config_content[@]}"; doecho "处理 $node_config ..."# 创建临时文件temp_file="${node_config}_tmp.xml"echo -e "${config_content[$node_config]}" > "$temp_file"sed -i '' '/<\/yandex>/d' "$temp_file"# linux下为# sed -i '/<\/yandex>/d' "$temp_file"    # 拼接 Zookeeper 和 Remote Servers 配置combined_insert="${ZOOKEEPER_CONFIG}
${REMOTE_SERVERS_CONFIG}"echo -e "$combined_insert" >> "$temp_file"echo "</yandex>" >> "$temp_file"mv "$temp_file" "$CONFIG_FOLDER/${node_config}.xml"echo "生成 $node_config 完成: ${node_config}.xml"
done}

6、config_template.xml

<?xml version="1.0"?>
<yandex><logger><level>notice</level><log>${BASE_CK_PATH}/log/clickhouse-server.log</log><errorlog>${BASE_CK_PATH}/log/clickhouse-server.err.log</errorlog><size>1000M</size><count>10</count></logger><path>${BASE_CK_PATH}/data/</path><tmp_path>${BASE_CK_PATH}/tmp/</tmp_path><user_files_path>${BASE_CK_PATH}/data/user_files/</user_files_path><users_config>${BASE_CK_PATH}/config/users_node${ck_index}.xml</users_config>    <users><default><password>${CK_PASSWORD}</password> <!-- 空密码 --><networks><ip>::/0</ip> <!-- 允许所有IP访问 --></networks><profile>default</profile><quota>default</quota><access_management>1</access_management></default></users>    <default_profile>default</default_profile><default_database>default</default_database><http><port>${HTTP_PORT}</port><max_connections>1024</max_connections><async_insert>1</async_insert></http><listen_host>0.0.0.0</listen_host><listen_host>::</listen_host><http_port>${HTTP_PORT}</http_port><tcp_port>${TCP_PORT}</tcp_port><interserver_http_port>${INTERSERVER_HTTP_PORT}</interserver_http_port><distributed_ddl><!-- Path in ZooKeeper to queue with DDL queries --><path>/clickhouse/task_queue/ddl</path></distributed_ddl><macros><shard>${MACROS_SHARD}</shard><replica>${MACROS_REPLICA}</replica></macros>
</yandex>

7、users_template.xml

<?xml version="1.0"?>
<yandex><!-- Profiles of settings. --><profiles><!-- Default settings. --><default><!-- Maximum memory usage for processing single query, in bytes. --><max_memory_usage>10000000000</max_memory_usage><load_balancing>random</load_balancing></default><!-- Profile that allows only read queries. --><readonly><readonly>1</readonly></readonly></profiles><users><default><password>${CK_PASSWORD}</password> <networks><ip>::/0</ip> <!-- 允许所有IP访问 --></networks><profile>default</profile><quota>default</quota><access_management>1</access_management></default></users>    <!-- Quotas. --><quotas><!-- Name of quota. --><default><!-- Limits for time interval. You could specify many intervals with different limits. --><interval><!-- Length of interval. --><duration>3600</duration><distributed_product_mode>allow</distributed_product_mode><!-- No limits. Just calculate resource usage for time interval. --><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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/464094.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【OpenGL】vs中glsl高亮显示插件

vs中glsl高亮显示插件 扩展搜索glsl安装

<项目代码>YOLOv8 猫狗识别<目标检测>

YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为一个回归问题&#xff0c;能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法&#xff08;如Faster R-CNN&#xff09;&#xff0c;YOLOv8具有更高的…

jmeter脚本-请求体设置变量and请求体太长的处理

目录 1、查询接口 1.1 准备组织列表的TXT文件&#xff0c;如下&#xff1a; 1.2 添加 CSV数据文件设置 &#xff0c;如下&#xff1a; 1.3 接口请求体设置变量&#xff0c;如下&#xff1a; 2、创建接口 2.1 见1.1 2.2 见1.2 2.3 准备创建接口的请求体TXT文件&#xff…

哔哩哔哩车机版2.7.0|专为司机打造的车机版B站,内容丰富,功能齐全

哔哩哔哩车机版是一款专为司机朋友们打造的车机版应用&#xff0c;扫码登录即可使用。该软件让你通过耳朵了解最新的游戏、动画动漫信息&#xff0c;感受其独特的趣味性内容。车机版亮点包括二次元和三次元的鬼畜视频、原创和翻唱音乐、前沿科技科普、国内外优秀舞蹈作品等。软…

在Mac下安装时间序列软件Hector

1.软件介绍 Hector 是一款开源软件&#xff0c;专用于 GNSS 时间序列数据的处理与分析&#xff0c;广泛应用于地球科学研究。它帮助研究人员从 GNSS 数据中提取长期趋势、周期性成分&#xff0c;并建模噪声特性&#xff0c;用于地壳形变、地震影响和气候变化等方面的研究。Hec…

opencv python笔记

OpenCV课程 OpenCV其实就是一堆C和C语言的源代码文件,这些源代码文件中实现了许多常用的计算机视觉算法。 OpenCV的全称是Open Source Computer Vision Library,是一个开放源代码的计算机视觉库OpenCV最初由英特尔公司发起并开发,以BSD许可证授权发行,可以在商业和研究领域中…

Rust 力扣 - 2461. 长度为 K 子数组中的最大和

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 我们遍历长度为k的窗口&#xff0c;用一个哈希表记录窗口内的所有元素&#xff08;用来对窗口内元素去重&#xff09;&#xff0c;我们取哈希表中元素数量等于k的窗口总和的最大值 题解代码 use std::collecti…

[实战-11] FlinkSql 设置时区对TIMESTAMP和TIMESTAMP_LTZ的影响

table.local-time-zone table.local-time-zoneDataStream-to-Table Conversion&#xff08;拓展知识&#xff09;代码测试flinksql代码执行结果截图1. Asia/Shanghai 结果如下2. UTC结果如下 table.local-time-zone table.local-time-zone可用于设置flinksql的时区。 flink的内…

rnn/lstm 项目实战

tip:本项目用到的数据和代码在https://pan.baidu.com/s/1Cw6OSSWJevSv7T1ouk4B6Q?pwdz6w2 1. RNN : 预测股价 任务&#xff1a;基于zgpa_train.csv数据,建立RNN模型,预测股价 1.完成数据预处理&#xff0c;将序列数据转化为可用于RNN输入的数据 2.对新数据zgpa_test.csv进…

MySQL超大分页怎么优化处理?limit 1000000,10 和 limit 10区别?覆盖索引、面试题

1. limit 100000,10 和 limit 10区别 LIMIT 100000, 10&#xff1a; 这个语句的意思是&#xff0c;从查询结果中跳过前100000条记录&#xff0c;然后返回接下来的10条记录。这通常用于分页查询中&#xff0c;当你需要跳过大量的记录以获取后续的记录时。例如&#xff0c;如果你…

规范:项目、目录、文件、样式、事件、变量、方法、url参数、注释、git提交 命名规范及考证

一、规范命名的重要性 易懂、通用、规范、标准、专业性、是经验积累的体现 1.1、常见命名方法 序号命名方法解释1全小写2全大写3驼峰&#xff1a;小驼峰命名法4驼峰&#xff1a;大驼峰命名法5烤串命名法 / 脊柱命名法6下划线分隔法 二、项目名 采用小写字母和中划线&#…

NumPy Ndarray学习

1.NumPy Ndarray 对象简介 NumPy 最重要的特点是其 N 维数组对象 ndarray&#xff0c;它是一系列同类型数据的集合&#xff0c;以 0 下标为开始进行集合中元素的索引。ndarray 对象是用于存放同类型元素的多维数组。ndarray 中的每个元素在内存中都有相同存储大小的区域。 2.N…

二:MySQL基础---查询专项练习

目录 表结构 1. 数据月表&#xff08;zbr_data_monthly_data_YYYYMM&#xff09; 2. 分类表&#xff08;zbr_category&#xff09; 3. 用户表&#xff08;zbr_user&#xff09; 4. 交易表&#xff08;zbr_transaction&#xff09; 查询知识点 1. 基本查询 2. 连接查询 …

C++线程异步

本文内容来自&#xff1a; 智谱清言 《深入应用C11 代码优化与工程级应用》 std::future std::future作为异步结果的传输通道&#xff0c;可以很方便地获取线程函数的返回值。 std::future_status Ready (std::future_status::ready): 当与 std::future 对象关联的异步操作…

Python小游戏19——滑雪小游戏

运行效果 python代码 import pygame import random # 初始化Pygame pygame.init() # 设置屏幕尺寸 screen_width 800 screen_height 600 screen pygame.display.set_mode((screen_width, screen_height)) pygame.display.set_caption("滑雪小游戏") # 定义颜色 WH…

批量删除redis数据【亲测可用】

文章目录 引言I redis客户端基础操作key的命名规则批量查询keyII 批量删除key使用连接工具进行分组shell脚本示例其他方法III 知识扩展:控制短信验证码获取频率引言 批量删除redis数据的应用: 例如缓存数据使用了新的key存储,需要删除废弃的key。RedisTemplate的key序列化采…

04字符串算法/代码随想录

四、字符串 反转字符串 力扣344 遇到数组双指针真是太好用了&#xff0c;左右指针不断逼近即可&#xff0c;代码也很简单 class Solution {public void reverseString(char[] s) {int fast s.length - 1;int slow 0;while (slow < fast) {char temp s[fast];s[fast] s[…

conda找不到对应版本的pytorch,就会自动下载cpu版本的

踩坑一&#xff1a; conda install pytorch2.0.1 torchvision0.15.2 torchaudio2.0.2 pytorch-cuda11.7 -c pytorch -c nvidia (本人的服务器支持的 且python3.8.20) 先nvidia-smi查看自己cuda支持的最高版本&#xff0c;然后去pytorch官网寻找对应的torch、torchaudio、to…

信息学科平台设计与实现:Spring Boot技术详解

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

二、应用层,《计算机网络(自顶向下方法 第7版,James F.Kurose,Keith W.Ross)》

文章目录 零、前言一、应用层协议原理1.1 网络应用的体系结构1.1.1 客户-服务器(C/S)体系结构1.1.2 对等体&#xff08;P2P&#xff09;体系结构1.1.3 C/S 和 P2P体系结构的混合体 1.2 进程通信1.2.1 问题1&#xff1a;对进程进行编址&#xff08;addressing&#xff09;&#…