云原生数据库设计新思路

本文做者为 PingCAP 联合创始人兼 CTO 黄东旭,将分享分布式数据库的发展趋势以及云原生数据库设计的新思路。

在讲新的思路以前,先为过去没有关注过数据库技术的朋友们作一个简单的历史回顾,接下来会谈谈将来的数据库领域,在云原生数据库设计方面的新趋势和前沿思考。首先来看看一些主流数据库的设计模式。数据库

常见的分布式数据库流派

分布式数据库的发展历程,我按照年代进行了分类,到目前为止分红了四代。第一代是基于简单的分库分表或者中间件来作 Data Sharding 和 水平扩展。第二代系统是以 Cassandra、HBase 或者 MongoDB 为表明的 NoSQL 数据库,通常多为互联网公司在使用,拥有很好的水平扩展能力。设计模式

第三代系统我我的认为是以 Google Spanner 和 AWS Aurora 为表明的新一代云数据库,他们的特色是融合了 SQL 和 NoSQL 的扩展能力,对业务层暴露了 SQL 的接口,在使用上能够作到水平的扩展。缓存

第四代系统是以如今 TiDB 的设计为例,开始进入到混合业务负载的时代,一套系统拥有既能作交易也能处理高并发事务的特性,同时又能结合一些数据仓库或者分析型数据库的能力,因此叫 HTAP,就是融合型的数据库产品。性能优化

将来是什么样子,后面的分享我会介绍关于将来的一些展望。从整个时间线看,从 1970 年代发展到如今,database 也算是个古老的行业了,具体每一个阶段的发展状况,我就不过多展开。网络

数据库中间件

对于数据库中间件来讲,第一代系统是中间件的系统,基本上整个主流模式有两种,一种是在业务层作手动的分库分表,好比数据库的使用者在业务层里告诉你;北京的数据放在一个数据库里,而上海的数据放在另外一个数据库或者写到不一样的表上,这种就是业务层手动的最简单的分库分表,相信你们操做过数据库的朋友都很熟悉。数据结构

第二种经过一个数据库中间件指定 Sharding 的规则。好比像用户的城市、用户的 ID、时间来作为分片的规则,经过中间件来自动的分配,就不用业务层去作。架构

这种方式的优势就是简单。若是业务在特别简单的状况下,好比说写入或者读取基本能退化成在一个分片上完成,在应用层作充分适配之后,延迟仍是比较低的,而总体上,若是 workload 是随机的,业务的 TPS 也能作到线性扩展。并发

可是缺点也比较明显。对于一些比较复杂的业务,特别是一些跨分片的操做,好比说查询或者写入要保持跨分片之间的数据强一致性的时候就比较麻烦。另一个比较明显的缺点是它对于大型集群的运维是比较困难的,特别是去作一些相似的表结构变动之类的操做。想象一下若是有一百个分片,要去加一列或者删一列,至关于要在一百台机器上都执行操做,其实很麻烦。app

NoSQL - Not Only SQL

在 2010 年先后,好多互联网公司都发现了这个大的痛点,仔细思考了业务后,他们发现业务很简单,也不须要 SQL 特别复杂的功能,因而就发展出了一个流派就是 NoSQL 数据库。NoSQL 的特色就是放弃到了高级的 SQL 能力,可是有得必有失,或者说放弃掉了东西总能换来一些东西,NoSQL 换来的是一个对业务透明的、强的水平扩展能力,但反过来就意味着你的业务原来是基于 SQL 去写的话,可能会带来比较大的改形成本,表明的系统有刚才我说到的 MongoDB、Cassandra、HBase 等。less

最有名的系统就是 MongoDB,MongoDB 虽然也是分布式,但仍然仍是像分库分表的方案同样,要选择分片的 key,他的优势你们都比较熟悉,就是没有表结构信息,想写什么就写什么,对于文档型的数据比较友好,但缺点也比较明显,既然选择了 Sharding Key,多是按照一个固定的规则在作分片,因此当有一些跨分片的聚合需求的时候会比较麻烦,第二是在跨分片的 ACID 事务上没有很好的支持。

HBase 是 Hadoop 生态下的比较有名的分布式 NoSQL 数据库,它是构建在 HDFS 之上的一个 NoSQL 数据库。Cassandra 是一个分布式的 KV 数据库,其特色是在 KV 操做上提供多种一致性模型,缺点与不少 NoSQL 的问题同样,包括运维的复杂性, KV 的接口对于原有业务改造的要求等。

