前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从 Clickhouse 到 Snowflake: 云原生

从 Clickhouse 到 Snowflake: 云原生

作者头像
腾讯数据库技术
发布2021-09-07 15:40:10
1.9K0
发布2021-09-07 15:40:10
举报

云原生Clickhouse

优势概述

以Clickhouse为基础,借鉴Snowflake等系统的设计思路,打造一款高性能的云原生OLAP系统,为用户提供多场景下的一站式的数据分析平台。

  • 简单、易维护:集群管理、统一共享分布式调度服务
  • 高可用、可扩展:支持500万以上的Table
  • 低成本:存储成本至少降低了50%
  • 兼容开源,复用超高性能:兼容协议、语法、数据库存储格式

Clickhouse是一款性能十分强悍的OLAP引擎,凭借优秀的性能在用户行为分析、ABTest、在线报表等多个领域大放异彩,但是目前Clickhouse在易用性、稳定性、可维护性、功能特性等方面都还有较多不足,主要体现在以下几方面:

  • 易用性方面,需要用户感知本地表、分布式表、Zookeeper等概念,在建表、导入、查询等流程中都有涉及,后期Schema Change时也需要分别做处理,使用门槛较高;
  • 稳定性方面,重度依赖Zookeeper,Zookeeper已经成为明显的中心化瓶颈,尤其在多副本场景下单机的写入、Merge、DDL的执行都需要经过Zookeeper协调,一旦Zookeeper不稳定或者代码有Bug,整个分布式集群都会不稳定;
  • 可维护性方面,缺少节点加入、节点退出、副本均衡等必要的分布式管理功能,一旦集群数量变多,维护代价巨大;
  • 功能特性方面,没有真正的MPP查询层,在分布式Join、聚合等方面能力不足,语法上也不符合相关标准,有一定的学习成本;

Snowflake 是当下最火的云原生数仓,它SaaS化的设计理念极大的提升了数据开发者的使用体验,Clickhouse高性能的存储引擎和计算算子是一个非常优秀的底座,我们希望以Clickhouse为基础,借鉴Snowflake的设计思路,打造一款高性能的云原生OLAP系统,为用户提供多场景下的一站式的数据分析平台,包括:

  • HTAP 场景,与腾讯CDB、CynosDB等无缝集成,实时同步OLTP系统中的变更,基于列存和并行执行引擎,实现海量数据下的亚秒级分析;同时支持MySQL协议和语法,无缝兼容用户现有的工具,达到零迁移成本。
  • 数仓场景,支持用户数据实时入仓,为用户提供超高性能的在线分析服务;针对结构化、半结构化数据,实现统一的分析解决方案,利用Clickhouse丰富可扩展的算子,构建简单易用的流式处理框架简化ETL流程。
  • 数据湖场景,支持对象存储COS、CFS、Elasticsearch、MongoDB等多数据源的查询,通过跟多个数据源做深度的整合,利用高速的向量化执行引擎,提升多源数据的分析能力及性能。

云原生Clickhouse架构设计

存算分离正在数据库领域掀起一场变革,不论OLTP还是OLAP系统都在拥抱存算分离。通过对Clickhouse的源码进行阅读分析,发现在Clickhouse中一旦实现了存算分离,那么稳定性、可维护性以及成本等方面的问题都会迎刃可解。Clickhouse虽然在分布式集群管理方面很弱,但是这也意味着在改造存算分离架构时的负担很少,成为了一个巨大的优势,所以我们把存算分离作为第一个目标,希望通过引入存算分离技术,并且围绕存算分离技术对分布式集群管理等各个方面进行改造,为用户提供一个更好的Clickhouse。

云原生Clickhouse的架构设计如下图,具体包括三层:

(云原生Clickhouse架构设计图)

集群管理层:分布式集群的大脑,它主要包含基于分布式一致性协议实现的元数据管理服务、多集群共享的分布式任务调度服务;

计算层:用户通过创建的计算集群来实际使用分析服务,每个计算集群由多个节点组成,用户的查询任务在一个计算集群上的节点里完成,同一个用户的多个计算集群可共享集群管理层;

存储层:基于共享存储实现,用户的所有数据都存放在共享存储内,可以被多个计算集群访问,同时它提供了廉价、按需、无限扩展的存储能力;

数据流

  • 用户直接连接Clickhouse Node,而不是Master Node,所以可以通过现有的Clickhouse工具连接和使用;
  • 数据流在多个Clickhouse Node之间传输,不会经过Master Node,所以不会成为中心化瓶颈;

