写点什么

看云上 ClickHouse 如何做计算存储分离

发布于: 2021 年 01 月 05 日
看云上 ClickHouse 如何做计算存储分离

2020 年 12 月 6 日-7 日,由 InfoQ 中国主办的综合性技术盛会 QCon 全球软件开发大会深圳站召开。QCon 内容源于实践并面向社区,演讲嘉宾依据热点话题,面向资深的技术团队负责人、架构师、工程总监、开发人员分享技术创新和实践。


在 QCon 盛会上,腾讯云大数据专家工程师陈龙为大家带来了题为《看云上 ClickHouse 如何做计算存储分离》的分享,以下是分享整理全文。


各位朋友大家好,我是陈龙,我今天给大家分享的内容是:看云上 ClickHouse 如何做计算存储分离。



首先介绍下我自己,我来自腾讯云大数据团队,2011 年加入腾讯,先后主导开发了腾讯云 Redis,云数据库 HBase 以及 EMR 等多款云产品的开发工作,在多个开源社区贡献过代码,目前专注于腾讯云 EMR 和云数仓 ClickHouse 的开发工作,我今天分享的内容主要分为三部分: 


一、腾讯云云数仓 ClickHouse 的演进过程 


二、腾讯云在 ClickHouse 计算存储分离的实现 


三、基于计算存储分离架构下的未来规划



1. 腾讯云云数仓 ClickHouse 的演进过程 


我们首先来看数据仓库的演进过程,数据仓库到目前为止大致分为 4 代,在第一代,数据库主要应用于 OLTP 场景,并采用共享存储架构, 因此被称为事务型数据库。这一阶段,由于 OLAP 场景尚不成熟,因此分析型数据库(即“数据仓库”) 尚未完全从事务型数据库中完全脱离出来,以采用 Oracle、DB2 等共享存储架构的事务型数据库为主。在这一阶段,数仓存在的问题是价格昂贵,且受到共享存储架构影响,可扩展性较差,扩展到十几个节 点就会遇到存储瓶颈,仅能适应面向管理层的报表分析需求,但无法适应更大规模、更多用户的数据分析场景。


在第二代,主要是面向分析型场景的无共享架构的 MPP 数据仓库,在一定程度上解决了因共享存储 架构带来的扩展性难题。但是由于它基于大型机、专有硬件,还有软件架构的限制,因此扩展性仍然难 以达到数千节点级别,且扩展成本昂贵,但是,MPP 也存在固有缺陷,一方面,无共享架构导致了其难 以实现上千节点的扩展,另一方面,计算与存储节点的绑定也使得其扩展灵活性不够,难以适应工作负载变化更快的数据分析场景的需求。


在第三代,主要是以 SQL-on-Hadoop 的方式来构建数据仓库,尽管 SQL-on-Hadoop 数仓在硬件 架构上仍然基于无共享架构,但在软件架构层面实现了计算与存储的完全分离。因此,相比于 MPP 数 仓,SQL-on-Hadoop 数仓进一步提升了扩展灵活性,降低了存储节点的管理难度,节点规模上限被提 升到几千节点,但是,由于底层存储系统 HDFS 的只读特点,SQL-on-Hadoop 数仓普遍存在一系列缺 点,比如对传统 SQL 兼容性不足,对 Update/Delete 等更新操作和混合工作负载(OLTP+OLAP 场 景)支持性较差,对事务型数据库所必备的 ACID 特性缺乏支持。


第四代,云原生数仓,随着云计算的兴起,数据仓库逐步开始云化。相比于部署在物理硬件上的数 仓,云数仓的优势在于能够支持云的按需取用、弹性扩容特性,有效提升数仓的扩展效率,降低扩展成 本和运维难度,早期的云数仓更像是将物理硬件环境的数仓打包到云环境中,并没有基于云环境的许多 特性对数仓进行深度原生优化。



技术演进的目的是为了成本和更加易于,我们首先来看成本问题。


无论什么样的架构,其服务承载的基本单位就是服务器,我们先从单台服务器来看数据分析的成本问 题,对一台服务器来看其核心成本分为三个部分:


CPU 以及芯片组,占整机成本的 50% 左右