第三代分布式数据库 NewSQL

刚才说过 Sharding 或者分库分表,NoSQL 也好,都面临着一个业务的侵入性问题,若是你的业务是重度依赖 SQL,那么用这两种方案都是很不温馨的。因而一些技术比较前沿的公司就在思考,能不能结合传统数据库的优势,好比 SQL 表达力,事务一致性等特性,可是又跟 NoSQL 时代好的特性,好比扩展性可以相结合发展出一种新的、可扩展的,可是用起来又像单机数据库同样方便的系统。在这个思路下就诞生出了两个流派,一个是 Spanner,一个是 Aurora,两个都是顶级的互联网公司在面临到这种问题时作出的一个选择。

Shared Nothing 流派

Shared Nothing 这个流派是以 Google Spanner 为表明,好处是在于能够作到几乎无限的水平扩展,整个系统没有端点,无论是 1 个 T、10 个 T 或者 100 个 T,业务层基本上不用担忧扩展能力。第二个好处是他的设计目标是提供强 SQL 的支持,不须要指定分片规则、分片策略,系统会自动的帮你作扩展。第三是支持像单机数据库同样的强一致的事务,能够用来支持金融级别的业务。

表明产品就是 Spanner 与 TiDB,这类系统也有一些缺点,从本质上来讲一个纯分布式数据库,不少行为没有办法跟单机行为如出一辙。举个例子,好比说延迟,单机数据库在作交易事务的时候,可能在单机上就完成了,可是在分布式数据库上,若是要去实现一样的一个语义,这个事务须要操做的行可能分布在不一样的机器上,须要涉及到屡次网络的通讯和交互,响应速度和性能确定不如在单机上一次操做完成,因此在一些兼容性和行为上与单机数据库仍是有一些区别的。即便是这样,对于不少业务来讲,与分库分表相比,分布式数据库仍是具有不少优点,好比在易用性方面仍是比分库分表的侵入性小不少。

Shared Everything 流派

第二种流派就是 Shared Everything 流派,表明有 AWS Aurora、阿里云的 PolarDB,不少数据库都定义本身是 Cloud-Native Database,但我以为这里的 Cloud-Native 更可能是在于一般这些方案都是由公有云服务商来提供的,至于自己的技术是否是云原生,并无一个统一的标准。从纯技术的角度来去说一个核心的要点,这类系统的计算与存储是完全分离的,计算节点与存储节点跑在不一样机器上,存储至关于把一个 MySQL 跑在云盘上的感受,我我的认为相似 Aurora 或者 PolarDB 的这种架构并非一个纯粹的分布式架构。

原来 MySQL 的主从复制都走 Binlog,Aurora 做为一种在云上 Share Everything Database 的表明,Aurora 的设计思路是把整个 IO 的 flow 只经过 redo log 的形式来作复制,而不是经过整个 IO 链路打到最后 Binlog,再发到另一台机器上,而后再 apply 这个 Binlog,因此 Aurora 的 IO 链路减小不少,这是一个很大的创新。

日志复制的单位变小,意味着我发过去的只有 Physical log,不是 Binlog,也不是直接发语句过去,直接发物理的日志能表明着更小的 IO 的路径以及更小的网络包,因此整个数据库系统的吞吐效率会比传统的 MySQL 的部署方案好不少。

Aurora 的优点是 100% 兼容 MySQL,业务兼容性好,业务基本上不用改就能够用,并且对于一些互联网的场景,对一致性要求不高的话,数据库的读也能够作到水平扩展,无论是 Aurora 也好,PolarDB 也好,读性能是有上限的。

Aurora 的短板你们也能看得出来,本质上这仍是一个单机数据库,由于全部数据量都是存储在一块儿的,Aurora 的计算层其实就是一个 MySQL 实例,不关心底下这些数据的分布,若是有大的写入量或者有大的跨分片查询的需求,若是要支持大数据量,仍是须要分库分表,因此 Aurora 是一款更好的云上单机数据库。

第四代系统:分布式 HTAP 数据库

第四代系统就是新形态的 HTAP 数据库,英文名称是 Hybrid Transactional and Analytical Processing,经过名字也很好理解,既能够作事务,又能够在同一套系统里面作实时分析。HTAP 数据库的优点是能够像 NoSQL 同样具有无限水平扩展能力,像 NewSQL 同样可以去作 SQL 的查询与事务的支持,更重要的是在混合业务等复杂的场景下,OLAP 不会影响到 OLTP 业务,同时省去了在同一个系统里面把数据搬来搬去的烦恼。目前,我看到在工业界基本只有 TiDB 4.0 加上 TiFlash 这个架构可以符合上述要求。

