大数据分析利器——clickhouse的简介与应用

大数据分析利器——clickhouse的简介与应用

背景介绍

	公司原有的数仓技术架构是基于传统的Hadoop的数仓体系,使用任务调度,通过不同的hive的任
	务调度解决不同的业务主题。传统的数仓架构胜在稳定,依托于Hadoop体系,使用的用户也较
	多。但是也存在以下的缺点:
	

	1. 实时性:实时性较低,基于T+1的数据导入限制,通常hive的整个数据从数据源
	 头到最后的数据应用,中间的时间跨度基本都在几个小时到一天,数据的实时
	 性达不到业务的需求,业务端会想要尽快的知道他想要知道的结果。
	2. 便捷性:原有的数仓架构由于依赖于Hadoop体系,整个架构体系都比较重,开
	发人员对于业务端不熟悉,对于全量纬度的预计算的扩展无法进行(代价太大,
	耗时长,不划算)。因此,业务端想要基于某个业务主体拓展新的业务需求时,
	开发往往需要从头开始设计整个工作流的调度,工作量较大。
	3. 经济性:原有的体系针对于日志数据进行处理时,基于日志的流的特性,无法
	给出良好的解决方案,便采用了神策加帆软的商业方案,不得不在某些业务上进
	行一些必要的商业支出。
	
	为了解决上述存在的问题,我们前期调研了很多olap的工具,最终采用了使用以 
	flink+clickhouse+superset 的为主要框架的开源的解决方案。

方案介绍

  1. 解决痛点:

    1.原有的批处理的任务调度更换为以flink为主的流处理,解决时效性的问题
    2.维度扩展使用flink在流中对小数据量的流式数据就行全量的维度扩展,基于
    clickhouse进行扩展后的宽表存储
    3.使用flink对日志进行字段解析替换神策,使用clickhouse进行存储,使用
    superset替换帆软,进行BI处理
    
  2. 方案难点:

    1.原有的数据同步需要以流式的方式进行,如何选取从mysql到clickhouse的实时
    的数据采集的实现方案
    2.日志解析时以及数据同步后的维度扩展,如何尽可能全的将业务需要的维度度量
    考虑进去
    3.clickhouse的表的设计,如何能够高效的发挥出clickhouse的特性,避免
    clickhouse的缺点
    
  3. 解决方案

     3.1 数据同步架构方案
     		mysql的数据增量同步方案很多,我们使用的还是通过binlog日志同步的方
     		式,即采用的是canal + kafka + flink 的方式,通过解析mysql数据变化时的日
     		志变化,将数据同步至clickhouse中(网上具体步骤很多,不赘述)
     3.2 clickhouse的优缺点介绍
     	优点:
     		快,超乎想象的快(单表),clickhouse的诞生和简介可以自行百度,
     		clickhouse目前测试和使用中来看,单表的查询性能无人能敌。目前我们的生
     		产中的一张日志表,使用分布式表存储数据,单表查询时,数据总量在300亿
     		(近百T)的级别,全表扫描的查询能够达到秒级响应(磁盘性能和带宽是影
     		响性能的一大瓶颈,目前我们的磁盘是7200的机械,带宽也很差,
     		clickhouse机器上的磁盘还在和其他的共用IO,穷穷穷)。
     		压缩率高,目前clickhouse的数据压缩能够达到30%~40%之前,这对于一个
     		精打细算的公司来说是一件很划算的事情(省磁盘)
     		总结起来就是吃的是草,挤的是奶(手动滑稽)
     	缺点:
     		当然,不可能没有缺点。
     		3.2.1 缺点之一就是对于并发支持不够友好。
     		在高并发查询,大概同时的查询数量在上千级别的话,就很容易出问题,因
     		此,用来做面向用户的查询的存储肯定就不是一个正确的选择
     		3.2.2 缺点之二就是相对于查询来说,他的写入速度没有那么优秀,目前测试
     		来看,单台机器的写入速度只能达到大概30W/s~60W/s。
     		3.2.3 缺点之三就是对于新接触的用户不是太友好(俄罗斯开发的东西,比较
     		粗狂),刚开始会比较头疼,但是越用越喜欢。
     		3.2.4 相比较他自己单表查询性能来说,join的性能就不是很优秀了,但是相
     		比较传统的hive和spark来说,性能还是很很不错的。
     3.3 clickhouse的表结构设计方案
     	3.3.1 表引擎
     		在众多的表引擎中,使用最多的也就是那么两三种,着重简介以下这几种表
     		引擎:
     		3.3.1.1 ReplicatedMergeTree
     			用来做数据副本的表引擎,该表引擎会依赖于zookeeper,进行副本信息
     			的存储,在数据插入的时候,会对数据进行复制存储,防止数据丢失时数
     			据的恢复(简单理解为hdfs的副本机制)
     		3.3.1.2 MergeTree
     			该表引擎就是在你插入数据的时候,按照你指定的主键(没有指定主键就
     			会默认使用order by字段作为主键),和你设定的索引的粒度对数据进行
     			合并,按照排序键进行存储。
     		3.3.1.3 Distributed
     			该表引擎即为依托于clickhouse的集群环境构建的分布式表,可以依托此
     			引擎对于超大数据集在服务器上横向扩展,进行存储。
     	3.3.2 表结构的设计
     		分布式表的建立需要构建在clickhouse的集群环境之上,分布式表的构建需要
     		先在每台机器上创建本地表,然后使用Distributed引擎创建分布式表。
     		clickhouse的分布式表简单理解可以理解为一个路由。针对于分布式表的查询
     		是基于这个路由做的查询的分发的结果的汇总,因此在小数据量的情况下,
     		不建议使用分布式表。只有在大数据量,才能够充分发挥分布式表的特性。
     		下边是一个分布式表的构建示例:
    