内存存储芯片,占整机成本的 15% 左右


外部存储,占整机成本的 10% 左右 


在传统模式下,这些资源强绑定在一起,造成的问题是计算浪费或者是存储浪费,结果就是成本升高, 解决的办法是计算和存储解耦,这也是目前大数据分析领域里一种新的尝试。


再从性能角度看,一台服务器 IO 磁盘 IO 能力为单盘 IO* 磁盘数,出于成本考虑,假设采用的是 HDD 的设备,10 块盘的设备其磁盘 IO 能力约是 2.5GB/s,而随着在云环境下硬件架构演进,整机网络 IO 能力都是 100GB 起,其 IO 能力远超普通磁盘 IO 能力,同时结合合理的索引以及数据结 构设计,能够带来更强的数据扫描能力,同时云上对象存储的容量可以理解为无上限,可以让存储集群 的维护成本降为 0,其按存储量计费的模式,可以大大降低存储成本,云上海量的计算资源可以保证数据 仓库的计算需求,那么我们接下看基于云的存储计算分离、资源弹性、统一存储如何构建云上云原生数仓。



站在云数据仓库视角看,主要满足企业中三种角色人员的需求,云的发展让 IAAS 进入了工业化时 代,而云数仓的目的也是要让数据分析进入工业化时代


对企业 CEO 而言,企业的成本能够得到合理的控制,企业利润率需要有所保障,同时对企业经营的数 据能做到实时或者时效性更高。



对企业运维而言:


第一是需要有 serverless 的能力,通过 serverless 能力降低运维成本进而可以聚焦于业务本身,第二是 具备按需配置的能力,用多少量付多少费 第三是具备良好的数据安全性 第四是具备良好的扩展能力,在业务到达峰值或者负载到达瓶颈的时候能够提供分钟级扩容能力。


对企业开发者而言:


第一是需要具备良好的 SQL 能力,serverless 化的产品屏蔽了复杂的集群细节,可以让企业开发者通过 SQL 更加聚焦于业务,使用门槛更低, 第二是具有强大的性能能力,满足日常交互式查询分析 第三是能够满足数据流动性需求,使各种业务系统、日志等数据简单的能够入仓 第四是具备良好的易用性,主要体现在数据管理、查询管理等。


那么针对要满足如上三种角色的需求,那么云数仓的架构应该是这样的管控层。


面向运维人员和开发人员提供计算资源管理、存储资源管理、数据管理、和各类人员的权限认证能力接入层。


面向开发人员,提供 SQL 接入、JDBC、以及 cli 接入的能力,可以根据访问者提供认证和授权,简化应用开发。


执行计划解释层:根据用户输入的 SQL 生成执行计划,并进行分区裁剪等,同时根据数据的分布进行计算任务的生成,同时跟踪每个 SQL 的执行情况。


执行层:负责执行 coordinator 下发过来计算任务,负责节点状态上报以及 metric 等信息的上报。


存储层:负责底层数据的物理存储,根据成本可以是云上对象存储、文件存储、云盘或者是 CHDFS。


从架构上来看,ClickHouse 并不符合这种架构,那么我们为什么采用改造 ClickHouse 来构建云上数仓呢,是因为 ClickHouse 在多维聚合查询分析场景中极致的性能,那么我们来看看 ClickHouse 在性能 方面有哪些黑科技



要达到好的性能,其核心是通过良好的数据结构以及算法,充分利用硬件,以达到最佳性能,我们首 先来看看在多维聚合查询场景下 ClickHouse 的性能表现: 相同单节点,同等配置的情况下,数据体量一亿规模条件下,ClickHouse 的平均响应速度是:


• Vertica 的 2.63 倍


• InfiniDB 的 17 倍


• MonetDB 的 27 倍


• MySQL 的 429 倍


• Greenplum 的 10 倍


• Spark 的 1 倍


那么 ClickHouse 是使用了哪些新技术或者黑科技呢,其实 ClickHouse 使用的技术并不新鲜,核心为两点:


第一是向量执行 


