clickhouse集群部署和分布式引擎实战

1.认识clickhouse

ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS)

OLAP: Online AnalyticalProcessing联机分析处理系统

列式存储

2.单机部署

官方文档安装 | ClickHouse Docs

2.1.docker安装单机版

不使用副本表时可以不用zookeeper

当使用Replicated table时,ZooKeeper用于存储关于replica的元数据。

可选的。如果不使用复制表,可以忽略这一点。

参见 https://clickhouse.tech/docs/en/engines/table-engines/mergetree-family/replication/

docker安装

## 镜像:

yandex/clickhouse-server:latest 服务端
yandex/clickhouse-clientr:latest 客户端

## 启动服务端命令:
docker run \
  --restart always \
  --publish=8123:8123 --publish=9000:9000 --publish=9009:9009 \
  --volume=/data1/clickhouse/data:/var/lib/clickhouse:rw \
  --volume=/data1/clickhouse/log:/var/log/clickhouse-server:rw \
  --volume=/data1/clickhouse/config.xml:/etc/clickhouse-server/config.xml:rw \  
  --volume=/data1/clickhouse/users.xml:/etc/clickhouse-server/users.xml:rw \
  --name clickhouse-server \
  -d \
  yandex/clickhouse-server:latest

3.客户端测试

## 运行客户端实例:
docker run -it --rm \
  --link clickhouse-server:clickhouse-server yandex/clickhouse-client \
  --host clickhouse-server

进入命令操作

查询 default 库里的表
select name from system.tables where database='default'

建表 (直接复制)
create table aaa( \
id String,\
name String\
)\
ENGINE = MergeTree\
PARTITION BY name \
ORDER BY (name )\
SETTINGS index_granularity = 8192

插入
insert into `default`.aaa (id,name) values (1,'test')

查询
select * from aaa
修改
ALTER table `default`.bsc_transfer update name = 2 where id = 1

删除表
DROP TABLE IF EXISTS aaa

删除数据
alter table `default`.aaa delete where 1=1

4.配置文件

4.1修改用户配置

## 进入到 docker 容器内部:
docker exec -it 容器id /bin/bash
## 修改用户配置:
vim etc/clickhouse-server/users.xml

## 安装vim
apt-get update
apt-get install vim

用户密码

初次密码是空的,也可以在挂载的user.xml里面配置密码

## 位置:
<default>
          <password></password>
</default>

案例:

       <root>
           <password_sha256_hex>4613ee102c0c0caf003a0ac5fbe5b54e6610bf551f76636958911702c994f717</password_sha256_hex>
        <networks incl="networks" replace="replace">
        <ip>::/0</ip>
        </networks>
        <profile>default</profile>
        <quota>default</quota>
       </root>

用户名: root
密码: baian123ck