--构建本地表

CREATE TABLE ods.px_nginx_raw_phy on cluster srt_cluster_3shards_2replicas(
`log_format` Nullable(String),
 `remote_addr` Nullable(String),
 `status` Nullable(String),
 `time_iso8601` String,
 `upstream_response_time` Nullable(String),
 `request_time` String,
 `request_method` Nullable(String),
 `request_uri` Nullable(String),
 `body_bytes_sent` Nullable(String),
 `http_referer` Nullable(String),
 `http_user_agent` Nullable(String),
 `http_x_forwarded_for` Nullable(String),
 `request_body` Nullable(String),
 `http_cookie` Nullable(String),
 `X_passport` Nullable(String),
 `etl_time` DateTime DEFAULT now()
) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{layer}-{shard}/px_nginx_raw_phy', '{replica}') PARTITION BY substring(time_iso8601, 1, 10) ORDER BY time_iso8601 SETTINGS index_granularity = 8192
--需要解释的是上述本地表的构建,需要clickhouse集群构建的集群名称,分布式表存在zk的路径,还
有集群的副本名字等参数
--构建分布式表

CREATE table ods.px_nginx_raw on cluster srt_cluster_3shards_2replicas as
 ods.px_nginx_raw_phy ENGINE = Distributed(srt_cluster_3shards_2replicas, ods, px_nginx_raw_phy, rand());

	3.4 clickhouse需要注意的点
		3.4.1 数据插入
			单表插入:
				官方建议是最好是以批次大数据量的插入方式为主。其根本原因是在于
				clickhouse本事的数据插入,会按照你插入的批次和你索引的粒度形成小文件,比如你每
				秒有100次的insert的提交,然后每个insert携带的是100条数据,在不考虑索引粒度不一致
				的情况下,就会产生一百个小文件,如果这10000条的数据的索引粒度都是一致的话,ck
				会将这100个小文件进行合并,但是如果你在插入的时候,将原本的每秒100次,每次100
				条的插入换成每秒一次,一次10000来说,ck会更喜欢,因为你让他减少了文件合并的操
				作。同时如果这10000条的数据的索引粒度不一致,比如这10000条数据包含100天不同时
				间的数据,然后你又是以天为粒度的索引划分,每一个不同的索引在每次插入的时候就会
				形成一个不同的小文件,这样就会产生最多10000个小文件,此时clickhouse就会耗费资
				源在文件合并上,就会跑出too many parts(官方默认配置数量是300,超过就会跑出此异
				常) 的异常。解释比较啰嗦,根本原因还是在文件合并(参考hive的小文件合并对于hive
				的查询性能的影响)
			分布式副本表的插入:
				分布式副本表是超大数据量存储的常用选择,但是在针对这种类型表结构的数据插入时,
				需要考虑的就是zookeeper的效率影响。不要直接对分布式表进行数据的插入,在数据量
				大的情况下,你的每次插入,都需要zookeeper进行一个类似于负载均衡的数据分发的工
				作,会对zookeeper造成极大的压力,如果你的zookeeper还不仅仅只是承担ck的工作话,
				就会影响其他的业务。因此,最后直接对本地物理表进行操作,自己手动实现loadblance
				的操作。
		3.4.2 内存限制
			说完了数据写入需要注意的点,数据查询时也会有很多坑存在(官网没有,手动滑稽),在
			我们刚开始使用时,会经常遇见,跑一个sql能干掉整个clickhouse进程的情况,会让你很懵
			逼,实际上就是由于你跑的这个sql耗费的内存太多,而你又没有进行内存限制的设置,因此
			在跑这种类型的sql时,由于oom,然后操作系统直接强行把你的clickhouse给干掉了。因此
			需要对clickhouse的查询的使用内存进行一个限制。通常使用clickhouse所在服务器的百分之
			八九十即可。
		3.4.3 建表时的索引粒度选择
			建表是的索引粒度的选择也是一个值得考究的问题。基于clickhouse在你数据插入时产生的
			小文件的问题,数据在插入ck前最好按照你的索引字段排序写入,同时你的索引字段的粒度
			选择不能够在单次插入时产生大量不同粒度的索引。比如上面的例子,你单次插入10000条
			数据,你按照小时和按照天选取的索引粒度最终产生的小文件数量肯定是不一致的。那么是
			不是索引粒度越粗糙越好呢,你还需要考虑你的业务查询时的性能,你业务最可能最经常查
			询的的粒度是什么,你就可以根据这两个必要条件去做均衡,选择你最适合的索引的粒度。
		3.4.4 and so on
			社区不是很友好,资料不是很多,所以,坑还有很多,需要自己不断的踩。但是香还是很香
			的。
	3.5 flink的日志解析
		解析流程(偷懒贴个流程图就好,代码很简单,有需要的可以私聊哈)

在这里插入图片描述

	3.6 superset的应用
		superset的选用来说,简单易用。加上我对这个很精通(手动狗头)。这就是一个开源的BI工具,免费,易用,可开发性也比较强。
		偷懒,扔一个图上来。

实时需求

ck的性能

	贯彻偷懒原则,放几个在我们有限的集群资源下的ck的单表查询性能图,自行同其他存储做对比
	1.集群资源
		六个ck节点(其中一个等同于不可用,资源太少),单节点64g内存,7200机械磁盘(管够),100M带宽
	2.测试表情况
		200亿行,30个字段,50T。
--sql语句
SELECT COUNT(1) from ods.px_nginx_raw pnr;

count查询

--sql语句
select count(1),toYYYYMMDD(time_iso8601 ) from ods.px_nginx_raw pnrp   group by toYYYYMMDD(time_iso8601 ) order by toYYYYMMDD(time_iso8601 ) desc;

查询每天的数据量

猜你喜欢

转载自blog.csdn.net/flyinthesky111/article/details/106801139
今日推荐