向量化执行就是利用寄存器硬件层面的特性,为上层应用程序的性能带来了指数级的提升。为了实现向 量化执行,需要利用 CPU 的 SIMD(Single Instruction Multiple Data,即用单条指令操作多条数据) 指令,它是通过数据并行来提高性能,原理就是在 CPU 寄存器层面实现数据的并行操作。


CPU 的三级缓存(包括 L1 一级缓存、L2 二级缓存、L3 三级缓存)都是集成在 CPU 内的缓存,它们的 作用都是作为 CPU 与主内存之间的高速数据缓冲区,L1 最靠近 CPU 核心;L2 其次;L3 再次。运行速度方面:L1 最快、L2 次快、L3 最慢;容量大小方面:L1 最小、L2 较大、L3 最大。


CPU 会先在最快的 L1 中寻找需要的数据,找不到再去找次快的 L2,还找不到再去找 L3,L3 都没有那就只能去内存找了。通过向量化,充分利用 CPU 的各级 Cache 以达到最佳性能。


第二是 MergeTree


MergeTree 是 ClickHouse 最为核心的数据结构,其核心处理数据结构的基本单位为 Block,Block 在 写入磁盘的时候转换为 Parts,针对每个 parts 存储采用了列式存储和稀疏索引的方式来提高查询效率, 索引可以通过 granularity 来控制粒度,


同时通过数据标记文件快速定位文件,以上是 clickhouse 优先的一面,如果我们基于 clickhouse 去构 建云数仓,还有哪些工作需要改造以及哪些不完善的,我们来看 ClickHouse 的整体架构:



ClickHouse 架构上总体分为 4 层:


第一层为协议接入层,在接入层 ClickHouse 支持 4 种类型的协议接入:Reust HTTP 方式,方便各种异构客户端接入,比如 python,nodejs 等。ClickHouse Native,通过 ClickHouse 协议 TCP 的方式接入,性能会更好。Mysql 可以通过 mysql 客户端或者管理工具直接连接 ClickHouse。Postgresql 可以通过 Postgresql 客户端或者 sdk 接入。


第二是语义解析层,负责 SQL 语法以及语义解析、分区裁剪等。


第三是 Interpreters 层,负责各种 groupby、join 等算子的计算。


第四是存储引擎,存储引擎是 ClickHouse 最为核心的部分,负责了表数据的存储和读取,目前 ClickHouse 支持 3 种类型存储引擎:


日志类,以 Log、TinyLog、StripeLog 为代表,主要使用在日志存储方面。


MergeTree 系列是 ClickHouse 使用最为广泛的存储引擎,主要使用在明细数据的场景和适合聚合数据 的场景。


外部存储引擎比如 HDFS、COS 对象存储、Kafka 等,只支持查询和写入,不支持更新, 目前以及支持 的外部数据源已经超过 18 种, 同时 ClickHouse 支持外部存储支持的数据格式也支持多种,比如 CSV、 ORC,JSON 等多种数据格式。


虽然 ClickHouse 目前在多维聚合查询方便有优秀的能力,但是如果要将 ClickHouse 云化为云数 仓,还有很多工作需要做:


  • 分布式不友好 目前 ch 分布式环境下,数据同步依赖 zookeeper,在表的数据以及写入量到达一定规模的时候, zookeeper 很容易成为瓶颈,影响稳定性。

  • 计算存储不分离 目前 ClickHouse 存储和设备强绑定,虽然支持 s3、hdfs 等外部存储,但是其核心存储引擎 mergetree 并不能使用。

  • 大表 join clickhouse 目前 join 算法是类似 mapjoin 的实现,对于超大表的 join 受限于单节点内存,无法满足 扩容数据自均衡能力。


目前 ClickHouse 集群扩容后数据无法自动均衡,需要手动操作,门槛比较高 数据实时更新。且目前 clickhouse 对于更新后的数据,其可见性依赖于后台的合并线程执行情况,在某些实时性较高的场 景无法满足需求。


针对以上问题,云 ClickHouse 其中部分问题已经解决,另外部分问题也在开发当中,接下来我会重点 介绍腾讯云云数仓 ClickHouse 在存储计算分离方面的方案。


2. 腾讯云云数仓 ClickHouse 计算存储分离实现


