ClickHouse的简单部署和应用

ClickHouse

引言

市面上比较流行的KFC套餐中的C就是ClickHouse,很多做实时和架构的同学都比较熟悉这个工具了,我会结合一下,部署和在业务中的使用简单的聊一下,以及之后为什么要抛弃CK。
ClickHouse是俄罗斯第一大搜索引擎Yandex开发的列式储存的OLAP数据库,单机和集群的查询性能快到飞起,OLAP中单表查询最快的工具,没有之一。今日头条、腾讯、携程、快手都在使用CK,对PB级别的数据进行分析。
优点:

  • 1.真正的面向列的DBMS
  • 2.数据高效压缩=>0.2
  • 3.磁盘存储的数据=>减少内存使用
  • 4.多核并行处理=>多核多节点并行化大型查询
  • 5.在多个服务器上分布式处理
  • 6.SQL语法支持
  • 7.数据有序存储=>ClickHouse支持在建表时,指定将数据按照某些列进行sort by。
  • 8.主键索引+ 稀疏索引

搭建(docker)

Dockerfile

FROM centos:7
MAINTAINER clickhouse

RUN yum install -y curl
RUN curl -s https://packagecloud.io/install/repositories/Altinity/clickhouse/script.rpm.sh | bash
RUN yum install -y clickhouse-server clickhouse-client
RUN mkdir -p /var/clickhouse/log
RUN mkdir -p /var/clickhouse/data

ADD clickhouse-start.sh /

ENTRYPOINT ["sh","/clickhouse-start.sh"]

clickhouse-start.sh

#!/bin/bash
set -e
exec /etc/init.d/clickhouse-server start & tail -f /dev/null

config.xml 基础配置,不多做赘述,这里把log和data的目录改成/var/clickhouse/…,不懂私聊我
metrika.xml 可以理解为集群的配置,以高可用的一种 3个分片,2个副本为例
简单说一下这个这个架构,一般情况先搭个单机,不用考虑这些问题,如果要搭建一个高可用的集群,比较靠谱的是有分片有副本,ck采用的是指定一个分配指定两个副本的方式,比如my_cluster集群的第一个shard是由ck01和ck02构成的,即一个分片由两个副本构成,然后在ck01上指定宏变量的macros是 01 01

机器 shard replica
ck01 01 01
ck02 01 02
ck03 02 01
ck04 02 02
ck05 03 01
ck06 03 02
<yandex>
    <clickhouse_remote_servers>
        <my_cluster>
            <shard>
                <internal_replication>true</internal_replication>
                <replica>
                    <host>ck01</host>
                    <port>9000</port>
                </replica>
                 <replica>
                    <host>ck02</host>
                    <port>9000</port>
                </replica>
            </shard>
            <shard>
                <internal_replication>true</internal_replication>
                <replica>
                    <host>ck03</host>
                    <port>9000</port>
                </replica>
                 <replica>
                    <host>s-hadoop-log04</host>
                    <port>9000</port>
                </replica>
            </shard>
            <shard>
                <internal_replication>true</internal_replication>
                <replica>
                    <host>ck05</host>
                    <port>9000</port>
                </replica>
                 <replica>
                    <host>ck06</host>
                    <port>9000</port>
                </replica>
            </shard>
        </my_cluster>
</clickhouse_remote_servers>

    <!--zookeeper相关配置-->
    <zookeeper-servers>
        <node index="1">
            <host>ck01</host>
            <port>2181</port>
        </node>
        <node index="2">
            <host>ck02</host>
            <port>2181</port>
        </node>
        <node index="3">
            <host>ck03</host>
            <port>2181</port>
        </node>
    </zookeeper-servers>

    <macros>
        <shard>01</shard>
        <replica>01</replica>
    </macros>

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

    <clickhouse_compression>
        <case>
            <min_part_size>10000000000</min_part_size>
            <min_part_size_ratio>0.01</min_part_size_ratio>
            <method>lz4</method>
        </case>
    </clickhouse_compression>
</yandex>

users.xml 基本用户管理 用户名:default 密码:123456

<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_uncompressed_cache>0</use_uncompressed_cache>
            <load_balancing>random</load_balancing>
        </default>

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

    <!-- Users and ACL. -->
    <users>
        <default>
            <password>123456</password>
            <networks incl="networks" replace="replace">
                <ip>::/0</ip>
            </networks>
            <profile>default</profile>
            <quota>default</quota>
        </default>
        <guest>
            <password></password>
            <networks incl="networks" replace="replace">
                <ip>::/0</ip>
            </networks>
            <profile>readonly</profile>
            <quota>default</quota>
        </guest>
    </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>

创建文件夹
/xxx/clickhouse/conf
/xxx/clickhouse/log
/xx/clickhouse/data/clickhouse-server

docker-compose-server.yml

version: '3.7'
services:
    clickhouse-server:
        image: clickhouse:v20.5.4
        restart: always
        network_mode: "host"
        container_name: "clickhouse-server"
        ports:
            - "9000:9000"
            - "9440:9440"
            - "9009:9009"
            - "8123:8123"
        volumes:
            - "/xxx/clickhouse/conf:/etc/clickhouse-server"
            - "/xxx/clickhouse/log:/var/clickhouse/log"
            - "/xxx/clickhouse/data/clickhouse-server:/var/clickhouse/data"
            - "/etc/localtime:/etc/localtime:ro"

