日前,字节跳动技术社区 ByteTech 举办的第四期字节跳动技术沙龙圆满落幕,本期沙龙以《字节云数据库架构设计与实战》为主题。在沙龙中,字节跳动基础架构数据库开发工程师刘辉聪,跟大家探讨了 《字节云数据库未来方向的探索与实践》,本文根据分享整理而成。
字节云数据库概览
字节云数据库架构分为四层,示意图如下:
DBEngine 层:我们对外会提供完备的数据库,兼容全面的数据库生态,包括 Mysql、PG、ES、Mongo 等;同时我们也支持混合负载,即 HTAP。
DB-Cache 层:这一层会存储两类数据,一类是日志流,另一类是用户数据的缓存。我们在这一层引入一些新的硬件进行加速,为用户提供极致的性能体验。
DB-Store 层:这一层是低成本、跨 AZ、多格式的 DB-Store 层,用于存储用户数据。DB-Store 层是一个分布式的存储平台,它支持插件式的存储格式,比如 veDB 中的行存格式、 ByteHTAP 的行列混合格式;它也支持 Segment 级别的 PITR 特性,提高数据的可用性;它还支持压缩 和 Tail Segment 的特性,来极致降低存储成本。
Store 层:这一层是冷数据存储层,用于存储备份数据或者分层的冷数据。
Severless:目前 veDB 部署在字节内部虚拟机上,同时我们支持在火山引擎上进行容器化部署。我们希望通过当前正在探索的 Serverless ,为用户提供 pay by usage 的计费模式,提供自动 scale up 和 scale down 能力,来充分提高空闲资源的利用率。
Brian:这是数据库的“大脑”,负责提供 AI 能力。
字节云数据库架构的特点是支持三个分离,一是存储与计算的分离,二是日志和数据的分离,三是缓存与计算的分离。
A-Store For veDB 探索与实践背景
业界的很多产品证明了 veDB 云原生数据库架构具有着强大优势,如下:
- 极致弹性,存储计算按需扩展,这是存储和计算分离带来的核心优势,使得云原生数据库在对外提供良好的兼容性同时提供良好的扩展性;
- 支持存储层多租户共享,能够极致提高存储资源利用率;
- 计算层超分超卖,提升计算利用率。
但是这种存储与计算分离的架构也有一定的劣势:
- 计算存储间延时增加;
- Local: 100us VS Remote: 1-5msdryme。
存储和计算分离后,我们将存储拉到远端的分布式存储系统上,会导致计算和存储之间的延时增加。之前 MySQL 在本地访问 nvme,访问时间大概在微秒级别,但是经过网络延时后,访问时间在毫秒级别。因此我们提出一个设想,是否有一个能和本地 NVME-SSD 同样快且稳定的存储层?新硬件的持久化内存和 RDMA 的出现为上述设想提供了可能。
Persistent Memory
在过去几十年间,计算机系统已经实现了如下金字塔型存储结构。
金字塔上层是易失存储,容量小,延时低;金字塔下层是非易失存储,容量大,延时高。对于 DRAM 及以上的易失存储,CPU 可以通过 Load 和 Store 指令直接访问,响应时间大致在几十纳秒到 100 纳秒级别。对于 SSD 及以下的非易失存储, CPU 就无法直接访问,企业级 SSD 的响应时间可以达到 10 微秒到 100 微秒的级别。由此可以看出 SSD 和 DRAM 之间存在差不多 100 多倍的性能差距,在访问时延上存在一个很大的跳变,但是持久化内存的出现弥补了它们之间的性能鸿沟。
持久化内存(PMEM)位于 DRAM 和 SSD 之间,它具有以下几个核心的特性:
- 非易失性:持久化内存具备硬盘的特性,即掉电重启,内存中的数据依旧存在;
- 字节可寻址;
- 大容量:对于单台服务器,持久化内存容量可以达到 TB 级别;
- 低延时。
在数据库领域,持久化内存目前主要有两种使用模式,模式一:将其作为一个单机的持久化层,用来加速单个计算节点的性能;模式二:把它拉远做一个分布式的持久化池。作为 veDB 产品的扩展,字节数据库团队在架构上是将 PMEM 作为分布式的共享存储池,用于加速 veDB 的性能。相对于第一种单机模式,拉远的存储池存在一个缺陷:它仍旧需要通过网络来访问,性能低于单机的持久化内存。但是 RDMA 的出现能够有效弥补该缺陷。
RDMA
RDMA 是一种远程直接内存访问的技术。在传统的 TCP/IP 协议中,数据传输时会经过多次的数据拷贝,以及经过 CPU 的内核上下文切换。数据需要经历从用户态到内核态,从内核态再拷贝到网卡。同时,TPC/IP 协议会有一些处理开销,包括 Buffer 管理,协议栈管理,以及发送完之后系统中断引起的开销。RDMA 技术能够帮助计算机直接存取另外一个计算机的内存。
RDMA 具有以下三个核心优势:
- 零拷贝(Zero-Copy):应用程序能够直接执行数据传输,不需要经过多次数据拷贝,就能直接发送到远端的计算机内存中去;
- 内核旁路(Kernal bypass):应用程序直接可以在用户态执行数据传输,不用经过用户态到内核态的上下文切换;
- 不需要 CPU 干预(No CPU invovlement)。
基于以上 PMEM 和 RDMA 的新硬件加持,存储系统能够提供极低的延时,非常适用于对性能要求很高、容量无需很大的场景,比如存储系统中的 Cache、WAL 日志、内存数据库等。
A-Store 架构
基于 AEP + RDMA 硬件,数据库团队设计了分布式、高性能存储系统——A-Store。A-Store 对外提供的语义是 Append-only 写接口和随机读,支持 RDMA 单双边的消息。
从图中可以看出,A-store 架构包含三个模块:
- AEP-SDK 模块: SDK 会作为一个库,连接到计算层的比如 veDB 的 DB Engine 中去,成为一个 IO 入口;
- AEP-Server 模块:它是一个单独的进程,部署在某个存储节点上,就负责管理该节点上所有 AEP 的介质以及后台任务;
- 集群管理模块:这个模块复用了 veDB 存储层的集群管理模块,对其进行了一些适配和修改,主要负责数据分布、节点故障发现、元数据的持久化。
最后,A-store 架构具有三个核心特点:一是高性能,硬件直通设计,旁路 Server 软件栈,IO 路径是完全无锁化的设计,也没有拷贝;二是分布式,底层的 Server 层可以扩展;三是高可用,存储在 AEP-Server 的数据,一般都支持多副本部署,目前我们一般部署三副本,保证数据的高可靠性。
A-Store 应用
A-Store 主要有以下两个应用方向:
- 缓解 veDB 存储拉远对性能的影响:veDB 存储拉远具体拉远了哪些数据?比如在 MySQL 系统里通常会有两类数据:Redo 日志和用户数据,我们就将这两类数据拉远,此时我们通过 A-Store 加速这两类数据访问速度,因此 A-Store 的第一个应用是用于 Redo 日志加速。第二个应用是 Extend Buffer Pool。
- 特性增强:我们正在开发一款基于 A-store 的高性能存储引擎, MemTable。
A-Store For Redo Log 加速
在之前的 veDB 部署中, Redo 日志是通过 Logstore 的组件,将数据写到了远端的 Append only 的分布式系统。当我们引入 A-Store 之后,我们将会替代原来的 Logstore 的组件,将 A-Store 的 SDK 集成到 DB Engine 内部。相比之前的 Logstore 实现,A-Store 具有两个优势:
- 无数据拷贝:在之前 Logstore 的实现里,除了有 TCP IP 的网络拷贝,从用户态到内核态的拷贝之外,在软件栈上也有多次数据拷贝。使用 A-Store 能够完全去掉这种内存拷贝, DB Engine 直接把 Redo 日志写到 RDMA 注册的内存上去,无需任何的数据拷贝;
- 无线程切换:在之前 Logstore 的实现里,我们会有多次的线程切换,从 DB Engine 的 Log writer 线程,切换到 Logstore 线程里去。使用 A-Store 之后,我们可以直接在 Log writer 的线程里调用 A-Store 接口,无需任何软件栈的处理,就能够直接写到远端的 AEP Server 上去。
Redo 日志的写速度,对于写负载是非常重要的。在我们目前的测试中,替换成 A-Store 之后,对于纯写的场景,性能能够提高 20% -30%;线上真实 Workload(write-heave),性能提升 2 倍+。
A-Store For Extend Buffer Pool
原生的 mysql 处理查询都是单线程的处理模型,访问数据时都要先去判断数据是否在 Buffer Pool 中,如果不在,我们需要通过同步的接口把数据从远端存储拉到 Buffer Pool。如果数据没有命中 Buffer Pool,比如数据量很大,Buffer Pool 线上最多开 100 G ,对于用户的请求,请求延时就会增加。为了缓解拉取远端存储的性能下降问题,我们扩展了原生的 Buffer Pool 设计,将 A-Store 作为一个远程分布式的二级缓存,来扩大缓存空间的大小。它的一个主要优势是:延时更低,容量更大。
除此之外,A-Store 还提供 Hot 特性。主节点在故障宕机,进行主备切换之后, 备机可以直接使用远端 AEP Buffer pool 的数据,缩短冷启动时间。我们在纯读、纯写的场景下都进行了测试,性能提高 30% - 70% 左右。
MemTable For veDB
第二个应用方向是提供特性增强。字节未来的发展方向是提供数据库的纵向融合探索,重塑应用缓存和数据库之间的边界。基于 A-store 设计,我们正在开发一款内存数据库引擎 MemTable,对外兼容 SQL 协议。
MemTable 架构
MemTable 架构也采用计算与分离的思路,中间通过 RDMA 进行通讯,它与当前的 veDB 存在几点不同。一是,MemTable 在计算层引入编译执行技术来大幅度提高 SQL 的执行速度;二是存储和事务的处理与 InnoDB 不同:在索引结构上,我们目前采用 ART 索引结构;另外我们采用 MVOCC 并发控制算法进行事务控制;最后我们采用 Record 粒度的数据组织格式。
MemTable for veDB 架构
MemTable 出现之后,veDB 的整体架构如上图所示,MemTable 将作为 MySQL 的插件式存储引擎。同时,它会与 InnoDB 形成互补,InnoDB 可以满足业务容量型需求,MemTable 则可以满足业务高吞吐低延时需求,预计性能可以达到 InnoDB 的 10 倍 +。
ByteHTAP 探索与实践
背景
HTAP 概念早在 2014 年由 Gartner 提出。HTAP 强调以下两个核心理念:
- 打破 AP(Analytical Processing) 和 TP(Transaction Processing)系统中间的墙:在数据库发展最初阶段,其实存在只有一个系统,不用区分 TP 和 AP 。伴随着数据量的增长,单个系统内部没法既支持 TP 又支持 AP, 因此发展出两个方向 OLTP 和 OLAP 。HTAP 的出现能够打破 TP 到 AP 之间的墙,在一个系统中同时去支持这两类负载。
- 实时性:伴随着互联网的发展,互联网企业的数据呈现爆发式增长。TP 和 AP 的用户 pattern 是完全不同的——TP 的 pattern 一般是命中二级索引的简单类查询,再加上一个增、删、改的高频更新操作,但是 AP 系统处理的都是一些复杂的查询。这两种 Workload 本身是非常不同的,所以如果在一个系统里,数据量比较大的前提下去支持这两类负载,基本不太现实。目前许多公司都有两套系统, TP 和 AP 系统,而这样的架构会带来三个问题:一是,实时性要求。数据产生在 OLTP 系统里,然后经过 ETL 的清洗流入到数据仓库之后,数据通常会存在分钟级甚至小时级、天级的延时。二是,数据一致性的要求。当前许多用户的使用场景都是把数据从 TP 的系统导入到 AP 的系统,在多个系统之间维护一致性非常困难;三是,成本,包括人力/硬件成本。
以上是业界提出 HTAP 的背景,在字节跳动,我们希望进行横向融合探索,通过对外提供 everything is SQL 的接口;在内部,不管是 TP 还是 AP,PG 还是 MySQL,通过设置统一的处理层来简化业务应用数据管理体系。
架构
ByteHTAP 架构主要基于以下三个核心目标进行设计:
- 实时查询(时延 < 1 sec):用户希望在 AP 侧实时看到 TP 侧引入的数据修改,延时小于 1 秒钟,该目标对于用户十分重要。比如字节跳动的用户增长部门就需要在数据不断变化的同时,对其进行复杂的查询;广告、商业分析的用户也希望能够在秒级的范围内对修改的数据进行应用。
- 强一致性(SI 隔离级别):实时分析的数据集支持强一致性,为用户提供 snapshot 隔离级别,大大简化用户对一致性的处理成本。
- 高性能(更新/复杂查询)。
整体架构
基于以上核心目标,数据库团队设计了如下的 ByteHTAP 整体架构。
目前业界存在很多 HTAP 产品,比如 Memory SQL 系统 、HANA 系统、还有在 TP 系统中扩展 AP 能力、或者在 AP 系统中扩展 TP 能力。2017 年 ACM 发表的一篇关于调研 HTAP 的论文将 HTAP 大致分为了两类,第一类是 Single Engine 系统,这类系统有一个统一的查询处理引擎,比如 Memory SQL 系统。第二类 Separate Engine 系统,这类系统使用分开的查询处理引擎进行 TP 和 AP 的处理。对于 ByteHTAP 而言,它具有以下三个核心特性:
- 一是:TP/AP 引擎分离。ByteHTAP 系统使用的是分开的查询处理引擎来处理 TP 和 AP,这么做带来的好处是我们可以在字节内部或者是在开源的成熟产品里面选择两个不同的 TP 和 AP 系统来分别支持 Query Processing 的处理。这种处理对于用户来说是透明的,我们对外会有一个智能代理层,它会自动将用户的请求路由到 TP 系统或者 AP 系统。
- 二是:计算存储分离。ByteHTAP 基于 veDB 扩展,使用 veDB 系统作为 OLTP 的引擎,它的一个核心组件是分布式日志框架,用来负责将日志复制和分发到底层的数据存储页面 PageStore 上。同时,在 ByteHTAP 系统中,数据库团队扩展了分布式日志框架,日志不仅能够被分发到 PageStore,还能够被分发到 HTAPStore。上层架构了 Query Processing,目前 Query Processing 采用的 Apache Flink 实现。
- 三是:共享行列存储平台。ByteHTAP 的另一个核心组件是 meta Data Service,用来存储 AP 系统的元信息,包括元信息的定义,统计信息,以此辅助用户查询。
关键技术点
数据库团队分别根据三个核心目标研发了对应的核心技术。针对实时查询,我们提供了以下三个核心技术,达到时延 < 1sec 的目标:
- 引入轻量级的 Log Parser 设计。在 HTAP 系统里,我们复用了 veDB 中高效的日志复制框架,基于 column 协议对日志进行分发,避免写入的一个长尾时延;其次如果日志有空洞,可以采用 gossip 协议进行补洞;我们设计了一个轻量级的 Log Parser 机制,按需解析字段并进行分发。
- 分布式并行 Apply。用户在创建表时可以根据需求定制自己指定的分片策略。随后,日志复制框架会将日记分发到存储系统上,各个分片可以进行分布式并行 Apply 。
- In-memory Delta Store + Persistent base Cloumn Store。该技术是针对存储的,我们在存储层采用一个 In-memory Delta Store,它是一种行存格式,以及 Persistent base Cloumn Store,它是行列混合的存储格式,用来加速 Apply 、Flash、 Compaction 流程。
针对强一致性,涉及以下三个核心技术点,实现 SI 隔离级别:
- 事务原子性更新可见点。我们实现了基于 lsn 的多本管理机制,我们在 AP 系统使用的日志是在 TP 系统里事务提交时产生的逻辑日志,所以事务原子性得到天然保障。我们为日志赋予了一个全局版本号,会原子地去更新版本号。
- 数据多版本。DataStore 支持多版本,每个用户在查询时都会携带一个全局一致的版本号,然后发送到 HTAPStore 上去,HTAPStore 会基于他的版本号给对应的数据。
- 元信息多版本。meta Data Service 的元信息支持多版本存储。HTAPStore 在进行日志回放时,会从逻辑日志里解析 DDL ,meta Data Service 会拿到 DDL 的变更。
最后针对高性能,涉及以下三个核心技术点,实现更新/复杂查询:
- 使用分布式计算引擎,提高执行效率。
- 支持算子下推,比如 Filter 算子、聚合算子都可以下推到 HTAPStore 上。
- 高效的数据导入。目前我们开发了一个快速导入的工具,该工具可以帮助我们从 veDB 的 TP 系统拿到一个一致性的点,直接进行数据页面的解析和写入,将解析出来的数据以批量的方式直接写入到 baseStore,大大提高数据迁移的速度。
应用
ByteHTAP 可以被应用到以下两个典型应用场景:
- 用户需求是实时性:投放分析师需要实时调整投放计划,在使用 ByteHTAP 之前,实时性基本上是小时级,当系统切换到 ByteHTAP 之后,实时性可以达到秒级。
- 用户需求是高性能查询:之前数据主要存储在 MySQL 上,人力科技做数据汇总查询比较复杂。在使用 ByteHTAP 之后,用户将系统迁到 veDB 上, TP 侧用来作为用户的写入,ByteHTAP 一侧用来作为用户的查询,性能提升从 10 分钟级降到秒级。