接下来我们看腾讯云云数仓 ClickHouse 计算存储分离实现,要实现 ClickHouse 的计算存储分离,我们首先来看 ClickHouse 的 IO 路径,ClickHouse 的读写 IO 路径是:


以 insert 为例,访问接入层在在接受到 insert 语句后,经过语法解析,然后调用请求解释器的 insert 方法,在这过程会通过语法解析获取到要写入的数据表,然后找到表对于的存储引擎,从表存储引擎中 得到 BlockOutputStream 对象,调用输出流的 write 方法将数据写出到输出流。


而读取的过程为:查询请求的 SQL 经过访问接入层,语法分析器将 SQL 解析为 queryblock,在从 queryblock 中提取到要读取的表,进而查找到表对应的存储引擎,获取到 BlockInputStream 对象, 调用 read 方法读取数据,由解释器层各种算子对数据进行计算。



因此在整个过程中我们可以看到在 ClickHouse 中表引擎至关重要,表引擎(即表的类型)决定了: 数据的存储方式和位置,写到哪里以及从哪里读取数据。支持哪些查询以及如何支持。并发数据访问。索引的使用(如果存在)。是否可以执行多线程请求。数据复制参数。


云 ClickHouse 计算存储分离方案基于 mergertree 表引擎进行改进,我们接下来 mergetree 架构设计。



在 clickHouse 中存储引擎有两个比较重要重要的接口,IStorage 和 ISource 表通过 IStorage 接口来表示,对此接口不同的实现成为不同的表引擎. 例如 StorageMergeTree, StorageHDFS 等,Istorage 最重要的方法是读和写操作以及存储策略,也有 alter, rename, drop, 等操作。


接口 ISource , 外部数据源读取接口,其实现有 HDFSSource、KafkaSource 等,外部存储引擎在 ClickHouse 中称为集成表引擎。


这里我们重点关注存储策略接口,一个存储策略描述了存储卷、存储介质之间的关系,目前腾讯云 ClickHouse 计算存储分离正是基于存储策略进行的,接下来我们看存储策略。



从宏观层面,一个数据表可以设置表的存储策略,一个存储策略可以有多个存储卷,一个存储卷可以 设定多个 Disk,在业务上可以设置数据写的存储策略,也可以将数据移动到特定的存储磁盘或者卷上, 接下我们看存储策略、存储卷以及磁盘的定义。


  • 存储策略


负责管理存储卷列表,定义当期存储策略下数据移动策略,以及磁盘预留等,默认情况下 ClickHouse 的默认存储策略为 default,存储策略是一个逻辑结构,不负责任何的 IO 请求。


  • 存储卷


存储卷可以认为是一系列存储磁盘的集合,定义了每块磁盘可以写入的数据量以及预留的空间等,同时 控制数据写盘顺序,它同样是一个逻辑结构,不负责任何的 IO 处理


  • Disk


持久化 clickhouse 数据的接口,该接口的核心方法有: 创建文件夹、删除文件、写文件、设置磁盘预留等,这里的 Disk 不等同于块设备,而是 ClickHouse 读 写底层存储系统的一个接口,默认情况下 clickhouse 实现了 localdisk。


基于上面的架构,腾讯云的 ClickHouse 服务计算存储分离的架构是定义 cloud 存储策略,该存储策略下设置一个存储卷,在该存储卷下挂载对象存储 Disk,和文件存储 Disk 以及云盘, 因此基于 ClickHouse 计算存储分离其核心就变为扩展云存储,让其成为 Disk,接下来我们看如何实现:



右侧是 IDisk 接口的类图结构,IDisk 接口集成自 Space 接口,该接口主要描述磁盘名称,以及 Disk 预留信息,而 IDisk 接口本身核心的方法有: 移动文件、读文件、写文件以及判断文件是否存在等,IDisk 默认实现有 DiskLocal 也就是本地磁盘, DiskS3,而在 DiskS3 中其实现的方式是索引文件和标记文件以及元数据文件强制存储在本机磁盘。


而只有数据文件则存储在对象存储,那么在这种实现下是无法实现计算存储分离的, 原因是文件索引数据以及元数据还在本机,无法释放计算资源,Disk3 之所有这样 实现是因为对象存储本质是一个 KV 存储,没有文件系统元数据的概念,其 list 和 rename 存在性能问题。