分布式 HTAP 数据库:TiDB (with TiFlash)

为何 TiDB 可以实现 OLAP 和 OLTP 的完全隔离,互不影响?由于 TiDB 是计算和存储分离的架构,底层的存储是多副本机制,能够把其中一些副本转换成列式存储的副本。OLAP 的请求能够直接打到列式的副本上,也就是 TiFlash 的副原本提供高性能列式的分析服务,作到了同一份数据既能够作实时的交易又作实时的分析,这是 TiDB 在架构层面的巨大创新和突破。

下图是 TiDB 的测试结果,与 MemSQL 进行了对比,根据用户场景构造了一种 workload,横轴是并发数,纵轴是 OLTP 的性能,蓝色、黄色、绿色这些是 OLAP 的并发数。这个实验的目的就是在一套系统上既跑 OLTP 又跑 OLAP,同时不断提高 OLTP 和 OLAP 的并发压力,从而查看这两种 workload 是否会互相影响。能够看到在 TiDB 这边,同时加大 OLTP 和 OLAP 的并发压力,这两种 workload 的性能表现没有什么明显变化,几乎是差很少的。可是,一样的实验发生在 MemSQL 上,你们能够看到 MemSQL 的性能大幅衰减,随着 OLAP 的并发数变大,OLTP 的性能降低比较明显。

接下来是 TiDB 在一个用户实际业务场景的例子,在进行 OLAP 业务的查询的时候,OLTP 业务仍然能够实现平滑的写入操做,延迟一直维持在较低的水平。

将来在哪里

Snowflake

Snowflake 是一个 100% 构建在云上的数据仓库系统,底层的存储依赖 S3,基本上每一个公有云都会提供相似 S3 这样的对象存储服务,Snowflake 也是一个纯粹的计算与存储分离的架构,在系统里面定义的计算节点叫 Virtual Warehouse,能够认为就是一个个 EC2 单元,本地的缓存有日志盘,Snowflake 的主要数据存在 S3 上,本地的计算节点是在公有云的虚机上。

这是 Snowflake 在 S3 里面存储的数据格式的特色,每个 S3 的对象是 10 兆一个文件,只追加,每个文件里面包含源信息,经过列式的存储落到磁盘上。

Snowflake 这个系统最重要的一个闪光点就是对于同一份数据能够分配不一样的计算资源进行计算,好比某个 query 可能只须要两台机器,另一个 query 须要更多的计算资源,可是不要紧,实际上这些数据都在 S3 上面,简单来讲两台机器能够挂载同一块磁盘分别去处理不一样的工做负载,这就是一个计算与存储解耦的重要例子。

Google BigQuery

第二个系统是 BigQuery,BigQuery 是 Google Cloud 上提供的大数据分析服务,架构设计上跟 Snowflake 有点相似。BigQuery 的数据存储在谷歌内部的分布式文件系统 Colossus 上面,Jupiter 是内部的一个高性能网络,上面这个是谷歌的计算节点。

BigQuery 的处理性能比较出色,每秒在数据中心内的一个双向的带宽能够达到 1 PB,若是使用 2000 个专属的计算节点单元,大概一个月的费用是四万美金。BigQuery 是一个按需付费的模式,一个 query 可能就用两个 slot,就收取这两个 slot 的费用,BigQuery 的存储成本相对较低,1 TB 的存储大概 20 美金一个月。

RockSet

第三个系统是 RockSet,你们知道 RocksDB 是一个比较有名的单机 KV 数据库,其存储引擎的数据结构叫 LSM-Tree,LSM-Tree 的核心思想进行分层设计,更冷的数据会在越下层。RockSet 把后面的层放在了 S3 的存储上面,上面的层实际上是用 local disk 或者本地的内存来作引擎,自然是一个分层的结构,你的应用感知不到下面是一个云盘仍是本地磁盘,经过很好的本地缓存让你感知不到下面云存储的存在。

因此刚才看了这三个系统,我以为有几个特色,一个是首先都是自然分布式的,第二个是构建在云的标准服务上面的,尤为是 S3 和 EBS,第三是 pay as you go,在架构里面充分利用了云的弹性能力。我以为这三点最重要的一点是存储,存储系统决定了云上数据库的设计方向。