控制流

  • 控制流不再依赖Zookeeper来协调,而是通过一个全局共享的Master Node来实现;
  • 所有的分布式DDL命令都转发给Master Node,由Master Node协调DDL任务在各个节点上的执行,Master控制DDL的并发、失败处理;
  • Master Node存储了全局的、统一的Schema信息,为后续的MPP查询层打下了元数据的基础;
  • Master Node控制节点加入和退出等集群管理工作;
  • 由于Master服务是非常轻量的,所以可以在多个集群之间共享,能有效的降低部署Zookeeper带来的成本开销;

基于共享存储的存算分离机制

  • 强一致,数据存放到共享存储上,各个节点可以有一致的数据视图,任何一个节点写入数据,其他副本均立即可见;
  • 基于共享存储我们实现了Insert、Mutation、Alter等任务的冲突处理机制;
  • Merge/Mutation过程可以在任意一个副本上执行,多个节点可以Merge不同的Part,在高速导入的情况下,能加速Merge的速度,快速的减少底层小文件数量;

云原生Clickhouse核心特性

易使用,易运维

过去在运维一个Clickhouse集群时,很头疼的一点就是集群管理,例如,我们要向集群中增加一个节点,需要以下操作:

  • 启动新的节点;
  • 在新节点上创建本地表和分布式表,为了获取已创建的表信息,就需要到其他节点上查询,如果表比较多就需要脚本来配合,相信运维Clickhouse的同学都积累了不少脚本-;
  • 修改所有节点的配置文件Metrica.xml,把新节点信息写入,生效;

在新架构下,Master维护了全局统一的元数据信息,使得我们可以通过一条条简单的SQL命令来自动化集群管理, 例如下面这个命令就是向集群中增加一个副本节点:

代码语言:javascript
复制
ALTER CLUSTER cluster_name ADD BACKEND 'ip:port' TO SHARD  2;

这个命令首先会修改Master统一管理的元数据,然后新增的Clickhouse Node会从Master上同步相关元数据,更新本地配置,最终用户可以在Clickhouse上运行以下命令来获取集群的节点信息,同时当前Clickhouse的各种查询语句也可以继续使用集群的拓扑结构来构建复杂的查询:

代码语言:javascript
复制
SELECT * FROM SYSTEM.CLUSTERS;

此外,用户不需要再使用ReplicatedMergeTree引擎,不需要关注元数据在Zookeeper上的存储路径,只需要普通的MergeTree引擎即可,系统内部会自动为每个表分配唯一的数据存储路径,并且使互为副本的多个表共用存储空间。

代码语言:javascript
复制
CREATE TABLE t1 (
	partition_col_1 String,
	tc1 int,
	tc2 int)
ENGINE=MergeTree() 
PARTITION BY partition_col_1 
ORDER BY tc1;

统一共享的分布式任务调度服务

              (分布式DDL任务执行流程图)

在引入Master Node后,分布式DDL任务的执行流程如上图所示,下面以Create Table为例介绍一下具体的流程:

  • 用户连接任意一个Clickhouse Node发送Create Table on cluster 请求,该节点做初步的解析后,把这个命令以一个DDL Job的形式发送给Master;
  • Master Node做DDL Job的解析,把Job转化为需要发送给集群内所有Clickhouse Node的DDL Task,每一个Task都是建立Local Table;
  • Clickhouse Node执行完DDL Task之后给Master返回成功消息;
  • Master做元数据的持久化,并且给客户端Clickhouse Node1 返回成功消息;

基于Master的分布式架构还具备以下特点:

高可用:Master Node自身多副本,多副本之间通过一致性协议保证高可用。同时,我们考虑了Master Node和ClickHouse Node间的松耦合设计,即使Master Node全部故障,也不影响存量业务的普通读写操作,仅限制新DDL操作的执行。

并发控制:Master Node能够区分对不同Table的DDL请求,可以控制不同请求的并发级别,比如对于Alter是顺序执行,对于Mutation可以并发执行。

回滚机制:DDL Task不一定能够在所有的Clickhouse Node上全部成功,部分成功是常态;过去Clickhouse 在这种情况下会出现各个Clickhouse Node的状态不一致,我们引入了回滚机制,如果任意一个任务失败,整个Job就会失败,保持各个Clickhouse Node的状态一致.

垃圾清理机制:Clickhouse Node自身会定时的跟Master Node做状态同步,清理本地的垃圾Table或者数据目录。

基于存算分离架构的多副本

多副本技术是分布式系统底层存储的核心的机制,任何一个分布式系统都有大量的代码在处理多副本, Clickhouse 面临的很多问题也是由于多副本引起的。当前Clickhouse的多副本机制如下所示:

           (当前Clickhouse多副本机制)