完整user.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>

           <!-- Use cache of uncompressed blocks of data. Meaningful only for processing many of very short queries. -->
           <use_uncompressed_cache>0</use_uncompressed_cache>

           <!-- How to choose between replicas during distributed query processing.
                random - choose random replica from set of replicas with minimum number of errors
                nearest_hostname - from set of replicas with minimum number of errors, choose replica
                 with minimum number of different symbols between replica's hostname and local hostname
                 (Hamming distance).
                in_order - first live replica is chosen in specified order.
                first_or_random - if first replica one has higher number of errors, pick a random one from replicas with minimum number of errors.
           -->
           <load_balancing>random</load_balancing>
           <max_partitions_per_insert_block>5000</max_partitions_per_insert_block>
       </default>

       <!-- Profile that allows only read queries. -->
       <readonly>
           <readonly>1</readonly>
       </readonly>
   </profiles>

   <!-- Users and ACL. -->
   <users>
       <!-- If user name was not specified, 'default' user is used. -->
       <default>
           <!-- Password could be specified in plaintext or in SHA256 (in hex format).

                If you want to specify password in plaintext (not recommended), place it in 'password' element.
                Example: <password>qwerty</password>.
                Password could be empty.

                If you want to specify SHA256, place it in 'password_sha256_hex' element.
                Example: <password_sha256_hex>65e84be33532fb784c48129675f9eff3a682b27168c0ea744b2cf58ee02337c5</password_sha256_hex>
                Restrictions of SHA256: impossibility to connect to ClickHouse using MySQL JS client (as of July 2019).

                If you want to specify double SHA1, place it in 'password_double_sha1_hex' element.
                Example: <password_double_sha1_hex>e395796d6546b1b65db9d665cd43f0e858dd4303</password_double_sha1_hex>

                If you want to specify a previously defined LDAP server (see 'ldap_servers' in main config) for authentication, place its name in 'server' element inside 'ldap' element.
                Example: <ldap><server>my_ldap_server</server></ldap>

                How to generate decent password:
                Execute: PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | sha256sum | tr -d '-'
                In first line will be password and in second - corresponding SHA256.

                How to generate double SHA1:
                Execute: PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | sha1sum | tr -d '-' | xxd -r -p | sha1sum | tr -d '-'
                In first line will be password and in second - corresponding double SHA1.
           -->
         <!-- <password></password> -->
           
                      <!-- <password>888888</password> --><password_sha256_hex>92925488b28ab12584ac8fcaa8a27a0f497b2c62940c8f4fbc8ef19ebc87c43e</password_sha256_hex>
           <!-- List of networks with open access.

                To open access from everywhere, specify:
                   <ip>::/0</ip>

                To open access only from localhost, specify:
                   <ip>::1</ip>
                   <ip>127.0.0.1</ip>

                Each element of list has one of the following forms:
                <ip> IP-address or network mask. Examples: 213.180.204.3 or 10.0.0.1/8 or 10.0.0.1/255.255.255.0
                    2a02:6b8::3 or 2a02:6b8::3/64 or 2a02:6b8::3/ffff:ffff:ffff:ffff::.
                <host> Hostname. Example: server01.yandex.ru.
                    To check access, DNS query is performed, and all received addresses compared to peer address.
                <host_regexp> Regular expression for host names. Example, ^server\d\d-\d\d-\d\.yandex\.ru$
                    To check access, DNS PTR query is performed for peer address and then regexp is applied.
                    Then, for result of PTR query, another DNS query is performed and all received addresses compared to peer address.
                    Strongly recommended that regexp is ends with $
                All results of DNS requests are cached till server restart.
           -->
           <networks>
               <ip>::/0</ip>
           </networks>

           <!-- Settings profile for user. -->
          <!-- <profile>default</profile> -->
           <profile>readonly</profile>

           <!-- Quota for user. -->
           <quota>default</quota>

           <!-- User can create other users and grant rights to them. -->
           <!-- <access_management>1</access_management> -->
       </default>
       

       <root>
           <password_sha256_hex>4613ee102c0c0caf003a0ac5fbe5b54e6610bf551f76636958911702c994f717</password_sha256_hex>
        <networks incl="networks" replace="replace">
        <ip>::/0</ip>
        </networks>
        <profile>default</profile>
        <quota>default</quota>
       </root>

       
   </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>

               <!-- 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>

4.1.1 用户密码生成

# 用户密码生成:

If you want to specify SHA256, place it in 'password_sha256_hex' element.
Example: <password_sha256_hex>65e84be33532fb784c48129675f9eff3a682b27168c0ea744b2cf58ee02337c5</password_sha256_hex>
Restrictions of SHA256: impossibility to connect to ClickHouse using MySQL JS client (as of July 2019).
# 如果密码使用 SHA256 时, 则需要<password_sha256_hex></password_sha256_hex>标签标注
# SHA256 密码生成:
How to generate decent password:
Execute: PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | sha256sum | tr -d '-'
In first line will be password and in second - corresponding SHA256.
# 案例:
echo -n "88888" | sha256sum | tr -d '-'
92925488b28ab12584ac8fcaa8a27a0f497b2c62940c8f4fbc8ef19ebc87c43e

If you want to specify double SHA1, place it in 'password_double_sha1_hex' element.
Example: <password_double_sha1_hex>e395796d6546b1b65db9d665cd43f0e858dd4303</password_double_sha1_hex>
# 如果密码使用 SHA1 时, 则需要<password_double_sha1_hex></password_double_sha1_hex>标签标注
How to generate double SHA1:
Execute: PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | sha1sum | tr -d '-' | xxd -r -p | sha1sum | tr -d '-'
# 案例:
echo -n "88888" | sha1sum | tr -d '-' | xxd -r -p | sha1sum | tr -d '-'
7820354fa39e9b967f91ea31d397dc1e788d4d43

4.2 修改集群配置