list 则是通过字符串前缀匹配实现,而 rename 则是通过拷贝加删除实现,而 ClickHouse 在数据写入以及数据合并的时候存在大量的 rename 操作,先生成临时文件,数据生成成功后在在 rename 到目标文件,这个特性大大的限制了 ClickHouse 上的写入速度。


因此腾讯云 clickhouse 实现 的方式是:扩展实现云存储 COSDisk,改进 PartsWriter 和 MergePartsWriter,检测存储类型为云存储的时候直接写目标文件,通过对象存 储的碎片文件特性来保证可见性。


通过规避 rename 大大的提高了数据写入和合并的速度,那在实现 ClickHouse 支持云存储后,我们来 看如何应用这些特性来达到数据自动沉降和存储计算分离。



假设现在有这样一张数据表,里面包含 4 种类型的数据 热数据,近一个月经常要使用的数据,为了查询效率期望保存在高速存储上,比如存储介质是 SSD 的这 种存储上,随着时间的推移, 这部分数据变成了温数据,查询或者使用的频率不是那么的高,期望自动沉降到常规存储介质上。


比如 HDD 的存储介质上,而更久的数据则使用频率更低,期望 自动沉降到云存储比如对象存储上,更早的数据希望自动删除,结合之前的介绍,我们实现了云存储 Disk,目前 ClickHouse 数据沉降策略支持按照 TTL、手动以及容量因子三种 方式进行沉降,接下来我们如何实现:



在磁盘列表里我们首先配置三种存储 Disk,分别为:SSD、HDD、和对象存储 COS,接着我们配置存储策略 cloud,在此存储策略下我们配置三种。


存储卷分别是:热存储 hot、温存储 warm、和冷存储 cold,接着我们创建数据表 example,在表的属 性里去设置: 多长时间的数据自动进入温存储,多长时间的数据进入冷存储,多长时间的数据需要删除,同时这些策略还可以直接到 DISK,策略的设置不仅仅支持表维度,还支持列维度的 数据自动沉降,在某些情况下,如果我们需要手动将某些数据移动到特性的存储,我们直接通过 SQL 就 可以进行,在介绍完数据沉降应用之后,我们在看另一种计算存储完全分离的场景。



Clickhouse 原生情况下支持数据的 sharding 和数据复制,也就是 clickhouse 的分布式表,Click- House 的分布式表更像是一种映射 local 表的视图,分布式表不负责任何数据的存储,我们首先从写路径看:


在分布式表写的情况下,当客户端连接到任一集群节点进行写的时候,该节点会按照 sharding key 把 数据分发到其他节点,分布式表维护了一个集群配置,在该配置里配置了每个 shard 的 shardID 和副本数,如果副本数大于 1,则会复制数据到其他 shard 在读的场景下,客户端连接到任一集群节点进行读的时候,会根据集群 shard 的配置,转发查询到其他 shard,把数据拉回到本地节点做合并后返回给客户端,也就是支撑查询的数据量受限于节点的内存。


而当存储全部为云存储的情况下,即不存在 sharding 的时候,默认情况下每个节点看到的数据都一样 的,这样会导致错误,因此我们需要改进内核,对数据进行分区,每个节点处理不同分区的数据,数据交换通过 Shuffle 后生成最终结果,改进后整个 ClickHouse 的查询能力不在受限于单节点的能力,计算可以水平 无限扩展,同时我们把 ClickHouse 的元数据针对云存储的这种情况也进行重构,通过这种改进后,即使集群释放存储的数据还在,当需要查询或者计算的时候可以快速拉起集群进行计算,还可以结合实际业务,在负 载较低的时候维护一个较小的集群,当负载较高的时候快速扩容提升查询效率,通过这种计算存储分离 的模式,大大降低了实时交互查询的成本。


接下来我们看看腾讯云 ClickHouse 的一个总体架构。



目前腾讯云 clickhouse 架构上总体分为四层: 


  • 管控层


管控层分为资源原理,主要是调度和管理底层 IAAS 基础设施层,集群管理主要服务集群进程、状态、配 置以及自动化生成等,Metrices 系统负责采集各个模块的监控数据并上报云监控,而智能诊断 则负责集群监控读以及 QueryTrace 等基础诊断功能,方便快速定位问题。


  • 服务层


