背景:

工作中,突然说需要用到ClickHouse。

发现问题

  • 调研与集成接入:
    调研过程中,理论知识看不出来什么名堂;
    采用MybatisPlus + Druid简单接入后,做数据验证发现一下问题:
1、采用insert方式更新,那么新老数据如果去重?
  2、碰到insert某个节点,其他节点没有数据,为什么?
  3、集群中各节点数据不一样,而jdbc客户端只能做负载均衡,那么查询操作如何将所有节点汇总后的数据?

解决问题

现在,我们来看一下,以上疑问:

问题1

ClickHouse去重,要么用optimize(很消耗性能,我们也不能每次查询前都optimize一下),要么使用GroupBy(建立物化视图,使用GroupBy语句去重,常用手段)

问题23

这个说起来有点复杂,可以先去了解一下,《下一节、ClickHouse的高可用集群方案》,然后我们分场景分析:

场景一

如果我们数据量不大,单节点ClickHouse完全可以hold住,那么,只要做备份就行了

直接使用ReplicaMergeTree表引擎搞定

注意:

  • a、DDL时,你可能要在每台节点上执行DDL,你可以使用on CLUSTER ,就可以只执行一次啦(前提是需要配置一个集群一个分片所有机器备份)
  • b、因为ReplicaMergeTree表引擎第二个参数是备份名,要求每个备份名不一样,可以采用配置macro来解决

场景二

如果我们数据量很大,但是对可用性,要求不是很高,那么可以使用分布式表来解决(具体使用,后续更新)

场景三

如果使用数据量很大,且要求高可用,那就 备份 + 分布式表 解决。

ClickHouse高可用集群方案


方案1.0:MergeTree + Distributed

clickhouse高可用架构图 clickhouse 案例_clickhouse高可用架构图

  • 优势
    架构简单,单机和分布式都可以用
  • 劣势
    单点问题,数据丢失风险大

方案2.0:MergeTree + Distributed + 多副本

在方案一的基础上为每个节点增加副本

clickhouse高可用架构图 clickhouse 案例_clickhouse_02

  • 优势
    在1.0的基础上,数据安全有了保障,任何一个实例或者服务器挂掉了,不影响集群查询服务
  • 劣势
    如果某个节点挂了,恢复以后可以将丢失的增量数据补全,但是如果硬盘彻底损坏,存量数据基本无法恢复,且这种方案不能用两个节点互为主备,会造成数据错乱

方案3.0:ReplicatedMergeTree + Distributed + 多副本

把2.0方案中的数据表引擎替换成ReplicatedMergeTree,并设置分布式写入时只写入分片的一个节点:internal_replication设置为true
实现同一个分片中,写入一个节点的数据后,自动同步到其他的副本中
下图实现的是一个节点启动多个ClickHouse实例

clickhouse高可用架构图 clickhouse 案例_高可用_03

  • 优势
    由ReplicatedMergeTree表引擎管理数据副本(依赖Zookeeper),无须担心节点挂掉后数据的同步和丢失问题
  • 劣势
    集群配置比较复杂, macros配置分片和副本需要仔细

实际应用

create table db_test.s03_shop_privatetraffic_traffic_d  ON CLUSTER 'cluster_1s4r' ( \
 create_time String COMMENT '日期', \
 tenant_nm String COMMENT '租户名称', \
 tenant_cd String COMMENT '租户编号', \
 tenant_info_id String COMMENT '租户信息唯一键', \
 shop_info_id String COMMENT '店铺唯一键', \
 shop_cd String COMMENT '店铺id', \
 shop_name String COMMENT '店铺名称', \
 day_nm Decimal128(4) COMMENT '日访问人数', \
 new_user_nm Decimal128(4) COMMENT '新用户访问人数', \
 backflow_user_nm Decimal128(4) COMMENT '回流用户数', \
 new_user_proportion Decimal128(4) COMMENT '新用户占比', \
 total_nm Decimal128(4) COMMENT '累计用户数', \
 total_lost_nm Decimal128(4) COMMENT '累计流失用户数', \
 new_user_keep Decimal128(4) COMMENT '新增日留存数', \
 active_keep Decimal128(4) COMMENT '活跃日留存', \
 share_user_nm Decimal128(4) COMMENT '分享人数', \
 browse_nm Decimal128(4) COMMENT '商品曝光人数', \
 browse_sku_nm Decimal128(4) COMMENT '被访问商品数', \
 expose_sku_nm Decimal128(4) COMMENT '商品曝光量', \
 add_nm Decimal128(4) COMMENT '日加购人数', \
 give_order_nm Decimal128(4) COMMENT '日下单人数', \
 payed_nm Decimal128(4) COMMENT '日支付人数', \
 browse_add_proportion Decimal128(4) COMMENT '访问加购转化率', \
 browse_give_order_proportion Decimal128(4) COMMENT '访问下单转化率', \
 browse_payed_proportion Decimal128(4) COMMENT '访问支付转化率', \
 give_order_payed_proportion Decimal128(4) COMMENT '下单支付转化率', \
 add_payed_proportion Decimal128(4) COMMENT '加购支付转化率', \
 dt String COMMENT '创建日期', \
 ds String COMMENT '指标类型' \
) engine = ReplicatedMergeTree('/clickhouse/table/s03_shop_privatetraffic_traffic_d/01','s03_shop_privatetraffic_traffic_d_{shard_one}') \
 partition by (dt) \
 order by (dt,create_time,ds,tenant_info_id,shop_info_id);