升级+扩容

升级前读说明,一般升级是滚动升级的,重新打镜像,替换目前的镜像即可
扩容更简单在metrika.xml中配置,比如多了两台机器,分别是ck07、ck08
在my_cluster中添加

 <shard>
    <internal_replication>true</internal_replication>
    <replica>
        <host>ck07</host>
        <port>9000</port>
    </replica>
     <replica>
        <host>ck08</host>
        <port>9000</port>
    </replica>
</shard>

然后07、08中分别修改macros中变量04-01,04-02

使用

应用场景是用户画像T+1,提供快速的圈选人群、特征筛选、快速查询,以及报表展示

ui

http://ui.tabix.io/#!/login 外部的UI登陆后使用,有监控

建表(以用户画像的表为例)

-- 创建ck表 高可用表 ON CLUSTER my_cluster的意思是在这个集群上创建,不写只会在一台机器上有这个表
CREATE TABLE `user_profile` ON CLUSTER my_cluster (
user_id              Bigint   comment '用户id',
user_name            String   comment '用户名称',
user_desc            String   comment '用户简介',
card_name            String   comment '身份证姓名',
...
partition_date       Int      comment '时间分区'
)
-- {shard} {replica} 是你在metrika.xml指定的宏变量
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/user_profile', '{replica}')
PARTITION BY partition_date
ORDER BY user_id
SETTINGS index_granularity = 8192;

-- 创建ck表 分布式表,上边的表是每台机器上都有的本地表,不同分片之间的数据不会互通,只查询上表,数据是一个分片的数据,这个表是所有分片上表的一个映射,查询分布式表是所有分片数据的总和
create table user_profile_all ON CLUSTER my_cluster as user_profile
ENGINE = Distributed(my_cluster, default, user_profile, rand());

从hive中导表

从hdfs中导到本地,在从本地导入到ck中
集群6台,13G数据,4千万条,获取数据4分钟,导入数据6分钟

#!/bin/bash
 
echo "select * from test.user_profile where partition_date=$1"
 
hive -e "SET hive.exec.compress.output=false; insert overwrite local directory '/home/tmp/test/user_profile/$1' row format delimited fields terminated by '\001' STORED AS TEXTFILE select * from test.user_profile where partition_date=$1"
 
echo "load csv to ck"
 
delimiter=$'\001'
cat ./$1/* | sed 's/"/\\"/g'| sed "s/'/\\\'/g"|clickhouse-client --host=ck01 --port=9000 --user=default --format_csv_delimiter="$delimiter" --query="INSERT INTO default.user_profile_all FORMAT CSV"
 
echo "load down! remove file"
 
rm -rf ./$1
  
-- 复杂数据类型,第47列是array[int]
cat 20200714/* | sed 's/"/\\"/g'| sed "s/'/\\\'/g" | sed "s/\x02/, /g"  | awk -F '\x01' '{
for(i=1;i<=NF;i++) {
    if(i==NF){print $i}
    else if( i==47 ){printf "["$i"]""\x01"}
    else {printf $i"\x01"}
}}' | clickhouse-client --host=ck01 --port=9000 --user=default --format_csv_delimiter=$'\001' --query="INSERT INTO default.user_user_profile_all FORMAT CSV"
 

db导表

CREATE TABLE tablename ENGINE = MergeTree ORDER BY id AS
SELECT *
FROM mysql('host:port', 'databasename', 'tablename', 'username', 'password')

alter

-- 删除分区
ALTER TABLE default.tablename ON CLUSTER my_cluster delete where partition_date=20200615
-- 添加列
alter table tablename ON CLUSTER my_cluster add column cost int default 0 after user_id
-- 删除列
alter table tablename ON CLUSTER my_cluster drop column cost
-- 注视
alter table tablename ON CLUSTER my_cluster comment column cost 'test'
-- 更改类型
alter table tablename ON CLUSTER my_cluster modify column cost String
-- 更改列名 (2020年9月初会更新至20.5.4,之后版本可用)
alter table default.tablename ON CLUSTER my_cluster rename column `oldname` to `newname`;

问题

因为这些问题,让我们放弃了继续用ClickHouse

  • 不支持事务,不支持真正的删除/更新其实是可以删除,只不过是异步的删除一条数据后,一分钟才生效
  • 不支持高并发,官方建议qps为100,可以通过修改配置文件增加连接数,但是在服务器足够好的情况下;测试阶段还好
  • SQL满足日常使用80%以上的语法,join写法比较特殊;最新版已支持类似SQL的join,但性能不好
  • 尽量做1000条以上批量的写入,避免逐行insert或小批量的insert,update,delete操作,因为ClickHouse底层会不断的做异步的数据合并,会影响查询性能,这个在做实时数据写入的时候要尽量避开;无法满足准实时写入的情况
  • Clickhouse快是因为采用了并行处理机制,即使一个查询,也会用服务器一半的CPU去执行,所以ClickHouse不能支持高并发的使用场景,默认单查询使用CPU核数为服务器核数的一半,安装时会自动识别服务器核数,可以通过配置文件修改该参数。
  • c++写的,小公司大规模使用起来,出了问题没人能解决

猜你喜欢

转载自blog.csdn.net/jklcl/article/details/112971187