修改config.xml文件

  <remote_servers>
      <!--集群名字: test_shard_localhost  -->
      <test_shard_localhost>
          <!-- 分布式查询的服务器间集群密码
                默认值:无密码(将不执行身份验证)

                如果设置了,那么分布式查询将在分片上验证,所以至少:
                - 这样的集群应该存在于shard上
                - 这样的集群应该有相同的密码。

                而且(这是更重要的),initial_user将作为查询的当前用户使用。
       -->
          <!-- <secret></secret> -->
          <!--定义集群的分片数量,2个shard标签说明有2个节点-->
          <shard>
              <!-- 可选的。写数据时分片权重。默认: 1. -->
              <weight>1</weight>
              <!-- 可选的。是否只将数据写入其中一个副本。默认值:false(将数据写入所有副本)。-->
              <internal_replication>false</internal_replication>
              <replica>
                  <!-- 可选的。负载均衡副本的优先级,请参见(load_balancing 设置)。默认值:1(值越小优先级越高)。-->
                  <priority>1</priority>
                  <host>example01-01-1</host>
                  <port>9000</port>
              </replica>
              <replica>
                  <host>example01-01-2</host>
                  <port>9000</port>
              </replica>
          </shard>
          <shard>
              <weight>2</weight>
              <internal_replication>false</internal_replication>
              <replica>
                  <host>example01-02-1</host>
                  <port>9000</port>
              </replica>
              <replica>
                  <host>example01-02-2</host>
                  <!-- secure – 是否使用ssl进行连接,设为true时,通常也应该设置 port = 9440。服务器也要监听 <tcp_port_secure>9440</tcp_port_secure> 并有正确的证书。-->
                  <secure>1</secure>
                  <port>9440</port>
              </replica>
          </shard>
      </test_shard_localhost>

  </remote_servers>
   
## 可参考文档:
https://clickhouse.com/docs/zh/engines/table-engines/special/distributed

所以一个集群最少需要俩个节点,各为主节点,互为副本节点.

正常合理的做法是: 一个节点对应一个副本节点. 那么如果是3个节点clickhouse集群,就有3个副本.

4.3修改zookeeper配置

修改config.xml文件

   <zookeeper>
       <node>
           <host>example1</host>
           <port>2181</port>
       </node>
       <node>
           <host>example2</host>
           <port>2181</port>
       </node>
       <node>
           <host>example3</host>
           <port>2181</port>
       </node>
   </zookeeper>

4.4 引入其他配置文件

<include_from>/etc/metrika.xml</include_from>

  <!-- If element has 'incl' attribute, then for it's value will be used corresponding substitution from another file.
        By default, path to file with substitutions is /etc/metrika.xml. It could be changed in config in 'include_from' element.
        Values for substitutions are specified in /yandex/name_of_substitution elements in that file.
     -->

可参考官方文档:配置文件 | ClickHouse Docs

5.集群部署

5.1手动搭建集群

clickhouse 集群是非主从结构,各个节点是相互独立的。因此,和hdfs、yarn的集群不同,我们可以根据配置,灵活的配置集群,甚至可以将一个节点同时分配给多个集群。

clickhouse集群的概念主要就是用于分布式表和表的副本

部署集群图示

上面这张图有3个节点,这3个节点组成了2个集群。

想要配置集群,需要在 /etc/clickhouse-server/config.xml的 <remote_servers> 标签下添加相关集群信息。或者在/etc/metrika.xml中进行配置。

如果要在 /etc/metrika.xml 中配置,需要确保metrika.xml已经被config.xml包含进去了:

<remote_servers incl=“clickhouse_remote_servers”> remote_servers记得加incl属性

<include_from>/etc/metrika.xml</include_from> config.xml 将metrika.xml包含进来

要实现上图的集群架构,ck1、ck2、ck3的/etc/metrika.xml配置分别如下:

ck1配置:

<yandex>
   <clickhouse_remote_servers>
       <!--自定义集群名称-->
       <test_cluster1>
           <!--定义集群的分片数量,2个shard标签说明有2个节点-->
           <shard>
               <!--定义分片的副本数量,这里副本只有1个-->
               <replica>
                   <host>ck1</host>
                   <port>9000</port>
               </replica>
           </shard>
           <shard>
               <replica>
                   <host>ck2</host>
                   <port>9000</port>
               </replica>
           </shard>
       </test_cluster1>
   </clickhouse_remote_servers>

   <zookeeper-servers>
       <node index="1">
           <host>zk1</host>
           <port>2181</port>
       </node>
   </zookeeper-servers>
</yandex>

ck2配置:

<yandex>
 <clickhouse_remote_servers>
   <test_cluster1>
     <shard>
       <replica>
         <host>ck1</host>
         <port>9000</port>
       </replica>
     </shard>
     <shard>
       <replica>
         <host>ck2</host>
         <port>9000</port>
       </replica>
     </shard>
   </test_cluster1>
   <test_cluster2>
     <shard>
       <replica>
         <host>ck2</host>
         <port>9000</port>
       </replica>
     </shard>
     <shard>
       <replica>
         <host>ck3</host>
         <port>9000</port>
       </replica>
     </shard>
   </test_cluster2>
 </clickhouse_remote_servers>

 <zookeeper-servers>
   <node index="1">
     <host>zk1</host>
     <port>2181</port>
   </node>
 </zookeeper-servers>

</yandex>

ck3:

<yandex>
 <clickhouse_remote_servers>
   <test_cluster2>
     <shard>
       <replica>
         <host>ck2</host>
         <port>9000</port>
       </replica>
     </shard>
     <shard>
       <replica>
         <host>ck3</host>
         <port>9000</port>
       </replica>
     </shard>
   </test_cluster2>
 </clickhouse_remote_servers>

 <zookeeper-servers>
   <node index="1">
     <host>zk1</host>
     <port>2181</port>
   </node>
 </zookeeper-servers>

</yandex>

配置完之后,无需重启clickhouse服务,clickhouse会热加载这些配置。我们可以分别登陆这3台clickhouse,通过 select * from system.clusters; 查看当前节点所属集群的相关信息:

也可以在客户端工具dbeaver上进行sql查询:

select * from `system`.clusters c ;

配置好集群之后,我们就可以基于配置好的集群创建分布式表了:

--在集群test_cluster1上的各个节点创建test表(也就是ck1、ck2)
create table default.test on cluster test_cluster1(id Int8,name String) engine = MergeTree order by id;
--基于test_cluster1创建分布式表
create table test_all as test engine =Distributed(test_cluster1,default,replicaTest,rand());

先去各个节点上创建数据表,然后去任意一个节点上创建分布式表,分布式表实际是一个视图

5.2 使用docker-compose搭建集群

当集群机器数量众多,一台一台操作会非常麻烦。另外,如果我们手上没有服务器,又想深入研究clickhouse集群的一些特性时,就可以通过docker快速的搭建起clickhouse集群。

这里简单介绍一下docker-compose,docker-compose会根据定义好的配置文件帮我们启动多个docker container,省去我们一个个容器的操作工作。

下面的docker-compose.yaml是我经常用来快速搭建一个clickhouse集群的docker-compose配置文件:

version: "3.7"

services:
ck1:
  image: yandex/clickhouse-server
  ulimits:
    nofile:
      soft: 300001
      hard: 300002
  ports:
    - 8123:8123
    - 9001:9000
  volumes:
    - ./conf/config.xml:/etc/clickhouse-server/config.xml
    - ./conf/users.xml:/etc/clickhouse-server/users.xml
    - ./conf/metrika1.xml:/etc/metrika.xml
  links:
    - "zk1"
  depends_on:
    - zk1

ck2:
  image: yandex/clickhouse-server
  ulimits:
    nofile:
      soft: 300001
      hard: 300002
  volumes:
    - ./conf/metrika2.xml:/etc/metrika.xml
    - ./conf/config.xml:/etc/clickhouse-server/config.xml
    - ./conf/users.xml:/etc/clickhouse-server/users.xml
  ports:
    - 8124:8123
    - 9002:9000
  depends_on:
    - zk1

ck3:
  image: yandex/clickhouse-server
  ulimits:
    nofile:
      soft: 300001
      hard: 300002
  volumes:
    - ./conf/metrika3.xml:/etc/metrika.xml
    - ./conf/config.xml:/etc/clickhouse-server/config.xml
    - ./conf/users.xml:/etc/clickhouse-server/users.xml
  ports:
    - 8125:8123
    - 9003:9000
  depends_on:
    - zk1

zk1:
  image: zookeeper
  restart: always
  hostname: zk1
  expose:
    - "2181"
  ports:
    - 2181:2181

如果是在同一台上模拟集群,连接时则需要将8123端口分别进行映射      - 8123:8123

上面的配置文件定义了4个容器,其中3个容器分别运行clickhouse服务,1个容器运行zookeeper服务。