为何 S3 是关键?

在存储里边我以为更关键的多是 S3。EBS 其实咱们也有研究过,TiDB 第一阶段其实已经正在跟 EBS 块存储作融合,但从更长远的角度来看,我以为更有意思的方向是在 S3 这边。

首先第一点 S3 很是划算,价格远低于 EBS,第二 S3 提供了 9 个 9 很高的可靠性,第三是具有线性扩展的吞吐能力,第四是自然跨云,每个云上都有 S3 API 的对象存储服务。可是 S3 的问题就是随机写入的延迟很是高,可是吞吐性能不错,因此咱们要去利用这个吞吐性能不错的这个特色,规避延迟高的风险。这是 S3 benchmark 的一个测试,能够看到随着机型的提高,吞吐能力也是持续的提高。

如何解决 Latency 的问题?

若是要解决 S3 的 Latency 问题,这里提供一些思路,好比像 RockSet 那样用 SSD 或者本地磁盘来作 cache,或者经过 kinesis 写入日志,来下降整个写入的延迟。还有数据的复制或者你要去作一些并发处理等,其实能够去作 Zero-copy data cloning,也是下降延迟的一些方式。

上述例子有一些共同点都是数据仓库,不知道你们有没有发现,为何都是数据仓库?数据仓库对于吞吐的要求实际上是更高的,对于延迟并非那么在乎,一个 query 可能跑五秒出结果就好了,不用要求五毫秒以内给出结果,特别是对于一些 Point Lookup 这种场景来讲,Shared Nothing 的 database 可能只须要从客户端的一次 rpc,可是对于计算与存储分离的架构,中间不管如何要走两次网络,这是一个核心的问题。

你可能会说没有关系,反正计算和存储已经分离了,大力出奇迹,能够加计算节点。可是我以为新思路不必这么极端,Aurora 是一个计算存储分离架构,但它是一个单机数据库,Spanner 是一个纯分布式的数据库,纯 Shared Nothing 的架构并无利用到云基础设施提供的一些优点。

好比说将来咱们的数据库能够作这样的设计,在计算层其实带着一点点状态,由于每台 EC2 都会带一个本地磁盘,如今主流的 EC2 都是 SSD,比较热的数据能够在这一层作 Shared Nothing,在这一层去作高可用,在这一层去作随机的读取与写入。热数据一旦 cache miss,才会落到 S3 上面,能够在 S3 只作后面几层的数据存储,这种作法可能会带来问题,一旦穿透了本地 cache,Latency 会有一些抖动。

这种架构设计的好处:首先,拥有对实时业务的数据计算亲和力,在 local disk 上会有不少数据,在这点上不少传统数据库的一些性能优化技巧能够用起来;第二,数据迁移其实会变得很简单,实际上底下的存储是共享的,都在 S3 上面,好比说 A 机器到 B 机器的数据迁移其实不用真的作迁移,只要在 B 机器上读取数据就好了。

这个架构的缺点是:第一,缓存穿透了之后,Latency 会变高;第二,计算节点如今有了状态,若是计算节点挂掉了之后,Failover 要去处理日志回放的问题,这可能会增长一点实现的复杂度。

还有不少值得研究的课题

上面的架构只是一个设想,TiDB 其实还不是这样的架构,但将来可能会在这方向去作一些尝试或者研究,在这个领域里面其实还有不少 open question 咱们尚未答案,包括云厂商、包括咱们,包括学术界都没有答案。

如今有一些研究的课题,第一,若是咱们要利用本地磁盘,应该缓存多少数据,LRU 的策略是什么样子,跟 performance 到底有什么关系,跟 workload 有什么关系。第二,对于网络,刚才咱们看到 S3 的网络吞吐作的很好,什么样的性能要配上什么样的吞吐,要配多少个计算节点,特别是对于一些比较复杂查询的 Reshuffle;第三,计算复杂度和计算节点、机型的关系是什么?这些问题其实都是比较复杂的问题,特别是怎么用数学来表达,由于须要自动化地去作这些事情。

即便这些问题都解决了,我以为也只是云上数据库时代的一个开始。将来在 Serverless,包括 AI-Driven 几大方向上,怎么设计出更好的 database,这是咱们努力的方向。最后引用屈原的一句话,就是路漫漫其修远兮,咱们还有不少事情须要去作,谢谢你们。

相关文章
相关标签/搜索