大数据技术与架构 大数据技术与架构git
2020年下半年在OLAP领域有一匹黑马以席卷之势进入大数据开发者的领域,它就是ClickHouse。在2019年小编也曾介绍过ClickHouse,你们能够参考这里进行入门:github
来自俄罗斯的凶猛彪悍的分析数据库-ClickHouse
基于ClickHouse的用户行为分析实践
Prometheus+Clickhouse实现业务告警算法
那么咱们有必要先从全局了解一下ClickHouse究竟是个什么样的数据库?
ClickHouse是一个开源的,面向列的分析数据库,由Yandex为OLAP和大数据用例建立。ClickHouse对实时查询处理的支持使其适用于须要亚秒级分析结果的应用程序。ClickHouse的查询语言是SQL的一种方言,它支持强大的声明性查询功能,同时为最终用户提供熟悉度和较小的学习曲线。
ClickHouse全称是Click Stream,Data Warehouse,简称ClickHouse就是基于页面的点击事件流,面向数据仓库进行OLAP分析。ClickHouse是一款开源的数据分析数据库,由战斗民族俄罗斯Yandex公司研发的,Yandex是作搜索引擎的,就相似与Google,百度等。
咱们都知道搜索引擎的营收主要来源与流量和广告业务,因此搜索引擎公司会着重分析用户网路流量,像Google有Anlytics,百度有百度统计,那么Yandex就对应于Yandex.Metrica。ClickHouse就式在Yandex.Metrica下产生的技术。
面向列的数据库将记录存储在按列而不是行分组的块中。经过不加载查询中不存在的列的数据,面向列的数据库在完成查询时花费的时间更少。所以,对于某些工做负载(如OLAP),这些数据库能够比传统的基于行的系统更快地计算和返回结果。sql
根据官网的介绍(https://clickhouse.tech/benchmark/dbms/),ClickHouse在相同的服务器配置与数据量下,平均响应速度:数据库
ClickHouse主要特色:设计模式
ClickHouse 采用了典型的分组式的分布式架构,集群架构以下图所示:
这其中的角色包括:安全
ClickHouse的特性有不少,一款被承认的OLAP引擎可以获得你们的频繁使用必定是有独特的特性,小编列举了几个ClickHouse异于常人的特性:
列式存储&数据压缩
按列存储与按行存储相比,前者能够有效减小查询时所需扫描的数据量,这一点能够用一个示例简单说明。假设一张数据表A拥有50个字段A1~A50,以及100行数据。如今须要查询前5个字段并进行数据分析,那么经过列存储,咱们仅需读取必要的列数据,相比于普通行存,可减小 10 倍左右的读取、解压、处理等开销,对性能会有质的影响。
若是数据按行存储,数据库首先会逐行扫描,并获取每行数据的全部50个字段,再从每一行数据中返回A1~A5这5个字段。不难发现,尽管只须要前面的5个字段,但因为数据是按行进行组织的,实际上仍是扫描了全部的字段。若是数据按列存储,就不会发生这样的问题。因为数据按列组织,数据库能够直接获取A1~A5这5列的数据,从而避免了多余的数据扫描。
按列存储相比按行存储的另外一个优点是对数据压缩的友好性。ClickHouse的数据按列进行组织,属于同一列的数据会被保存在一块儿,列与列之间也会由不一样的文件分别保存 ( 这里主要指MergeTree表引擎 )。数据默认使用LZ4算法压缩,在Yandex.Metrica的生产环境中,数据整体的压缩比能够达到8:1 ( 未压缩前17PB,压缩后2PB )。列式存储除了下降IO和存储的压力以外,还为向量化执行作好了铺垫。性能优化
坊间有句玩笑,即"能用钱解决的问题,千万别花时间"。而业界也有种调侃一模一样,即"能升级硬件解决的问题,千万别优化程序"。有时候,你千辛万苦优化程序逻辑带来的性能提高,还不如直接升级硬件来得简单直接。这虽然只是一句玩笑不能当真,但硬件层面的优化确实是最直接、最高效的提高途径之一。向量化执行就是这种方式的典型表明,这项寄存器硬件层面的特性,为上层应用程序的性能带来了指数级的提高。
向量化执行,能够简单地看做一项消除程序中循环的优化。这里用一个形象的例子比喻。小胡经营了一家果汁店,虽然店里的鲜榨苹果汁深受你们喜好,但客户老是抱怨制做果汁的速度太慢。小胡的店里只有一台榨汁机,每次他都会从篮子里拿出一个苹果,放到榨汁机内等待出汁。若是有8个客户,每一个客户都点了一杯苹果汁,那么小胡须要重复循环8次上述的榨汁流程,才能榨出8杯苹果汁。若是制做一杯果汁须要5分钟,那么所有制做完毕则须要40分钟。为了提高果汁的制做速度,小胡想出了一个办法。他将榨汁机的数量从1台增长到了8台,这么一来,他就能够从篮子里一次性拿出8个苹果,分别放入8台榨汁机同时榨汁。此时,小胡只须要5分钟就可以制做出8杯苹果汁。为了制做n杯果汁,非向量化执行的方式是用1台榨汁机重复循环制做n次,而向量化执行的方式是用n台榨汁机只执行1次。
为了实现向量化执行,须要利用CPU的SIMD指令。SIMD的全称是Single Instruction Multiple Data,即用单条指令操做多条数据。现代计算机系统概念中,它是经过数据并行以提升性能的一种实现方式 ( 其余的还有指令级并行和线程级并行 ),它的原理是在CPU寄存器层面实现数据的并行操做。
在计算机系统的体系结构中,存储系统是一种层次结构。典型服务器计算机的存储层次结构如图1所示。一个实用的经验告诉咱们,存储媒介距离CPU越近,则访问数据的速度越快。
从上图中能够看到,从左向右,距离CPU越远,则数据的访问速度越慢。从寄存器中访问数据的速度,是从内存访问数据速度的300倍,是从磁盘中访问数据速度的3000万倍。因此利用CPU向量化执行的特性,对于程序的性能提高意义非凡。
ClickHouse目前利用SSE4.2指令集实现向量化执行。服务器
相比HBase和Redis这类NoSQL数据库,ClickHouse使用关系模型描述数据并提供了传统数据库的概念 ( 数据库、表、视图和函数等 )。与此同时,ClickHouse彻底使用SQL做为查询语言 ( 支持GROUP BY、ORDER BY、JOIN、IN等大部分标准SQL ),这使得它平易近人,容易理解和学习。由于关系型数据库和SQL语言,能够说是软件领域发展至今应用最为普遍的技术之一,拥有极高的"群众基础"。也正由于ClickHouse提供了标准协议的SQL查询接口,使得现有的第三方分析可视化系统能够轻松与它集成对接。在SQL解析方面,ClickHouse是大小写敏感的,这意味着SELECT a 和 SELECT A所表明的语义是不一样的。
关系模型相比文档和键值对等其余模型,拥有更好的描述能力,也可以更加清晰地表述实体间的关系。更重要的是,在OLAP领域,已有的大量数据建模工做都是基于关系模型展开的 ( 星型模型、雪花模型乃至宽表模型 )。ClickHouse使用了关系模型,因此将构建在传统关系型数据库或数据仓库之上的系统迁移到ClickHouse的成本会变得更低,能够直接沿用以前的经验成果。网络
也许由于Yandex.Metrica的最初架构是基于MySQL实现的,因此在ClickHouse的设计中,可以察觉到一些MySQL的影子,表引擎的设计就是其中之一。与MySQL相似,ClickHouse也将存储部分进行了抽象,把存储引擎做为一层独立的接口。截至本书完稿时,ClickHouse共拥有合并树、内存、文件、接口和其余6大类20多种表引擎。其中每一种表引擎都有着各自的特色,用户能够根据实际业务场景的要求,选择合适的表引擎使用。
一般而言,一个通用系统意味着更普遍的适用性,可以适应更多的场景。但通用的另外一种解释是平庸,由于它没法在全部场景内都作到极致。
在软件的世界中,并不会存在一个可以适用任何场景的通用系统,为了突出某项特性,势必会在别处有所取舍。其实世间万物都遵循着这样的道理,就像信天翁和蜂鸟,虽然都属于鸟类,但它们各自的特色却铸就了彻底不一样的体貌特征。信天翁擅长远距离飞行,环绕地球一周只须要1至2个月的时间。由于它可以长时间处于滑行状态,5天才须要扇动一次翅膀,心率可以保持在每分钟100至200次之间。而蜂鸟可以垂直悬停飞行,每秒能够挥动翅膀70~100次,飞行时的心率可以达到每分钟1000次。若是用数据库的场景类比信天翁和蜂鸟的特色,那么信天翁表明的多是使用普通硬件就能实现高性能的设计思路,数据按粗粒度处理,经过批处理的方式执行;而蜂鸟表明的多是按细粒度处理数据的设计思路,须要高性能硬件的支持。
将表引擎独立设计的好处是显而易见的,经过特定的表引擎支撑特定的场景,十分灵活。对于简单的场景,可直接使用简单的引擎下降成本,而复杂的场景也有合适的选择。
ClickHouse几乎具有现代化高性能数据库的全部典型特征,对于能够提高性能的手段可谓是一一用尽,对于多线程和分布式这类被普遍使用的技术,天然更是不在话下。
若是说向量化执行是经过数据级并行的方式提高了性能,那么多线程处理就是经过线程级并行的方式实现了性能的提高。相比基于底层硬件实现的向量化执行SIMD,线程级并行一般由更高层次的软件层面控制。现代计算机系统早已普及了多处理器架构,因此现今市面上的服务器都具有良好的多核心多线程处理能力。因为SIMD不适合用于带有较多分支判断的场景,ClickHouse也大量使用了多线程技术以实现提速,以此和向量化执行造成互补。
若是一个篮子装不下全部的鸡蛋,那么就多用几个篮子来装,这就是分布式设计中分而治之的基本思想。同理,若是一台服务器性能吃紧,那么就利用多台服务的资源协同处理。为了实现这一目标,首先须要在数据层面实现数据的分布式。由于在分布式领域,存在一条金科玉律—计算移动比数据移动更加划算。在各服务器之间,经过网络传输数据的成本是高昂的,因此相比移动数据,更为聪明的作法是预先将数据分布到各台服务器,将数据的计算查询直接下推到数据所在的服务器。ClickHouse在数据存取方面,既支持分区 ( 纵向扩展,利用多线程原理 ),也支持分片 ( 横向扩展,利用分布式原理 ),能够说是将多线程和分布式的技术应用到了极致。
HDFS、Spark、HBase和Elasticsearch这类分布式系统,都采用了Master-Slave主从架构,由一个管控节点做为Leader统筹全局。而ClickHouse则采用Multi-Master多主架构,集群中的每一个节点角色对等,客户端访问任意一个节点都能获得相同的效果。这种多主的架构有许多优点,例如对等的角色使系统架构变得更加简单,不用再区分主控节点、数据节点和计算节点,集群中的全部节点功能相同。因此它自然规避了单点故障的问题,很是适合用于多数据中心、异地多活的场景。
ClickHouse常常会被拿来与其余的分析型数据库做对比,好比Vertica、SparkSQL、Hive和Elasticsearch等,它与这些数据库确实存在许多类似之处。例如,它们均可以支撑海量数据的查询场景,都拥有分布式架构,都支持列存、数据分片、计算下推等特性。这其实也侧面说明了ClickHouse在设计上确实吸收了各路奇技淫巧。与其余数据库相比,ClickHouse也拥有明显的优点。例如,Vertica这类商用软件价格高昂;SparkSQL与Hive这类系统没法保障90%的查询在1秒内返回,在大数据量下的复杂查询可能会须要分钟级的响应时间;而Elasticsearch这类搜索引擎在处理亿级数据聚合查询时则显得捉襟见肘。
正如ClickHouse的"广告词"所言,其余的开源系统太慢,商用的系统太贵,只有Clickouse在成本与性能之间作到了良好平衡,即又快又开源。ClickHouse当之无愧地阐释了"在线"二字的含义,即使是在复杂查询的场景下,它也可以作到极快响应,且无须对数据进行任何预处理加工。
数据分片是将数据进行横向切分,这是一种在面对海量数据的场景下,解决存储和查询瓶颈的有效手段,是一种分治思想的体现。ClickHouse支持分片,而分片则依赖集群。每一个集群由1到多个分片组成,而每一个分片则对应了ClickHouse的1个服务节点。分片的数量上限取决于节点数量 ( 1个分片只能对应1个服务节点 )。
ClickHouse并不像其余分布式系统那样,拥有高度自动化的分片功能。ClickHouse提供了本地表 ( Local Table ) 与分布式表 ( Distributed Table ) 的概念。一张本地表等同于一份数据的分片。而分布式表自己不存储任何数据,它是本地表的访问代理,其做用相似分库中间件。借助分布式表,可以代理访问多个数据分片,从而实现分布式查询。
这种设计相似数据库的分库和分表,十分灵活。例如在业务系统上线的初期,数据体量并不高,此时数据表并不须要多个分片。因此使用单个节点的本地表 ( 单个数据分片 ) 便可知足业务需求,待到业务增加、数据量增大的时候,再经过新增数据分片的方式分流数据,并经过分布式表实现分布式查询。这就比如一辆手动挡赛车,它将全部的选择权都交到了使用者的手中。
关于ClickHouse的安装,咱们在这里再也不详细展开,官网有详细的文档能够参考。
咱们使用Java客户端链接ClickHouse进行一些简单的操做。首先Clickhouse 有两种 JDBC 驱动实现:
一种是官方给出的
<dependency> <groupId>ru.yandex.clickhouse</groupId> <artifactId>clickhouse-jdbc</artifactId> <version>0.2.4</version> </dependency>
还有一种第三方提供的驱动:
<dependency> <groupId>com.github.housepower</groupId> <artifactId>clickhouse-native-jdbc</artifactId> <version>2.5.2</version> </dependency>
二者间的主要区别以下:
驱动类加载路径不一样,分别为
ru.yandex.clickhouse.ClickHouseDriver 和 com.github.housepower.jdbc.ClickHouseDriver
默认链接端口不一样,分别为 8123 和 9000
链接协议不一样,官方驱动使用 HTTP 协议,而三方驱动使用 TCP 协议
须要注意的是,两种驱动不可共用,同个项目中只能选择其中一种驱动。
Class.forName("com.github.housepower.jdbc.ClickHouseDriver"); Connection connection = DriverManager.getConnection("jdbc:clickhouse://192.168.60.131:9000"); Statement statement = connection.createStatement(); statement.executeQuery("create table test.example(day Date, name String, age UInt8) Engine=Log"); PreparedStatement pstmt = connection.prepareStatement("insert into test.example values(?, ?, ?)"); // insert 10 records for (int i = 0; i < 10; i++) { pstmt.setDate(1, new Date(System.currentTimeMillis())); pstmt.setString(2, "panda_" + (i + 1)); pstmt.setInt(3, 18); pstmt.addBatch(); } pstmt.executeBatch(); Statement statement = connection.createStatement(); String sql = "select * from test.jdbc_example"; ResultSet rs = statement.executeQuery(sql); while (rs.next()) { // ResultSet 的下标值从 1 开始,不可以使用 0,不然越界,报 ArrayIndexOutOfBoundsException 异常 System.out.println(rs.getDate(1) + ", " + rs.getString(2) + ", " + rs.getInt(3)); }
经过 clickhouse-client 命令行界面查看表状况:
ck-master :) show tables; SHOW TABLES ┌─name─────────┐ │ hits │ │ jdbc_example │ └──────────────┘ ck-master :) select * from example; SELECT * FROM jdbc_example ┌────────day─┬─name─────┬─age─┐ │ 2019-04-25 │ panda_1 │ 18 │ │ 2019-04-25 │ panda_2 │ 18 │ │ 2019-04-25 │ panda_3 │ 18 │ │ 2019-04-25 │ panda_4 │ 18 │ │ 2019-04-25 │ panda_5 │ 18 │ │ 2019-04-25 │ panda_6 │ 18 │ │ 2019-04-25 │ panda_7 │ 18 │ │ 2019-04-25 │ panda_8 │ 18 │ │ 2019-04-25 │ panda_9 │ 18 │ │ 2019-04-25 │ panda_10 │ 18 │ └────────────┴──────────┴─────┘
从2019年起,已经有不少大厂开始在生产环境使用ClickHouse,小编在这里根据各大公司使用状况做了一些总结,适用场景、方案、优化等等。
下图是携程实际应用ClickHouse的架构图,底层数据大部分是离线的,一部分是实时的,离线数据如今大概有将近 3000 多个 job 天天都是把数据从 HIVE 拉到 ClickHouse 里面去,实时数据主要是接外部数据,而后批量写到 ClickHouse 里面。数据智能平台 80%以上的数据都在 ClickHouse 上面。
同时,携程还存在全量数据同步和增量数据同步的场景。
全量数据同步的流程流程以下图:
QQ音乐大数据团队基于ClickHouse+Superset等基础组件,结合腾讯云EMR产品的云端能力,搭建起高可用、低延迟的实时OLAP分析计算可视化平台。
集群日均新增万亿数据,规模达到上万核CPU,PB级数据量。总体实现秒级的实时数据分析、提取、下钻、监控数据基础服务,大大提升了大数据分析与处理的工做效率。
经过OLAP分析平台,极大下降了探索数据的门槛,作到全民BI,全民数据服务,实现了实时PV、UV、营收、用户圈层、热门歌曲等各种指标高效分析,全链路数据秒级分析定位,增强数据上报规范,造成一个良好的正循环。
面对上万核集群规模、PB级的数据量,通过QQ音乐大数据团队和腾讯云EMR双方技术团队无数次技术架构升级优化,性能优化,逐步造成高可用、高性能、高安全的OLAP计算分析平台。
(1)基于SSD盘的ZooKeeper
ClickHouse依赖于ZooKeeper实现分布式系统的协调工做,在ClickHouse并发写入量较大时,ZooKeeper对元数据存储处理不及时,会致使ClickHouse副本间同步出现延迟,下降集群总体性能。
解决方案:采用SSD盘的ZooKeeper大幅提升IO的性能,在表个数小于100,数据量级在TB级别时,也可采用HDD盘,其余状况都建议采用SSD盘。
(2)数据写入一致性
数据在写入ClickHouse失败重试后内容出现重复,致使了不一样系统,如Hive离线数仓中分析结果,与ClickHouse集群中运算结果不一致。
解决方案:基于统一全局的负载均衡调度策略,完成数据失败后仍然可写入同一Shard,实现数据幂等写入,从而保证在ClickHouse中数据一致性。
(3)实时离线数据写入
ClickHouse数据主要来自实时流水上报数据和离线数据中间分析结果数据,如何在架构中完成上万亿基本数据的高效安全写入,是一个巨大的挑战。
解决方案:基于Tube消息队列,完成统一数据的分发消费,基于上述的一致性策略实现数据幂同步,作到实时和离线数据的高效写入。
(4)表分区数优化
部分离线数据仓库采用按小时落地分区,若是采用原始的小时分区更新同步,会形成ClickHouse中Select查询打开大量文件及文件描述符,进而致使性能低下。
解决方案:ClickHouse官方也建议,表分区的数量建议不超过10000,上述的数据同步架构完成小时分区转换为天分区,同时程序中完成数据幂等消费。
(5)读/写分离架构
频繁的写动做,会消耗大量CPU/内存/网卡资源,后台合并线程得不到有效资源,下降Merge Parts速度,MergeTree构建不及时,进而影响读取效率,致使集群性能下降。
解决方案:ClickHouse临时节点预先完成数据分区文件构建,动态加载到线上服务集群,缓解ClickHouse在大量并发写场景下的性能问题,实现高效的读/写分离架构,具体步骤和架构以下:
a)利用K8S的弹性构建部署能力,构建临时ClickHouse节点,数据写入该节点完成数据的Merge、排序等构建工做;
b)构建完成数据按MergeTree结构关联至正式业务集群。
固然对一些小数据量的同步写入,可采用10000条以上批量的写入。
(6)跨表查询本地化
在ClickHouse集群中跨表进行Select查询时,采用Global IN/Global Join语句性能较为低下。分析缘由,是在此类操做会生成临时表,并跨设备同步该表,致使查询速度慢。
解决方案:采用一致性hash,将相同主键数据写入同一个数据分片,在本地local表完成跨表联合查询,数据均来自于本地存储,从而提升查询速度。
这种优化方案也有必定的潜在问题,目前ClickHouse尚不提供数据的Reshard能力,当Shard所存储主键数据量持续增长,达到磁盘容量上限须要分拆时,目前只能根据原始数据再次重建CK集群,有较高的成本。ClickHouse从进入大众视野到开始普遍应用实践并不久,ClickHouse社区也在飞速发展中。ClickHouse仍然年轻,虽然在某些方面存在不足,但极致性能的存储引擎,使得ClickHouse成为一个很是优秀的存储底座。