当前架构有以下缺陷:

  • 依赖Zookeeper存储Log、Parts信息,在Local Table数量变多、数据量变多、导入频繁后会成为瓶颈,所以可以看到业界有很多改进都在设法降低Zookeeper中存储的元数据量,或者把不同的表放到不同的Zookeeper集群中;
  • 成本高,云上一般都是使用云磁盘,Clickhouse继续做副本结果导致磁盘存储成本高。比如云磁盘自身3副本,Clickhouse的ReplicationMergeTree 2副本,结果最后数据实际是6副本;此外云上很多客户都是中小客户,很多客户的Clickhouse集群的规模小于10,而Zookeeper本身就需要3个节点,带来了一些附加成本;

 使用了共享存储之后,我们支持多读多写的模型,多副本管理的架构如下:

方案概要:

  • 数据放到共享存储上,一个批量数据写入会产生一个Part;
  • 通过一个Commit Log记录Part的变更,比如Add Part, Remove Part等信息;
  • 所有的Clickhouse Replica读取Commit Log,根据Commit Log中记录的操作,更新本机内存中的Part列表信息,由于Part数据文件在共享存储上,所以不需要拉数据,直接加载就好。

 为了能够让所有的副本都可以提供读写服务,基于Commit Log,我们增加了冲突处理机制,思路如下图所示:

         (冲突处理机制思路图)

  • 每个part 有一个唯一的UUID,不再使用part name做文件夹名字,而是使用uuid做文件夹名字,因为使用part name作为文件夹名字会带来名字冲突;
  • Commit Log提供写的冲突、回放机制,上层的Clickhouse进程写入Commit Log遇到冲突时,需要Replay CommitLog 然后重新提交Part信息;
  • Commit Log定期做Snapshot,一方面可以做Commit Log的回收,另外一方面也降低每次重启获取最新元数据的时间。

在存算分离架构下,成本相对于原来有大幅度降低:

  • 多个副本之间共享物理存储,相比过去2副本的情况下,存储成本至少降低一半;
  • 每个集群不需要单独部署Zookeeper,可以省去至少3个节点的资源成本;
  • 多读多写的模型,不存在只读备份节点的资源浪费,可提升资源利用率。

同时,多读多写的模型消除了传统主从副本在故障时的复杂切换逻辑,任意节点挂掉,其他副本都可以轻松接管读写,大幅提高系统可用性。

高可用无状态的数据服务层

Clickhouse社区目前有基于S3的多副本机制,也能够降低多副本带来的存储成本,但是这种方案目前有以下问题:

  • 共享存储需要依赖Zookeeper来协调,比如记录part的引用计数信息,Zookeeper记录的元数据更多了,每个Clickhouse Node与Zookeeper的交互更多了;
  • 在每个Clickhouse Node上仍需要记录一部分信息:
    • 在Metadata目录下仍保留存储表的元数据;
    • 每个数据文件会对应一个本地小文件,存储了数据文件到S3对象的映射关系;
  • 由于本地元数据的存在,所以Clickhouse Node本身不是无状态的,有以下问题:
    • 在节点宕机磁盘损坏时,这部分元数据就丢了,存储到S3上的数据在缺少元数据的情况下,也是不可用的;
    • 副本迁移的时候,虽然不需要拷贝数据了,但是元数据仍然需要同步,仍然使用了当前的多副本机制,在线上运维过程中发现这块代码的问题还是比较多的;

我们的改造思路是把所有的元数据都与本地存储剥离,使得基于Clickhouse的计算层彻底无状态:

  • Master Node保存了表的Schema元数据信息,每个Clickhouse Node本地的元数据只是一个缓存,一旦丢失,立即从Master同步;
  • 重新实现的基于共享存储的Part管理机制,将Part所有的信息都放到共享存储上,本地不再保存;

在存算分离模式下,多副本的目标已经从保证数据的可靠性转变为保证服务的可用性,通过把每个副本本地的状态消除,可以任意增加副本的数目,提升服务的可用性而不需要付出存储成本;另外还可以做到查询级别的调度,根据每个节点的健康状况和负载情况,把查询调度到合适的节点上来执行,而不需要复杂的多副本同步,服务整体的可用性大幅度提升。

秒级的弹性伸缩能力

在数据服务层完全无状态后,除了高可用之外,带来的一个巨大的优势是弹性,节点的加入和退出不需要复杂的数据同步机制,可以在秒级完成集群的伸缩:

  • 新节点加入时只需要从Master上获取表的Schema元数据,再从共享存储上获得Part元数据信息,就可以直接提供服务了,可以在秒级完成;
  • 旧节点删除,不需要等待数据迁移完成,可以直接下线,可以在秒级完成;

集群能够在秒级完成扩缩容有以下优势:

  • 低成本,分析型业务对系统资源的需求有明显的波峰、波谷的特点,例如,白天的资源消耗比晚上多,工作日比周末多,通过制定合适的集群伸缩计划可以显著降低对资源的需求;
  • 高性能,过去数据和节点是绑定的关系,一直遵循着计算跟着数据走的原则,而数据是在节点本地,所以计算是很难扩展的,当计算层无状态后,在一些场景下(比如大查询)可以直接扩充更多的计算节点,快速完成查询任务。