配置后docker-compose.yaml后,进入该配置文件的目录,执行 docker-compose up -d 就会一起启动这些容器,clickhouse集群也就快速搭建好了。通过docker-compose down可以卸载集群。

上面docker-compose.yaml中引入的./conf/users.xml、./conf/config.xml、./conf/metrika.xml 等内容会在本博客的最后贴出。

6.扩展

6.1 集群扩容

6.2 集群缩容

6.3 数据副本

官方文档:数据副本 | ClickHouse Docs

6.4 数据备份

官方文档: 数据备份 | ClickHouse Docs

尽管 副本 可以提供针对硬件的错误防护, 但是它不能预防人为操作失误: 数据的意外删除, 错误表的删除或者错误集群上表的删除, 以及导致错误数据处理或者数据损坏的软件bug.

可选方案:

  • 不能人工删除使用带有MergeTree引擎且包含超过50Gb数据的表. 但是,这些保护措施不能覆盖所有可能情况,并且这些措施可以被绕过。

  • 将源数据复制到其它地方,推荐的冷存储,可能是对象存储或分布式文件系统(额外订阅kafka,将数据冷备份一份)

  • 文件系统快照,将数据文件拷贝到其他服务器

  • clickhouse-copier 是一个多功能工具,最初创建它是为了用于重新切分pb大小的表。因为它能够在ClickHouse表和集群之间可靠地复制数据,所以它也可用于备份和还原数据

  • part操作

6.5 分布式表写入数据

# 创建一个Distributed引擎的表
:) create table d_table(id UInt8, name String, date Date)
  engine=Distributed(cluster_name, database, table [,sharding_key])
      # cluster_name : 集群名 -- /etc/metrika.xml中<clickhouse_cluster>这个自定义的标签的名字
      # database : 数据库名
      # table : 表名
      # sharding_key : 分片键(某一列名) 可选 -- 向分布式引擎的表插入数据时 会根据分片名(默认 1 2 3)和你指定的分片键 计算得出实际上数据插入哪一个节点 每次插入的节点可能都不一样 根据默认算法来

sharding_key 必须有,不然会报:  ClickHouse exception Method write is not supported by storage Distributed with more than one shard and no sharding key provided.

不建议使用分布式表写入数据

参考文档: ClickHouse合集(一):分布式集群部署及python调用hungry和她的朋友们的博客-CSDN博客python 安装clickhouse

6.6 clickhouse看这一篇就够了

参考文档: ClickHouse合集(一):分布式集群部署及python调用hungry和她的朋友们的博客-CSDN博客python 安装clickhouse

7. docker-compose 中的一些文件

users.xml :

<?xml version="1.0"?>
<clickhouse>
   <!-- Profiles of settings. -->
   <profiles>
       <!-- Default settings. -->
       <default>
           <!-- Maximum memory usage for processing single query, in bytes. -->
           <max_memory_usage>10000000000</max_memory_usage>


           <!-- How to choose between replicas during distributed query processing.
                random - choose random replica from set of replicas with minimum number of errors
                nearest_hostname - from set of replicas with minimum number of errors, choose replica
                 with minimum number of different symbols between replica's hostname and local hostname
                 (Hamming distance).
                in_order - first live replica is chosen in specified order.
                first_or_random - if first replica one has higher number of errors, pick a random one from replicas with minimum number of errors.
           -->
           <load_balancing>random</load_balancing>
           <allow_ddl>1</allow_ddl>
           <readonly>0</readonly>
       </default>

       <!-- Profile that allows only read queries. -->
       <readonly>
           <readonly>1</readonly>
       </readonly>
   </profiles>

   <!-- Users and ACL. -->
   <users>
       <!-- If user name was not specified, 'default' user is used. -->
       <default>
<access_management>1</access_management>
           <password></password>

           <networks>
               <ip>::/0</ip>
           </networks>

           <!-- Settings profile for user. -->
           <profile>default</profile>

           <!-- Quota for user. -->
           <quota>default</quota>

           <!-- User can create other users and grant rights to them. -->
           <!-- <access_management>1</access_management> -->
       </default>
<test>
    <password></password>
    <quota>default</quota>
           <profile>default</profile>
    <allow_databases>
        <database>default</database>
               <database>test_dictionaries</database></allow_databases>
           <allow_dictionaries>
        <dictionary>replicaTest_all</dictionary>
           </allow_dictionaries>
</test>
   </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>

               <!-- 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>
</clickhouse>

config.xml:

<?xml version="1.0"?>
<!--
 NOTE: User and query level settings are set up in "users.xml" file.
 If you have accidentally specified user-level settings here, server won't start.
 You can either move the settings to the right place inside "users.xml" file
  or add <skip_check_for_incorrect_settings>1</skip_check_for_incorrect_settings> here.
-->
<clickhouse>
   <logger>
       <level>trace</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>

   <http_port>8123</http_port>
   <tcp_port>9000</tcp_port>
   <mysql_port>9004</mysql_port>
   <postgresql_port>9005</postgresql_port>
   <interserver_http_port>9009</interserver_http_port>
   <max_connections>4096</max_connections>
   <keep_alive_timeout>3</keep_alive_timeout>
   <grpc>
       <enable_ssl>false</enable_ssl>
       <ssl_cert_file>/path/to/ssl_cert_file</ssl_cert_file>
       <ssl_key_file>/path/to/ssl_key_file</ssl_key_file>
       <ssl_require_client_auth>false</ssl_require_client_auth>
       <ssl_ca_cert_file>/path/to/ssl_ca_cert_file</ssl_ca_cert_file>
       <compression>deflate</compression>
       <compression_level>medium</compression_level>
       <max_send_message_size>-1</max_send_message_size>
       <max_receive_message_size>-1</max_receive_message_size>
       <verbose_logs>false</verbose_logs>
   </grpc>
   <openSSL>
       <server>
           <certificateFile>/etc/clickhouse-server/server.crt</certificateFile>
           <privateKeyFile>/etc/clickhouse-server/server.key</privateKeyFile>
           <dhParamsFile>/etc/clickhouse-server/dhparam.pem</dhParamsFile>
           <verificationMode>none</verificationMode>
           <loadDefaultCAFile>true</loadDefaultCAFile>
           <cacheSessions>true</cacheSessions>
           <disableProtocols>sslv2,sslv3</disableProtocols>
           <preferServerCiphers>true</preferServerCiphers>
       </server>

       <client>
           <loadDefaultCAFile>true</loadDefaultCAFile>
           <cacheSessions>true</cacheSessions>
           <disableProtocols>sslv2,sslv3</disableProtocols>
           <preferServerCiphers>true</preferServerCiphers>
           <invalidCertificateHandler>
               <name>RejectCertificateHandler</name>
           </invalidCertificateHandler>
       </client>
   </openSSL>
   <max_concurrent_queries>100</max_concurrent_queries>
   <max_server_memory_usage>0</max_server_memory_usage>
   <max_thread_pool_size>10000</max_thread_pool_size>
   <max_server_memory_usage_to_ram_ratio>0.9</max_server_memory_usage_to_ram_ratio>
   <total_memory_profiler_step>4194304</total_memory_profiler_step>

   <total_memory_tracker_sample_probability>0</total_memory_tracker_sample_probability>
   <uncompressed_cache_size>8589934592</uncompressed_cache_size>
   <mark_cache_size>5368709120</mark_cache_size>
   <mmap_cache_size>1000</mmap_cache_size>
   <compiled_expression_cache_size>134217728</compiled_expression_cache_size>
   <compiled_expression_cache_elements_size>10000</compiled_expression_cache_elements_size>
   <path>/var/lib/clickhouse/</path>
   <tmp_path>/var/lib/clickhouse/tmp/</tmp_path>
   <user_files_path>/var/lib/clickhouse/user_files/</user_files_path>
   <ldap_servers>
   </ldap_servers>
   <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>
   <custom_settings_prefixes></custom_settings_prefixes>
   <default_database>default</default_database>
   <mlock_executable>true</mlock_executable>
   <remap_executable>false</remap_executable>

   <![CDATA[
        Uncomment below in order to use JDBC table engine and function.

        To install and run JDBC bridge in background:
        * [Debian/Ubuntu]
          export MVN_URL=https://repo1.maven.org/maven2/ru/yandex/clickhouse/clickhouse-jdbc-bridge
          export PKG_VER=$(curl -sL $MVN_URL/maven-metadata.xml | grep '<release>' | sed -e 's|.*>\(.*\)<.*|\1|')
          wget https://github.com/ClickHouse/clickhouse-jdbc-bridge/releases/download/v$PKG_VER/clickhouse-jdbc-bridge_$PKG_VER-1_all.deb
          apt install --no-install-recommends -f ./clickhouse-jdbc-bridge_$PKG_VER-1_all.deb
          clickhouse-jdbc-bridge &

        * [CentOS/RHEL]
          export MVN_URL=https://repo1.maven.org/maven2/ru/yandex/clickhouse/clickhouse-jdbc-bridge
          export PKG_VER=$(curl -sL $MVN_URL/maven-metadata.xml | grep '<release>' | sed -e 's|.*>\(.*\)<.*|\1|')
          wget https://github.com/ClickHouse/clickhouse-jdbc-bridge/releases/download/v$PKG_VER/clickhouse-jdbc-bridge-$PKG_VER-1.noarch.rpm
          yum localinstall -y clickhouse-jdbc-bridge-$PKG_VER-1.noarch.rpm
          clickhouse-jdbc-bridge &

        Please refer to https://github.com/ClickHouse/clickhouse-jdbc-bridge#usage for more information.
   ]]>
   <remote_servers incl="clickhouse_remote_servers">
       <test_unavailable_shard>
           <shard>
               <replica>
                   <host>localhost</host>
                   <port>9000</port>
               </replica>
           </shard>
           <shard>
               <replica>
                   <host>localhost</host>
                   <port>1</port>
               </replica>
           </shard>
       </test_unavailable_shard>
   </remote_servers>

   <zookeeper incl="zookeeper-servers">
   </zookeeper>
   <builtin_dictionaries_reload_interval>3600</builtin_dictionaries_reload_interval>
   <max_session_timeout>3600</max_session_timeout>
   <default_session_timeout>60</default_session_timeout>
   <query_log>
       <database>system</database>
       <table>query_log</table>
       <partition_by>toYYYYMM(event_date)</partition_by>
       <flush_interval_milliseconds>7500</flush_interval_milliseconds>
   </query_log>
   <trace_log>
       <database>system</database>
       <table>trace_log</table>

       <partition_by>toYYYYMM(event_date)</partition_by>
       <flush_interval_milliseconds>7500</flush_interval_milliseconds>
   </trace_log>
   <query_thread_log>
       <database>system</database>
       <table>query_thread_log</table>
       <partition_by>toYYYYMM(event_date)</partition_by>
       <flush_interval_milliseconds>7500</flush_interval_milliseconds>
   </query_thread_log>
   <query_views_log>
       <database>system</database>
       <table>query_views_log</table>
       <partition_by>toYYYYMM(event_date)</partition_by>
       <flush_interval_milliseconds>7500</flush_interval_milliseconds>
   </query_views_log>
   <part_log>
       <database>system</database>
       <table>part_log</table>
       <partition_by>toYYYYMM(event_date)</partition_by>
       <flush_interval_milliseconds>7500</flush_interval_milliseconds>
   </part_log>
   <metric_log>
       <database>system</database>
       <table>metric_log</table>
       <flush_interval_milliseconds>7500</flush_interval_milliseconds>
       <collect_interval_milliseconds>1000</collect_interval_milliseconds>
   </metric_log>
   <asynchronous_metric_log>
       <database>system</database>
       <table>asynchronous_metric_log</table>
       <flush_interval_milliseconds>7000</flush_interval_milliseconds>
   </asynchronous_metric_log>
   <opentelemetry_span_log>
       <engine>
          engine MergeTree
          partition by toYYYYMM(finish_date)
          order by (finish_date, finish_time_us, trace_id)
       </engine>
       <database>system</database>
       <table>opentelemetry_span_log</table>
       <flush_interval_milliseconds>7500</flush_interval_milliseconds>
   </opentelemetry_span_log>
   <crash_log>
       <database>system</database>
       <table>crash_log</table>

       <partition_by />
       <flush_interval_milliseconds>1000</flush_interval_milliseconds>
   </crash_log>

   <session_log>
       <database>system</database>
       <table>session_log</table>

       <partition_by>toYYYYMM(event_date)</partition_by>
       <flush_interval_milliseconds>7500</flush_interval_milliseconds>
   </session_log>
   <top_level_domains_lists>
   </top_level_domains_lists>
   <dictionaries_config>*_dictionary.xml</dictionaries_config>