Coordinator、负责执行计划生成以及节点管理,统一元数据服务,管理集群 schema 信息,认证和权 限提供基于 SQL 的用户认证和用户权限认证


  • 弹性计算层


根据文件进行分片计算,并进行计算结果的 shuffle,最后输出数据。


  • 存储层


云上统一存储层,根据成本和效率选择不同的存储作为数仓的存储层。总体技术架构上采用共享存储的架构设计,通过计算存储分离重复利用云的弹性能力,和无限存储扩 展能力,下面是目前腾讯云 ClickHouse 的一个产品截图:



在监控方面提供了从 IAAS 基础设计到 ClickHouse 服务维度的各种监控,同时基于传统 ClickHouse 扩展数据自均衡问题,我们还开发了集群扩容数据自动迁移服务,接下来我们看 clickhouse 比较主流的应用。



假设数仓 ClickHouse 有 n 个分区,数据写入的方式可以通过 SDK 客户端直接写入而更常见的是通 过 Hadoop 离线计算平台导入或者是 flink 流式以及 Kafka 直接摄入,在这种应用场景中比较优雅的方式是:


Spark 的一个分区对应 ClickHouse 的一个分区,或者 Kafka 的 topic 分区对应 ClickHouse 的分区, 这样性能可以达到最优,数据写入的方式可以是 Spark 或者 Flink 直接写入到 ClickHouse 也可以通过消息中间件在流入 Kafka,写入的时候应该尽量大批次写,尽量规避小批次多次写,因为 ClickHouse 底层 数据结构是 mergetree,写入过于频繁会因为合并而导致性能下降。


如上是腾讯云 ClickHouse 计算存储方面的一些优化分享,第三部分我介绍腾讯云在 ClickHouse 方面的一些规划。


3. 腾讯云在 ClickHouse 方面的规划


腾讯云云数仓 ClickHouse 在产品层面的规划主要围绕 3 个方向展开:


第一是管控,在集群构建方面提供分钟级集群构建,同时提供 api 和 SDK 方便客户进行二次开发,同时结合云的弹 性能力,深度优化集群横向扩容能力以及数据均衡服务,降低使用和运维成本。


第二是智能诊断,智能诊断将会围绕云基础设施以及 ClickHouse 服务本身进行建设,提供从 IAAS 层到服务层立体化的 监控告警能力,同时提供巡检和智能分析快速定位问题。


第三是数据流动和性能,将会围绕无缝对接接云上消息中间件、数据库对象存储等多种数据源,方便客户进行数据分析 同时我们也会在内核方面深度优化,以最大可能的提高性能降低成本,接下来是在内核方面的规划。



在内核方面的规划分为三部分,第一部分为内核增强,主要方向是位图索引,加速 bitmap 类应用的查询效率 提供支持实时更新的存储引擎,以方便对接流计算等场景下的应用 支持 insert ignore 语义满足数据更新需求 谓词下推到存储,进一步提升查询性能。


第二部分是性能增强和架构改进,针对对象存储进行深度优化,解决 list 和 rename 带来的性能问题,同时通过构建合理的索引设计来降 低对网络流量的依赖 第二是线程模型改进,现在的服务器都有很多个核,常规手段是通过锁机制来解决并发问题,这种模型 并不高效,因此需要针对新硬件架构改进线程模型。


第三是目前 ClickHouse 数据的复制依赖 zookeeper,在 parts 数较多的时候,zookeeper 会带来性能和稳定性的问题。


第三是从内核层面上进行成本优化,第一个计算存储分离,第二 ClickHouse 计算容器化,第三是支持存储分级。



因为部分技术涉及到产品的商业保密性,细节这里不会展开。以上是我今天分享,谢谢各位。




关注“腾讯云大数据”公众号,技术交流、最新活动、服务专享一站 Get~


用户头像

还未添加个人签名 2020.06.19 加入

欢迎关注,邀您一起探索数据的无限潜能!

评论

发布
暂无评论
看云上 ClickHouse 如何做计算存储分离