持续兼容开源生态

在改造Clickhouse的过程中,我们跟很多不同的团队做了一些交流,发现一个非常大的问题就是大家对Clickhouse做了大量的修改,然而由于各种原因这部分代码没能合并到社区,最终跟社区分叉了,所以出现了XXX版本Clickhouse;这一幕在过去10年的大数据历程中反复出现,我们都见过XXX公司内部版本的HDFS、HBase、Kafka等,而这些所谓的自研版本几乎都失败了。Clickhouse的功能迭代速度是很快的,比如最近社区推出的LLVM表达式优化、异步的Pipeline执行、zOrder等,都是非常重要的feature,对性能提升十分明显,一旦分叉这些功能就都用不上了,所以我们坚信兼容Clickhouse社区虽然会慢点,我们的设计会复杂点,但是会走的更远。

对于一个云服务而言,我们面对着各种各样的用户,很多用户的诉求是我们提供的Clickhouse能够跟随社区的版本升级。所以我们在项目伊始就定下了一个原则----尽量少的侵入Clickhouse,能够跟进开源社区Clickhouse进行持续升级。

(模块结构图)

模块结构如上图所示,在我们的架构中,Clickhouse实际是一个单机的库,所以虽然我们实现了复杂的控制流和存算分离的功能,但是通过精巧的设计,基本上对Clickhouse没有侵入,改动了极少的代码,这使得后续的版本升级更加方便,能够随时合并Clickhouse社区的最新功能。

通过把Clickhouse进行云原生改造,与现状相比有以下优势:

优势总结

简单、易维护:通过简单易用的集群管理、统一共享的分布式任务调度服务,可以大幅降低运维人员的运营压力,降低用户的使用门槛,运维同学可以一键完成集群伸缩、用户可以统一入口简单完成DDL操作等,整个系统更为简单易维护。

高可用、可扩展:整个系统的架构设计有充分的可用性考虑,各组件的容灾能力都颇具创新,后续也会继续增强;此外,消除了Zookeeper这个明显的中心化瓶颈后,系统支持的数据量可无限扩展,表数量仅受限于Master Node内存,在压力测试中,能够支持500万以上的Table,可覆盖绝大部分需求。

低成本:通过存算分离技术,存储成本至少降低了50%,消除了副本间的冗余写入开销,也去除了Zookeeper带来的附加成本;多读多写的模型保障了各个副本之间实时强一致,用户不需要在导入性能和一致性等级之间做权衡;资源调度方面,用户也可以根据集群的负载情况,秒级的弹性伸缩集群资源,可用于降低成本,也可用于提升一部分场景下的查询性能。

• 兼容开源,复用超高性能:持续完整的兼容性,对外的协议、语法、数据存储格式都完全兼容Clickhouse现有的版本,用户可以很方便的迁移,也可以充分享用ClickHouse的超高性能。

未来工作 

  • MPP架构的查询引擎:这部分已经在紧张的设计开发中,我们以Clickhouse当前的向量化算子为基础,增加查询优化器、分布式join、聚合计算等功能,预期在今年晚些时候上线;除了支持Clickhouse之外,高性能的MPP执行框架还将支持对HDFS、对象存储、MySQL、Hive、Elasticsearch等多个数据源的查询,提升多源数据查询的速度。
  • 消除Shard,实现简单完全的分布式化:Shard是分布式领域的一个重要概念,主要是做数据在各个节点上的分布打散,然而这是分布式系统自身内部的逻辑,用户一般无需关注Shard,用户希望看到的是一个高度抽象、类单机的分布式系统。此外,当前数据副本和机器绑死的Shard方式,不利于充分发挥分布式系统在伸缩、故障恢复时的潜能,比如扩容时要求成倍进行、故障恢复时压力全部集中在少量节点上。所以我们也在努力改变这种使用方式方式,降低用户的使用负担或顾虑。

腾讯数据库技术团队对内支持QQ空间、微信红包、腾讯广告、腾讯音乐、腾讯新闻等公司自研业务,对外在腾讯云上依托于CBS+CFS的底座,支持TencentDB相关产品,如CynosDB、CDB、CTSDB、MongoDB、CES等。腾讯数据库技术团队专注于持续优化数据库内核和架构能力,提升数据库性能和稳定性,为腾讯自研业务和腾讯云客户提供“省心、放心”的数据库服务。此公众号旨在和广大数据库技术爱好者一起推广和分享数据库领域专业知识,希望对大家有所帮助。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-09-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯数据库技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档