<user_defined_executable_functions_config>*_function.xml</user_defined_executable_functions_config>
   <encryption_codecs>
     
   </encryption_codecs>

   <distributed_ddl>
       <path>/clickhouse/task_queue/ddl</path>
   </distributed_ddl>
   <graphite_rollup_example>
       <pattern>
           <regexp>click_cost</regexp>
           <function>any</function>
           <retention>
               <age>0</age>
               <precision>3600</precision>
           </retention>
           <retention>
               <age>86400</age>
               <precision>60</precision>
           </retention>
       </pattern>
       <default>
           <function>max</function>
           <retention>
               <age>0</age>
               <precision>60</precision>
           </retention>
           <retention>
               <age>3600</age>
               <precision>300</precision>
           </retention>
           <retention>
               <age>86400</age>
               <precision>3600</precision>
           </retention>
       </default>
   </graphite_rollup_example>

   <format_schema_path>/var/lib/clickhouse/format_schemas/</format_schema_path>
   <query_masking_rules>
       <rule>
           <name>hide encrypt/decrypt arguments</name>
           <regexp>((?:aes_)?(?:encrypt|decrypt)(?:_mysql)?)\s*\(\s*(?:'(?:\\'|.)+'|.*?)\s*\)</regexp>
           <replace>\1(???)</replace>
       </rule>
   </query_masking_rules>



   <send_crash_reports>
       <enabled>false</enabled>
       <anonymize>false</anonymize>
       <endpoint>https://6f33034cfe684dd7a3ab9875e57b1c8d@o388870.ingest.sentry.io/5226277</endpoint>
   </send_crash_reports>
   <include_from>/etc/metrika.xml</include_from>
</clickhouse>

metrika1.xml、metrika2.xml、metrika3.xml 见第二章ck1、ck2、ck3的配置文件。

8. 集群考虑点

clickhouse多节点组合在一起是需要一个分布式视图表进行关联在一起.

入数据节点的时候可以从分布式视图表入库, 但建议从数据节点进行入库.

通过对Distributed表写入流程的分析,了解了该类型表的实际工作原理,所以在实际应用中有几个点还需要关注一下:

Distributed表在写入时会在本地节点生成临时数据,会产生写放大,所以会对CPU及内存造成一些额外消耗,建议尽量少使用Distributed表进行写操作;

Distributed表写的临时block会把原始block根据sharding_key和weight进行再次拆分,会产生更多的block分发到远端节点,也增加了merge的负担;

Distributed表如果是基于表函数创建的,一般是同步写,需要注意。

了解原理才能更好的使用,遇到问题才能更好的优化。

写入原理参考: 【clickhouse】ClickHouse最佳实战之分布表写入流程分析_九师兄的博客-CSDN博客

写入流程参考:clickhouse 写入 分布式表 - CSDN

9. 集群案列测试:

分别连接 8123,8124,8125clickhouse数据库

连接8123:

-- 查看集群信息
select * from `system`.clusters c ;

-- 创建表:
create table IF NOT EXISTS `default`.hits (
id Int64,
name String,
birthday DateTime64
)ENGINE = MergeTree()
ORDER BY (id)
SETTINGS index_granularity=8192

-- 插入数据
insert into hits(id,name,birthday ) values(1,'张三', toDateTime('2016-06-15 23:00:00'));
insert into hits(id,name,birthday ) values(3,'王五', '2022-7-13 09:14:13');

--查询数据

select * from hits h ;

连接 8124:

-- 查看集群信息
select * from `system`.clusters c ;

-- 创建表:
create table IF NOT EXISTS `default`.hits (
id Int64,
name String,
birthday DateTime64
)ENGINE = MergeTree()
ORDER BY (id)
SETTINGS index_granularity=8192

-- 插入数据
insert into hits(id,name,birthday ) values(4,'赵六', '2020-7-13 02:04:53');


--查询数据

select * from hits h ;


-- 在 8124 上创建 分布式表
CREATE TABLE hits_all AS hits
ENGINE = Distributed(test_cluster1, default, hits,id)
SETTINGS
  fsync_after_insert=0,
  fsync_directories=0;
   
-- 查询分布式表:
select * from hits_all h ;

-- 给予分布式表写入数据
insert into hits_all(id,name,birthday ) values(5,'王五', '2022-7-13 09:14:13');
--(当前操作必须在创建分布式表时候要有sharding_key,否则会报错)

-- 删除分布式表
drop table hits_all;

公众号发哥讲

这是一个稍偏基础和偏技术的公众号,甚至其中包括一些可能阅读量很低的包含代码的技术文,不知道你是不是喜欢,期待你的关注。

代码分享

发哥讲Java (naimaohome) - Gitee.com

微信公众号 点击关于我,加入QQ群,即可获取到代码以及高级进阶视频和电子书!!

​​​​​

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

航迹者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值