前言
Databend 在 2021 年开源后,陆续受到了很多社区同学的关注。Databend 应用了 Rust 编程语言。为了吸引更多的开发者,特地是没有 Rust 开发教训的新同志,咱们设计了 Rust 相干课程,同时建设了多个 Rust 兴趣小组。
Databend 在 issue 中还引入了“Good First issue”的 label 来疏导社区新同学参加第一次奉献,目共有超过一百多位 contributors,算是一个不错的成绩。
但 Databend 也在过来的一年中经验了数次迭代,代码日渐简单。目前代码骨干分支有 26 w 行 rust 代码,46 个 crate,对于新接触 Databend 的技术爱好者来说,奉献门槛越来越高。即便是相熟 rust 的同学,clone 代码后,面对着茫茫码海,竟不知如何读起。在多个社区群中,也有敌人数次提到什么时候能有一个 Databend 源码浏览系列文章,帮忙大家更快相熟 Databend 代码。
因而,咱们接下来会发展“Databend 源码浏览”系列文章,次要受众是社区技术开发者,心愿通过源码浏览,来增强和社区的技术交换,引发更多思维碰撞。Databend 的故事
Databend 的故事
很多同学都问过咱们一个问题:为什么你们要用 Rust 从零构建一个数据库?其实这个问题能够分为两个子问题:
1. 为什么抉择的是 Rust?
答:咱们晚期的成员大多是 ClickHouse、tidb、tokudb 等出名数据库的贡献者,从技术栈来说更相熟的是 C++ 和 Go。虎哥 @bohutang 在疫情期间也应用 Go 实现了一个小的数据库原型 vectorsql 有同学示意 vectorsql 的架构十分优雅,值得学习借鉴。
语言本没有孰劣之分,要从面向的场景来聊聊。目前大多的 DMBS 应用的是 C++/Java,新型的 NewSQL 更多应用的是 Go。在以往的开发教训来看,C/C++ 曾经是高性能的代名词,开发者更容易写出高运行效率的代码,但 C++ 的开发效率切实不忍直视,工具链不是很欠缺,开发者很难一次性写出内存平安,并发平安的代码。而 Go 可能是另外一个极其,大道至简,工具链欠缺,开发效率十分高,不足之处在于泛型的进度太慢了,在 DB 零碎上内存不能很灵便的管制,且难于达到前者的运行性能,尤其应用 SIMD 指令还须要和汇编代码交互等。咱们须要的是兼具 开发效率(内存平安,并发平安,工具链欠缺)& 运行效率 的语言,过后看来,Rust 可能是咱们惟一的抉择了,历经尝试后,咱们也发现,Rust 不仅能满足咱们的需要,而且很酷!
2. 为什么要从零构建一个数据库系统?
总体来说,路线无非就以下两条:
- 基于出名的开源数据库做二次开发优化
这条路线可能更多人会抉择,因为有一个好的数据库底座,无需再做一些重复性的工作,在下面做二次开发的话能省不少力量,团队专一做优化改良重构,能更早推动版本,落地商业化。毛病是 fork 后的版本难于再次回馈到社区,相当于另外一套独立的零碎,如 PG 下的各个子流派。
- 从零构建一套新的数据库系统
这条路线走起来比拟艰巨,因为数据库系统切实太宏大了,一个子方向都足够专业人士深入研究十几年。这个方向尽管没能间接站在已有的底座上,但会让设计者更加灵便可控,无需关注太多历史的包袱。Databend 在设计之初面向的是云原生数仓的场景,和传统的数据库系统有很大的区别,如果基于传统数据库系统来做,革新代码的老本和从零做的老本可能差不多,因而咱们抉择的是这条路来从零打造一个全新的云数仓。
Databend 的架构
画虎画皮难画骨,咱们先从 Databend 的“骨”聊起
尽管咱们是应用 Rust 从零开始实现的,但不是齐全闭门造轮子,一些优良的开源组件或者生态也有在其中集成。如:咱们兼容了 Ansi-SQL 规范,提供了 MySQL/ClickHouse 等支流协定的反对,拥抱了万物互联的 Arrow 生态,存储格局基于大数据支流的 Parquet 格局等。咱们不仅会踊跃地回馈了奉献给上游,如 Arrow2/Tokio 等开源库,一些通用的组件咱们也抽成独立的我的项目开源在 Github(openraft, opendal, opencache, opensrv 等)。
Databend 定义为云原生的弹性数据库,在设计之初咱们不仅要做到计算存储拆散,每一层的极致的弹性都是设计次要考量点。Databend 次要分为三层:MetaService Layer,Query Layer,Storage Layer,这三层都是能够弹性扩大的,意味着用户能够为本人的业务抉择最适宜的集群规模,并且随着业务倒退来伸缩集群。
上面咱们将从这三层来介绍下 Databend 的次要代码模块
Databend 的模块
-
MetaService Layer
MetaService 次要用于存储读取长久化的元数据信息,比方 Catalogs/Users 等。
包名 | 作用 |
---|---|
metasrv | MetaService 服务,作为独立过程部署,可部署多个组成集群,底层应用 Raft 做分布式共识,Query 以 Grpc 和 MetaService 交互。 |
common/meta/types | 定义了各类须要保留在 MetaService 的构造体,因为这些构造体最终须要长久化,所以波及到数据序列化的问题,以后应用 Protobuf 格局来进行序列化和反序列化操作,这些类型相干的 Rust 构造体与 Protobuf 的互相序列化规定代码定义在 common/proto-conv 子目录中。 |
common/meta/sled-store | 以后 MetaService 应用 sled 来保留长久化数据,这个子目录封装了 sled 相干的操作接口。 |
common/meta/raft-store | openraft 用户层须要实现 raft store 的存储接口用于保留数据,这个子目录就是 MetaService 实现的 openraft 的存储层,底层依赖于 sled 存储,同时这里还实现了 openraft 用户层须要自定义的状态机。 |
common/meta/api | 对 query 裸露的基于 KVApi 实现的用户层 api 接口。 |
common/meta/grpc | 基于 grpc 封装的 client,MetaService 的客户端应用这里封装好的 client 与 MetaService 进行通信交互。 |
raft | https://github.com/datafusela…,从 async-raft 我的项目中衍生改良的全异步 Raft 库。 |
-
Query Layer
Query 节点次要用于计算,多个 query 节点能够组成 MPP 集群,实践上性能会随着 query 节点数程度扩大。SQL 在 query 中会经验以下几个转换过程
从 SQL 字符串通过 Parser 解析成 AST 语法树,而后通过 Binder 绑定 catalog 等信息转成逻辑打算,再通过一系列优化器解决转成物理打算,最初遍历物理打算构建对应的执行逻辑。query 波及的模块有:
包名 | 作用 | |
---|---|---|
query | Query 服务,整个函数的入口在 bin/databend-query.rs 其中蕴含一些子模块,这里介绍下比拟重要的子模块:1.api:对外裸露给内部的 HTTP/RPC 接口 2.catalogs:catalogs 治理,目前反对默认的 catalog(存储在 metaservice)以及 hive catalog(存储在 hive meta store)3.Clusters:query 集群信息 4.Config:query 的配置相干 5.databases:query 反对的 database engine 相干 6.evaluator:表达式计算工具类 7.Interpreters:SQL 执行器,SQL 构建出 Plan 后,通过对应执行器去做物理执行 8.pipelines:实现了物理算子的调度框架 9.Servers:对外裸露的服务,有 clickhouse/mysql/http 等 10. Sessions:session 治理相干 11. Sql:蕴含新的 planner 设计,新的 binder 逻辑,新的 optimizers 设计 12. Storages:表引擎相干,最罕用为 fuse engine13. table_functions:表函数相干,如 numbers | |
common/ast | 基于 nom_rule 实现的新版 sql parser | |
common/datavalues | 各类 Column 的定义,示意数据在内存上的布局,后续会逐渐迁徙到 common/expressions | |
common/datablocks | Datablock 示意 Vec<Column> 汇合,外面封装了一些罕用办法, 后续会逐渐迁徙到 common/expressions | |
common/functions | 标量函数以及聚合函数等实现注册 | |
common/hashtable | 实现了一个线性探测的 hashtable,次要用于 group by 聚合函数以及 join 等场景 | |
common/formats | 负责数据对外各类格局的 序列化反序列化,如 CSV/TSV/Json 格局等 | |
opensrv | https://github.com/datafusela… |
-
Storage Layer
Storage 次要波及表的 Snapshots,Segments 以及索引信息等治理,以及和底层 IO 的交互。Storage 目前一大亮点是基于 Snapshot 隔离 实现了相似 Iceberge 形式的 Increment view, 咱们能够对表在任意历史状态下进行 time travel 拜访。
后续布局
源码浏览系列刚刚开始撰写,后续预计将依照介绍各个模块的形式进行逐渐解说,输入次要以文章为主,一些比拟重要且乏味的模块设计可能会以视频直播的形式和大家一起交换。
目前只是一个初步的布局,在这个过程中会承受大家的倡议做一些工夫内容调整。无论如何,咱们都期待通过这个系列的流动,让更多气味相投的人参加到 Databend 的开发中来,一起学习交换成长。对于 Databend 对于 DatabendDatabend 是一款开源、弹性、低成本,基于对象存储也能够做实时剖析的旧式数仓。期待您的关注,一起摸索云原生数仓解决方案,打造新一代开源 Data Cloud。
对于 Databend
Databend 是一款开源、弹性、低成本,基于对象存储也能够做实时剖析的旧式数仓。期待您的关注,一起摸索云原生数仓解决方案,打造新一代开源 Data Cloud。
- Databend 文档:https://databend.rs/
- Twitter:https://twitter.com/Datafuse_…
- Slack:https://datafusecloud.slack.com/
- Wechat:Databend
- GitHub:https://github.com/datafusela…
文章首发于公众号:Databend