日前,字节跳动技能社区 ByteTech 举办的第四期字节跳动技能沙龙满意落幕,本期沙龙以《字节云数据库架构规划与实战》为主题。在沙龙中,字节跳动根底架构数据库开发工程师马浩翔,跟大家探讨了 《从单机到分布式数据库存储体系的演进》,本文依据同享收拾而成。
存储体系概览
存储体系是指能高效存储,耐久化用户数据的一系列体系软件。在众多的存储体系中,以下是三类比较干流的存储产品及其特色剖析:
块存储
- 底层语义,依据 block 编程;
- 接口朴素:在 Linux 的 IO 软件栈中,要直接运用块存储的话就要依据 LBA 编程,因而接口较为简单朴素,再加上块存储本身处于整个存储软件栈的底层,这导致块存储运用起来并不十分友爱;
- 寻求低时延、高吞吐:研制一个块存储体系,在规划方针上咱们往往会寻求超高的功能,体现在超低的时延和超高的吞吐。但考虑到块存储的接口的确过于朴素,往往只需一些寻求超高功能的体系才会直接依据块存储构建,然后自建应用层 cache。
方针存储
- 公有云上的主力存储产品:在 IT 年代,“Everything is data”的趋势敏捷催化了方针存储体系。尤其关于字节跳动的事务而言,运用方针存储体系来处理视频、图片、音频等非结构化的数据,语义最为自然;
- 非结构化数据,供给 immutable 语义:一旦图片或视频等非结构化数据上传至方针存储体系成功,则无法对其进行原地修正,只能经过删去旧数据,重新上传新数据的方式完结“修正”逻辑;
- 本钱优先:一般不苛求单次操作的时延,可是十分注重体系吞吐 & 存储本钱。
文件体系
- 接口语义丰厚,普适性强:遵从 POSIX/弱 POSIX 语义,诸如 Open、Write、Read 等许多操作数据的接口都能在文件体系中被找到。
- 具有较多开源的分布式完成,生态良好。
- 一般也不苛求时延,注重体系吞吐 & 存储本钱。
单机数据库存储解析
单机数据库存储,要从内存层和耐久化层两个方面来解析。在内存层,仅说联系型数据库,其内存数据结构特色能够总结为:一切都是“树”。咱们以最常见的 B+ 树为例,B+ 树具有以下杰出的特色:
- In memory 操作功率十分高: B+ 树查找时刻复杂度是 log 等级;而且 B+ 树的叶子节点构成链表,十分有利于在内存中对数据进行 scan 操作。
- 磁盘操作功率高: B+ 树的 Fanout 足够大,树的层级较少,呈矮胖状,能够削减磁盘 IO 数;一起 B+ 树的非叶子节点只存索引数据,叶子节点存实际数据,能大大紧缩树高,进一步削减磁盘 IO 数。
- 数据结构高度一致: 数据 & 索引都能够直接组织成 B+ 树,因而代码的可保护性、可读性和开发功率都比较好。
仅有内存数据结构当然是不行的,咱们还需求规划高效的磁盘数据结构,下图展现了从内存数据结构到磁盘数据结构的数据耐久化进程:
左面虚线框描绘的是 In Memory 结构暗示图。举个比如,如果咱们要修正 Page A 的某一行数据,对其中的一个字段进行自增,自增值是 2。自然而然会产生一个数据库的物理操作日志,即 Redo Log,用来描绘咱们对 Page A 的修正。一起,在数据库的事务履行进程中,或许还会产生很多暂时数据(图里的 Temp data),当内存不行用的时分也需求将其耐久化。
右边虚线框描绘的是 In Persistent Layer 的暗示图。假设咱们运用比较友爱的文件体系来将内存数据耐久化,咱们需求设置不同的文件,让它们各司其职。例如图里的蓝色文件存储 Page,绿色文件存储 Redo Log,粉色文件存储暂时数据。如果数据库产生 crash ,在康复阶段咱们就在各类文件中进行数据定位,结合 Redo Log File 和 Page File ,进行数据库的数据康复。除此之外,如果直接依据块存储进行耐久化,就需求数据库本身的存储引擎办理好 LBA,需求在用户态里边完成 buffer cache 等逻辑,这也是可行的。
那么依据单机的 FS / 块存储去做耐久化,咱们会遇到哪些问题呢? 经过下面的单机数据库体系的典型架构图,咱们能够发现三个问题:
- 单机容量瓶颈: 在 Database 层的单机服务器上运行着 database 进程,服务器上挂载了很多本地磁盘用作数据耐久化。但一台物理服务器能挂载的磁盘容量总是有限的,这就导致了单机的容量瓶颈问题。
- 扩缩容困难: 当容量、CPU 或许内存等资源不行时,咱们需求进行扩容。在单机年代,扩容意味着将数据从这个磁盘搬家到另一个磁盘。但不论咱们是经过网络还是有线连接手法,都需求花费必定的时刻,这或许导致事务较长时刻的停写(不可用),因而扩缩容是十分困难的。
- 多份独立数据,本钱高: 如果咱们要在“复制集”之间或许主备机之间去做数据冗余或数据同步,那么每新增一分核算才能(新增一个核算节点),就要新增一分存储冗余,就会导致存储本钱提高。
分布式数据库存储解析
为了处理单机数据库存储体系面临的问题和应战,字节跳动的数据库团队调研了一些业界干流的分布式数据库计划。
MyRocks: MySQL + RocksDB
需求阐明的是,MyRocks 不是分布式数据库或许分布式处理计划,它是单机 SQL over kv 的典型代表。
- 核心理念: 用 RocksDB 替换 InnoDB 。运用 RocksDB 能够有用缓解单机容量瓶颈的问题;
- 特色: 一是:数据可紧缩份额较高。RocksDB 完成了一种比较优异的紧缩算法,依据实际调研成果显现,在联系型数据库场景,基本上它能完成 2-4 倍的紧缩比,能有用缓解单机的容量瓶颈问题。例如,单机本来挂载了 10 块磁盘,只能承载 10 TB 数据,运用 RocksDB 就能在不改变硬件条件下帮助单机承载 20 TB 或 30 TB 等更多的数据;二是,次序写功能较好,这也是 LSM-Tree 这种数据结构在 HDD 年代呈现的核心原因。
- 难点: Compaction 会导致功能抖动,且兼容性一般。众所周知,RocksDB 依据 LSM-Tree 构建,必定会遇到一些典型的 LSM-Tree-based 体系的问题。尽管 RocksDB 对次序写特别友爱,但它必定程度上牺牲了读功能—— RocksDB 在读的进程中会触发 Compaction,或许引发功能抖动,导致前台的写呈现卡顿现象;一起,这一类 SQL over kv 处理计划的兼容功能体现较为一般。
Amazon Aurora: 核算存储别离
- 核心理念: 核算存储别离,Log is Database。
- 特色: 架构灵活,存储层带有特定的数据库核算逻辑,除了具有存储才能之外,还具有 Redo Log 解析、回放生成数据库 Page、保护多版别数据的才能。
- 优势: 兼容性强、读扩展才能较优。依据同享存储体系的特色,Amazon Aurora 的读核算节点具有较好的扩展性,能够完成一主 15 备的部署形态,其兼容性、读扩展性体现较好。
Spanner 系: Shared-Nothing
- 核心理念: 核算存储别离,且 Share-Nothing。
- 特色: Spanner 系的数据库体系一般依据分布式 k-v 存储构建,由存储层保证事务特性,核算层做成纯核算的无状态节点。
- 难点: 要处理当前数据库生态兼容性问题 & 分布式 k-v 体系的 hotspot 问题比较费事。
最佳实践:veDB 分布式存储体系
依据上述字节数据库团队的调研成果,咱们规划了 veDB 分布式存储体系以处理单机数据库存储体系面临的问题与应战,本节将首要介绍 veDB 分布式存储体系的体系方针与核心技能特色。
体系方针
在规划理念上,咱们希望存储体系能够完成以下四个首要方针:
- 极致弹性: 存储节点与核算节点解耦,随时弹性扩缩容;
- 极致易用性: 构建 one-size-fits-all 的存储体系,而非专用存储,要能兼容多个干流数据库(MySQL & PostgreSQL & Mongo……);
- 极致性价比: 低时延、低本钱;
- 极致牢靠性: 具有高功能、高牢靠的备份康复才能。
依据以上体系方针,数据库团队规划并开发了 veDB 分布式存储体系,如下图所示:
从图中能够看出,分布式存储层依据 LogStore 和 PageStore 这两个子体系构建,其体系特色与咱们的规划方针彼此呼应。
- 高弹性:存储层可独立扩缩容,核算层彻底不感知;
- 高性价比:在 LogStore 完成了高功能 Log 存储 & 在 PageStore 完成了低本钱 Page 存储;
- 兼容性好:LogStore 和 PageStore 都支撑多 DB Engine 插件化;
- 高牢靠:PageStore 侧支撑 Segment 等级的 PITR 功能。
核心技能
以下首要从研制背景(Problem)、处理思路(Solution)、处理成效(Outcome)三个方面来别离介绍 veDB 分布式存储体系的五个核心技能。
Distributed Data Model
Problem:从单机 FS 到分布式存储,需求有高效的数据布局模型。 依据单机的文件体系或块存储体系去完成数据耐久化是比较简单的,咱们能够直接经过申请一批 LBA 或许一批文件来存储数据,然后操控并发即可,可是这关于分布式存储并不简单。从上面的暗示图能够看到,最上层的 Tablespace 代表一张数据库表,里边或许包括上百万乃至上千万的 Page data(数据库的根底办理单元)。然而存储体系的办理单元,却不或许是 Page —— Page 的粒度过小,往往只需 KB 等级,如果存储层以过小的粒度去办理数据,或许会造成元数据膨胀,添加办理本钱。
Solution:Tablespace -> Segement 分布式映射。 依据上述问题,咱们能够在存储层使用相对大的办理单元 Segment 去进行数据办理。此时,数据库的办理单元是 Page,存储体系的办理单元是 Segement。Tablespace 和 Segement 之间必定要存在一层映射联系,该映射联系能够依据不同数据库引擎的数据办理空间巨细要求进行设置,或许 MySQL 和 PostgreSQL 的映射规矩就大不相同。上述暗示图展现了最简单的模 2 规矩,咱们也能够发展出其他更加复杂的打散规矩,此处不进行赘述。当咱们将 Page 打散到对应的 Segement 之后,数据库就不需求管数据 Replication 的逻辑,不论底层存储是多副本还是 EC 策略,能够彻底由存储体系来做通明的 Replication ,数据库就像在运用单机文件体系一样简单。
Outcome
- 天然负载均衡;
- 分布式打散,可最大程度完成并行核算;
- Scale in/out 简单,仅需部分 Segement 数据 rebalance,摒弃了将整个数据库表的 TB 级数据在硬盘间搬家的繁杂流程。
Log-Only Segement
Problem:数据冗余本钱高,需求下降存储本钱。
Solution:开发 Log-Only Segement,节省非必要的 Page 副本空间。 什么是 Log-only segement? 联系型数据库中往往都包括 Log 数据和 Page 数据。在存储层中,存了多副本的 Log 数据后,咱们能够选择性地只回放一部分 Log 数据来生成 Page,让另一部分 Log 数据保持不动,不要生成任何 Page 数据。以上面的暗示图为例,Rep_0 和 Rep_1 都是 Log 数据生成的各种版别 Page 数据,然而 Rep_2 是一个空的 Page 数据副本,它里边只需 Redo log。咱们都知道 Redo log 和 Page data 的数据巨细份额是比较夸张的,Page data 的巨细或许是 Redo log 的几倍乃至十几倍,因而经过以上办法能够较大的节省单机的 Page 存储空间。
Outcome: 结合单机引擎的紧缩算法,能将存储空间放大倍数从 3.x -> 1.x,较好缓解本钱问题。
高功能 IO 引擎
Problem: 存储层写功能简单成为体系功能瓶颈,怎么处理?
Solution:全异步 IO + 无锁结构 +并发打散。 当数据库提交了一个 Redo log 到 Log Storage 之后,Log Storage 中会有一个无锁的 Ring buffer 去对 Redo log 进行有序组织,然后咱们将 Redo Log 的 Ring buffer 进行线性的定长切割,并发打散到底层存储的 Blob 单元。
Outcome:4KB + depth 8,write latency ~100+us, 较好支撑了数据库下发日志的功能刚需。
PITR
PITR(Point-in-time Recovery)是指咱们都能够敏捷地康复在曩昔一段时刻内某个时刻点的数据库快照。
Problem: 怎么快速备份康复,且下降对前台事务影响?
Solution:依据 Segement 的高并发 PITR 机制,Segement 间互不影响。 之前提到存储层的办理单元是 Segement ,咱们也能够依据 Segement 做备份康复。这样做有两个好处:首先核算层是彻底通明的,核算层彻底不会感知,而且核算层的功能不会抖动。其次依据 Segment 能够做到天然的并发打散,因而备份康复也能够做到并发康复。
Outcome
- 功能优异,康复 1TB 数据 ~15min;
- 扩展性强,不受数据巨细影响,功能与数据巨细呈近常数联系:由于依据 Segment 单元去做并发备份康复,每个 Segment 都是独立的,其功能能够与数据巨细解耦开来。因而不论数据巨细是多少,只需备份康复资源足够,都能做到常数级的备份康复功能。
多核算引擎插件化
Problem: 数据库团队希望一致的存储层能够支撑不同的数据库引擎,做到 100% 兼容和快速接入。
Solution:Write Ahead Log + Log Replay = 恣意 Page Data。 依据本地存储引擎的 k-v 结构,或许依据裸的块设备笼统出一种相对通用的数据结构,从而高效地存储 Page data。一起,咱们在 SDK 侧和 Server 侧都做了 Log parse 的插件化,要接入新的数据库引擎只需求其供给适配存储接口的日志插件,从而能够快速接入各式各样的数据库核算引擎。
Outcome:
- 依据一致接口,核算引擎仅需供给 Log parse + Replay lib 即可接入 veDB 存储层。
- 一致存储层已支撑 MySQL、PostgreSQL、MongoDB 核算引擎,现在仍在持续拓展。
数据库存储体系:What’s Next
在谈及数据库存储的未来演进时,首先咱们能够考虑一下哪些因素会触发数据库存储架构的革新和演进?答案或许包括:存储架构本身的革命、数据库理论的打破、或许新硬件冲击引发存储体系架构迭代。依据这三个方向的考虑,咱们总结了以下几个数据库存储体系的演进趋势:
HTAP/HSAP
咱们总结的榜首个趋势即 HTAP/HSAP 体系将会逐步爆发。在 HTAP/HSAP 体系中,“实时”是榜首关键词。为了支撑实时,存储体系或许会产生架构演进和革新,因而咱们需求探索:
- 行列存 All-in-one:既要存储行式的数据,又要存储列式的数据。
- 近实时,写时核算:咱们需求在存储层完成写时核算的逻辑来支撑实时性。
AI Enhancement
AI 技能运用领域广泛,具体在数据库存储领域,咱们能够使用 AI 技能进行以下工作:
- 存储参数调优;
- 智能存储格局:使用 AI 技能进行智能的行存和列存格局转化,AI 能够提醒咱们什么时刻进行转化,什么时分肯定不能转化,从而防止格局转化为前台事务带来的功能 overhead。
Hardware Revolution
在硬件革新趋势上,咱们总结了三个革新方向:
- 存储介质革新:前几年,咱们或许更多关注 SSD、HDD。现在咱们处于 SSD 往 persistent memory 转变的风口,那么怎么使用 persistent memory 去定制软件架构?现在看在文件体系侧已经有一些研究,可是在数据库侧并没有太多公开实践。
- 核算单元革新:CPU 产品已经从 multi-core 变成了 many-core (从 96c 变成了 192c、384c)。要怎么使用多核的才能?关于非核算密集型的存储体系而言,剩余的算力能否用来加速数据库算子?一些无锁的数据结构是不是需求要重新规划?以上都需求咱们认真考虑。
- 网络设施革新:例如 RDMA ,以及可编程的 P4 交换机这类全新的一些网络设施,或许会对咱们的软件架构特别是分布式存储架构造成较大的冲击。相应地,咱们需求在存储侧做出调整。
字节跳动根底架构数据库&云存储团队
Database & Cloud Storage Team,服务于字节跳动全系产品。在这里,咱们有丰厚的云存储产品,担任管理数十 EB 等级的海量数据;有多种数据库产品,供给极致时延、超大吞吐的云原生数据库服务;有前沿的技能研究,探索新硬件与新软件架构的融合,打造下一代革命性的云存储与数据库产品。
以上内容收拾自第四期字节跳动技能沙龙《字节云数据库架构规划与实战》,获取讲师 PPT 和回放视频,请在公众号“字节跳动技能团队”后台回复关键词“0416”。