【社区同学好文分享】[SIGMOD Record 2016] NewSQL 究竟新在哪里

技术好文分享

来自 Apache IoTDB 开源社区的刘旭鑫撰写了一篇基于 SIGMOD Record 2016:NewSQL 究竟新在哪里的文章,对该篇文章中谈及的 NewSQL 发展、分类、技术等方向进行了详解。现转发社区,欢迎更多小伙伴踊跃投稿/分享~

今天介绍的这篇文章标题为 What's Really New with NewSQL?,作者为 CMU 的网红教授 Andrew Pavlo。看标题就知道,这篇文章研究的就是到底 NewSQL 和过去的数据库系统有何不同。NewSQL 自从 2011 年提出以来,在过去几年里一直是数据库领域的热门话题之一,国内也诞生了许多出名 NewSQL 数据库,例如 TiDB、OceanBase、TDSQL 等。NewSQL 数据库声称他们可以以过去系统做不到的方式拓展 OLTP 负载。这篇文章研究了两个问题:NewSQL 真的能比过去的系统做的更好吗?如果可以,是什么因素导致它们做的更好,还是只是硬件进步解决了过去的瓶颈呢?这些内容也能帮助我们了解数据库系统的演进过程和发展历史,这对于刚入门或对这一领域不太了解的从业者来说会有所帮助。

原文地址:

https://link.zhihu.com/?target=https%3A//15721.courses.cs.cmu.edu/spring2020/papers/01-intro/pavlo-newsql-sigmodrec2016.pdf

在 NewSQL 之前

outside_default.png

早期数据库(1960s - 2000s)

最早的 DBMS 诞生于 1960 年代,其中之一是 IBM 的 IMS 系统,用于支持土星五号和阿波罗项目的零件管理。这推动了一种观念:应用程序的代码应该与其操作的数据分开,开发者应该专注于编写应用的逻辑,而不是解决如何执行复杂的数据访问和操作。在 IMS 之后诞生了第一个关系型数据库,IBM System R 和加州大学的 INGRES。1970 年代末,Oracle 发布了他们第一个 DBMS,其设计与 System R 类似。1980 年代早期又陆续成立了一些新公司,这些公司的目标是模仿先前如 Sybase 和 Informix 等商业数据库的成功。虽然 IBM 从来没有向外界提供过 System R 的使用,但是他们随后在 1983 年发布了 DB2,其中用到了 System R 的一部分代码。

在 1980 年代末期到 1990 年代早期出现了一种新的数据库,其旨在消除面向对象编程语言和关系型模型之间的不匹配,它们被称为面向对象的数据库(object-oriented DBMS)。但是这类数据库并未广泛普及,主要原因是它们缺少像 SQL 这样的标准化交互方式,不过它们的很多思想在 10 年后人们往关系型数据库中增加对对象以及 XML 的支持时得到了借鉴,在 20 年后人们构建文档数据库时同样也借鉴了它们的思想。

1990 年代还出现了两个重要的开源数据库:MySQL 和 PostgreSQL。MySQL 在 1995 年在早期的 ISAM-based mSQL 系统的基础上开发;PostgreSQL 则由两个 Berkeley 的研究生在 QUEL-based Postgre 的基础上开发,往其中加入了 SQL 的支持(QUEL 是 Stonebraker 提出的一种数据库交互语言)。

outside_default.png

NoSQL 运动(2000s - 2010s)

2000 年左右互联网开始兴起,这对数据库也提出了更大的挑战。互联网应用需要支持大量用户同时操作,并且需要随时在线,但是这些应用所使用的数据库却成为了瓶颈,因为应用的需求已经超过了数据库和硬件所能提供的极限。于是有些人采取了垂直扩展(scale-up)的方式,即把数据库搬到更快更好的硬件上运行。这样做不仅 scale 到一定程度之后边际效应比较明显,在数据库迁移时还会使得应用长时间下线,这对互联网应用来说是不可接受的。

为了解决这个问题,有一些公司开始开发定制的中间件(middleware)。他们把数据库部署在多台廉价的机器上,然后通过中间件把数据切分(shard)到多个节点上。对应用来说,这些数据库表现的就好像是一个数据库一样。当应用读写数据库时,中间件就会重定向或者改写它们的请求,然后把最终结果汇总后返回给应用。使用这类解决方案的典型代表就是 eBay 的 Oracle 集群和 Google 的 MySQL 集群。Facebook 也使用了 MySQL 集群,并且运行至今。

中间件方案对像读或者更新一行记录这样的操作可以支持地比较好,但是对于像在一个事务里面更新许多记录,或者将多个表 join 起来这样的查询,支持的就不是很好,早期的中间件甚至是不支持这样的操作的。eBay 在 2002 年使用的中间件就不支持,于是他们的工程师就只能把 join 操作在应用程序里面实现。

最终,一些公司由于难以忍受这些限制,便开始开发自己的分布式数据库系统。主要有三个原因:

  • 过去的数据库系统主要关注数据的一致性和正确性,但是牺牲了可用性和性能。

  • 使用一个像 MySQL 这样的全功能数据库带来的开销太大了。

  • 使用 SQL 进行简单查找等工作,实际上是小题大作。

这三个原因也就导致了 NoSQL 运动在 2000 年代的兴起。NoSQL 的关键点在于,他们牺牲了强一致性的事务保证和关系模型,转而拥抱了最终一致性和多种多样的数据模型(kv、图、文档等)。NoSQL 数据库最著名的两个代表就是 Google 的 BigTable 和 Amazon 的 Dynamo。这两个系统最开始仅供内部使用(但是它们现在已经成了云服务),因此一些组织开发了他们的开源版本。Facebook 的 Cassandra 基于 BigTable 和 Dynamo,PowerSet 的 Hbase 基于 BigTable。也有一些公司跟随 NoSQL 的哲学实现了自己的数据库,例如 MongoDB。

到了 2000 年代末出现了一大批可拓展并且更廉价的分布式数据库。使用 NoSQL 的好处(至少人们是这么认为的)是开发者只需要关注于如何实现应用的逻辑,而无需担心如何 scale 数据库。然而,某些应用仍然无法放弃强一致性事务,特别是那些处理重要数据(例如金融数据)的系统。某些公司(最著名的就是 Google)发现 NoSQL 数据库系统使得他们的工程师花费了大量时间编写代码处理数据库中数据不一致的情况,如果使用事务则能让他们更加高效,因为事务为人类提供了一个更容易理解的抽象。于是,我们又回到了原点,要么购买更贵的硬件和数据库,要么使用分库分表中间件。但是这两种方案都可能比较贵,并且对大部分人来说并不合适。所以,这就导致了 NewSQL 系统的出现。

NewSQL 的兴起

我们对 NewSQL 的定义是:一类不仅提供 NoSQL 可拓展性并且还对 OLTP 负载提供 ACID 事务的关系型数据库系统。这使得应用可以使用 SQL 同时执行大量的事务来写入新信息和修改数据库的状态,应用的开发者无需编写代码处理 NoSQL 中那样由于最终一致性导致的数据不一致问题。

有些人认为 2000 年代中期出现的数据仓库符合这个定义(例如 Vertica、Greenplum、Aster Data),但是这些数据库的目标是 OLAP 负载,因此不应该被认为是 NewSQL 系统。数据仓库主要负责在大量数据上处理只读查询,每个查询都可能运行很长时间(例如几十秒甚至几分钟),每个查询可能都和之前的查询大不相同。然而 NewSQL 系统主要是处理有以下特征的事务:

  • 短时间

  • 只会通过索引处理一小部分数据(不是全表扫描或者分布式 join)

  • 具有重复性(使用不同参数重复执行同一个查询)

有些人认为 NewSQL 系统的定义应该更加狭窄,包括:

  • 使用无锁的并发控制协议

  • 具有 share-nothing 的分布式架构

后文中我们介绍的所有 NewSQL 数据库都具有这两个特征,因此作者认同这一观点。

NewSQL 的分类

NewSQL 可以分成以下三类:

  • 从头构建的新数据库

  • 重新实现了分片逻辑的中间件

  • Database-as-a-service 系统,通常是云厂商提供的

过去有些人认为在现有的单机 DBMS 中更换新的存储引擎也是一种 NewSQL 系统,最典型的例子就是更换 MySQL 的 InnoDB,例如 TokuDB、ScaleDB、Akiban、deepSQL。这么做的最大好处就是,应用侧无需做任何修改就可以得到更好的性能,并且现有的生态工具也可以继续使用。最有意思的就是 ScaleDB,它在数据库内部提供了透明的 sharding 机制,将执行计划分发到多个存储引擎上。此外,微软也为 SQL Server 开发了一个名为 Hekaton 的内存 OLTP 引擎。还有些开发者通过使用 PostgreSQL 的外部数据包装器和 API 钩子,针对 OLAP 场景实现了类似的整合,例如 Vitesse、CitusDB。

现在我们认为,为已有的单机数据库系统改变存储引擎或者增加拓展插件并不是一种 NewSQL。因为 MySQL 的 InnoDB 已经在可靠性和性能方面改善了非常多,为 MySQL 更换存储引擎在 OLTP 负载上所得到的收益已经不大了。或许对 OLAP 负载来说将 MySQL 的存储引擎从行存的 InnoDB 更换为列存引擎会有所收益(例如 Infobright、InfiniDB),但是总的来说为 MySQL 更换存储引擎这件事情大多数都是失败的。

接下来我们分别介绍前面所提到的三类数据库。

outside_default.png

从头构建的新数据库

代表:TiDB、OceanBase、CockroachDB、Google Spanner、HyPer、MemSQL、VoltDB

这类数据库都是全新设计的,其代码库中不包含任何传统系统的遗留问题。这一类数据库都是基于 shared-nothing 的分布式架构,并且有专门的组件用来负责多节点的并发控制、副本容错、流控制以及分布式查询。

优点:新分布式架构的优点在于,系统的各个部件都可针对多节点环境进行优化,包括查询优化器、不同节点之间的沟通协议等。例如在这样的系统中,在查询时一个节点可以将中间数据直接推送到另一个节点,而在中间件架构中这个数据就必须先发送到中心化的中间件。

这一类的系统一般都会自己管理存储(这里的存储有可能是内存或者磁盘),而不是依赖于一个现成的存储系统(例如 HDFS)。这样做允许数据库在查询时将查询计划发送给节点,然后将结果集返回到另一个节点,而不是需要将原始数据从一个节点传输到另一个节点。这样可以显著地减少网络开销,因为传输原始数据不仅包含记录本身,还包括索引、物化视图等。

自己管理存储的另一个好处是,数据库可以使用更加灵活的方式构建副本,而不是像 HDFS 一样只能使用基于块的备份(block-based replication)。这样可以使得系统比起那些基于已有技术的系统提供更好的性能,比如 SQL on Hadoop 的代表 Trafodion ,以及基于 Hbase 提供事务能力的 Splice Machine,这样的系统不应该被称之为 NewSQL。

缺点:当然,使用这样的系统也有一些问题。最主要的是,许多公司对于采用太新、未经过大规模验证的技术持谨慎态度,这就意味着有经验使用这些系统的人相对就比较少,从而有可能导致企业因为招不到有相关经验的人从而更不愿意使用。同时,使用这些新系统有可能会导致原有的管理和生态工具无法使用,Clustrix 和 MemSQL 等数据库通过与 MySQL 协议的兼容性,成功避免了这类问题。

outside_default.png

透明的分片中间件

代表:AgilData Scalable Cluster、MariaDB MaxScale、ScaleArc、ScaleBase、Apache ShardingSphere、TDSQL 2.0

这类产品复现了 2000 年代大型企业内部开发的分片(sharding)中间件,它们允许将原本的一个数据库拆成多个分片,然后分别存储在集群的不同节点中,集群的每个节点都运行着一个单机数据库。

sharding 中间件系统与传统的数据库联邦技术(database federation)有显著区别,主要区别在于:

  • sharding 中间件系统中每个节点都运行着相同的单机数据库系统,而在数据库联邦中不同节点运行的可能是不一样的系统;

  • sharding 中间件系统中每个节点都只有数据库的一小部分内容;

  • sharding 中间件系统中每个节点并不是应用程序直接访问和更新的对象,所有的操作都通过中间件执行;而在数据库联邦中应用会直接访问单个节点并进行操作。

在 sharding 中间件系统中,中心化的中间件负责从应用处接收请求,然后重定向查询、管理事务,此外还要负责数据的分布、副本和容灾。在每个节点的本地,通常还会运行一个代理层,负责与中心化的中间件通信,并且在本地节点运行查询并返回结果。最终,这一套系统对于应用来说,就好像是一个单机数据库系统一样。

优点:使用这一类系统的最大优点在于由于保持了和单机数据库行为的兼容,对于很多公司来说这样的系统是即插即用的,开发者无需在应用层修改任何已有的逻辑就可以迁移到新数据库上。最常见的此类系统就是对 MySQL 的各种中间件,为了与 MySQL 兼容,这些中间件都必须支持 MySQL 的 wire protocol。Oracle 提供了 MySQL Proxy 和 Fabric 来实现这个目标。有一些人为了避免 MySQL 所使用的 GPL 协议的限制,选择自己开发协议兼容层。

缺点:中间件架构的系统仍然在每个节点上都需要运行传统的 DBMS,例如 MySQL、Postgres 或者 Oracle。这些数据库都是在 1970 年代针对磁盘存储系统所开发的,因此他们无法像一些 NewSQL 系统一样使用充分为内存优化的存储引擎或者并发控制协议。此前有研究表明,面向磁盘的旧组件是导致传统数据库无法充分利用更多 CPU 核心和更大内存的重要原因之一。此外,中间件架构还会导致在处理复杂查询时查询计划被重复生成和优化(在中心中间件和节点本地都要生成和优化一次),当然这也允许每个节点都对查询计划做出它们本地的优化。

outside_default.png

数据库即服务系统

(Database-as-a-Service)

代表:Amazon Aurora、Snowflake、PolarDB、ClearDB

这一类数据库通常由云厂商提供,用户在使用这类产品时无需自己在物理机或者云主机上维护数据库系统,数据库提供商会帮用户管理数据库的物理配置(例如 buffer pool 的大小)、副本、备份等。用户会拿到一个连接数据库的 URL,以及用于管理系统的 API 或者看板。

使用 DBaaS 产品的用户按照他们的使用量进行付费。由于不同查询对数据库中计算资源的使用差异较大,因此 DBaaS 提供商不会用他们对块存储设备计费的方式来对查询进行计费。用户一般会先花钱购买某个水平的配置,这个配置保证了他们最大可用的资源(例如存储大小、cpu 核心数、内存大小)。

DBaaS 产品由于规模效应,大多由云计算领域的巨头提供。但是这些云厂商几乎也都提供了云托管数据库,例如 Google Cloud SQL、Microsoft Azure SQL、阿里云的 RDS。这种数据库使用的还是传统的面向磁盘的架构,因此我们不认为它们属于 NewSQL 系统。相反,我们认为只有那些使用了新架构的 DBaaS 产品才算是 NewSQL,这其中最著名的就是 Amazon 的 Aurora,它对于 MySQL InnoDB 的最大改动就是使用了一个基于日志的存储引擎,这极大地改善了 I/O 并行度。

这类产品也有一些第三方公司,他们并没有自己的数据中心,但是他们在公有云平台上提供 DBaaS 产品。例如 ClearDB 就在所有的公有云平台上提供他们的产品,这样的好处是他们可以将数据库分布在同一个地理区中不同的厂商中,以更大程度地避免故障。

在论文发表时(2016 年),市面上 NewSQL 类的 DBaaS 产品还只有 Aurora 和 ClearDB。当时已经有一些公司失败了(例如 GenieDB、Xeround),它们不得不让他们的用户在数据库关闭之前将数据迁移出去,作者认为它们失败的原因是他们的出现早先于市场的需求,并且他们的定价也高于主流的产品。当然,在 2023 年的今天市面上有大量的 DBaaS 产品,其中不乏 Snowflake 这样数据库领域的明星产品。

The State Of the Art

上面介绍完了 NewSQL 系统的分类,下面介绍在这些系统中使用了什么不一样的技术。

outside_default.png

内存存储

自 1970 年代起开发的大多数数据库系统都是面向磁盘的,他们将主要的数据都存在磁盘上,然后使用内存来缓存从磁盘上读的数据或者缓存事务中的更新。这么做是因为在当时内存非常贵,并且相比于磁盘内存的容量非常小。但是随着硬件的不断发展,目前的技术已使得将 OLTP 数据库完全放入内存成为一种可行且经济的选择。笔者特意查了一下,目前单个 8 路服务器的最大内存可以达到 24 TB,如果使用 3 节点的集群,总内存容量可以达到 72TB。作为对比,阿里云的 PolarDB MySQL 最大支持的数据量为 100TB。关于服务器最大内存容量的计算可以参考:

https://zhuanlan.zhihu.com/p/60830925。

将数据库放到内存里的好处是系统可以使用一些特定的优化,无需担心一个事务需要访问那些不在内存里的数据而导致 stall,一些为了处理这样的 case 而构建的组件也就可以被去除(例如 BufferPool、重量级的并发控制协议),使得数据库能够具有更好的性能。

目前已经有一些 NewSQL 是基于内存架构构建的,研究型系统有 H-Store、HyPer,商业化系统有 MemSQL、SAP HANA、VoltDB。这些系统在性能上比面向磁盘的系统要好的多。

然而,将数据库放入内存并不是一个新颖的概念。在 1980 年代 Wisconsin-Madison 相关的研究就已经为内存数据库在许多方面打下了基础,包括索引、查询处理以及故障恢复。1980 年代也已经出现了第一个分布式的内存数据库 PRISMA/DB,后续又出现了一些商业化的内存数据库,例如 Altibase、Oracle 的 TimesTen 等等。

NewSQL 内存数据库有一点创新,就是可以将数据的一部分移到磁盘上,以减少内存的使用。这项技术使得内存数据库可以存储比内存容量还大的数据。实现这一点,最常用的方法就是使用追踪机制找出那些可能不会再被访问的记录,然后把它们放到磁盘上。H-Store 的 anti-caching 组件在把数据移动到磁盘后,会在原来的地方安装一个墓碑。当一个事务访问到了墓碑数据,这个事务就会被 abort,然后另一个线程会异步地把数据加载进来。为了避免误报,所有的数据库在把记录放到磁盘上以后仍然还会在内存中保存其对应的 key(可能是主键也可能是辅助索引对应的键),因此如果数据库中有大量的二级索引,即使把数据放到磁盘上可能也不能节省很多空间。

outside_default.png

数据分区/分片

几乎所有分布式数据库扩展的方法都是把一个数据库切分成多个不相交的子集,每一个子集称为一个分区(Partition)或者分片(Shard)。在分片数据库上进行事务处理并不是一个新颖的概念,很多基础工作在 1970 年代的 SDD-1 项目就已经完成。在 1980 年代初,System R 和 INGRES 背后的两个团队就分别开发了这两个数据库对应的分布式版本。但是早期的分布式数据库大部分都没有很成功,主要有两个原因。第一个是在 20 世纪计算机的价格仍然比较高,只有少数公司才有钱购买一个集群的计算机并将数据库部署在上面;第二个原因是过去的应用所产生的数据也没有那么多,对分布式数据库的需求不足。现如今由于开源的分布式系统、云计算平台以及廉价的移动设备,构建大规模的数据密集应用变的非常简单。

数据库在分片时,首先会根据一个或者多个列的值通过 Range 分区或哈希分区将表水平划分成多个片段(Fragment),来自多个表的相关 Fragment 会组成一个分区,一个分区由一个节点管理,这个节点负责处理对这个分区的所有查询。除某些 DBaaS 系统外,大多数分布式数据库支持这种分区机制。在分片完成以后,数据库会把这些分片分布到集群的不同节点上。在执行查询的时候,也可以将查询切分成多个子查询在多个节点上并行执行,最后将结果汇总后返回给客户端。

许多 OLTP 应用可以适用这种分片架构的原因是,他们的 schema 可以被转换成一个类似树的结构,树的子节点和父结点之间有外键的关系。因此,系统可以通过某种分片方式,使得跟一个实体相关的所有数据都存储在同一个分区里。例如,假设树的根是 customer 表,那么数据库就可以按每位 customer 进行分区,跟一个 customer 相关的账号、订单等信息都可以存在同一个分区中。这样做的好处是,大部分事务都只需要访问一个分区,减少了并发控制过程中网络的开销。

有一些 NewSQL 系统在集群中使用了异构节点,例如 NuoDB 和 MemSQL。在 NuoDB 中,有一类节点称为 StorageManager(SM),负责存储数据库的一个分区;还有一类节点被成为 TransactionEngine(TE),其在内存中保存了数据的缓存。在处理查询时,TE 从 SM 或者其他 TE 中拉取需要的所有数据,然后获取写锁,并将对数据的修改广播给所有的 TE 和 SM。MemSQL 也使用了类似的异构集群,其中一些是只负责计算的聚合节点,以及一些存储数据的叶子节点。这两种数据库的优点是,可以在不对数据进行 re-partition 的情况下增加计算节点。

还有一部分 NewSQL 系统支持热点的实时迁移,通过识别热点分区并且将分区实时迁移到其他节点,可以在不对上层应用产生影响的情况下完成负载均衡。这和某些 NoSQL 数据库系统的做法有点像,但是在 NewSQL 里难点是如何在保证运行中的事务 ACID 特性的情况下同时完成热点的迁移。

outside_default.png

并发控制

并发控制是 TP 数据库中最重要的一个组件,它的设计会影响系统的方方面面。

除了一个系统选择使用哪种并发控制协议之外,还有一个重点是系统选择一个中心化还是去中心化的协调协议。在中心化的协调模式中,所有的事务都必须通过一个协调者节点判断是否合法;在去中心化的协调模式中,每个节点都管理了它自己所存储数据的事务状态,节点之间相互协调以判断事务是否有冲突。去中心化的调度模式有更好的扩展性,但是需要更严格的时钟用来确定不同事务之间的顺序。

1970-80 年代的第一个分布式数据库使用了中心化的 2PL 协议,IBM 的 R* 使用了去中心化的 2PL 协议,INGRES 的分布式版本也使用了一个去中心化的 2PL 协议,并实现了一个中心化的分布式死锁检测机制。

由于分布式死锁的复杂性,几乎所有基于新架构的 NewSQL 系统都不再使用 2PL。目前的趋势是使用 TimestampOrdering 并发控制的变种,这种协议允许不同的事务交替执行而不违反可串行化的结果。在 NewSQL 中最常用的并发控制协议是去中心化的 MVCC 协议,当事务更新一条记录的时候就会为它创建一个新的快照。维护多个快照允许读事务不阻塞写事务,这也使得某些在后台长时间允许的只读事务不会阻塞前台的写入。几乎所有基于新架构的 NewSQL 系统都使用了这样的并发控制协议,例如 MemSQL、HyPer、HANA 以及 CockroachDB。虽然这些系统做了很多工程上的工作来优化 MVCC 的性能,但是基本的东西和上个世纪的理论还是一样的。

还有一些系统使用了 MV2PL(MVCC+2PL)来实现并发控制,当一个事务更新一条记录时,就会创建一个新的快照,并且拿到这条记录的写锁;只读事务无需拿锁,也不会阻塞写入。使用 MV2PL 的系统中,最著名的就是 MySQL 的 InnoDB,其他的系统例如 Google Spanner、NuoDB、Clustrix 也使用了这一并发控制协议。很多中间件结构的 NewSQL 系统以及 DBaaS 系统都是基于 MySQL 开发的,因此他们也就顺理成章地使用 MV2PL 作为并发控制协议。

在所有 NewSQL 系统中,Google Spanner 的并发控制协议实现被认为是最为特殊的。它使用了 MV2PL 协议,但是它利用硬件的原子钟(atomic clock)来获取高精度的时间以实现同步,最终提供了全球范围内的事务一致性。CockroachDB 也希望提供和 Spanner 相同的跨数据中心事务一致性,但是他们没有原子钟,最后使用了一个硬件同步时钟和逻辑计数器混合的时钟协议来提供这样的能力。Spanner 特别的一点还在于,这个系统的出现代表着 Google 又开始重新在最重要的业务中使用事务。

唯一一个没有使用 MVCC 的 NewSQL 系统是 VoltDB,他使用了 TO 并发控制协议,但是并不是让事务交错运行,而是一次执行一个事务。它也设计了一个混合的事务调度逻辑,单一分区的事务可以使用中心化的协调机制,多分区事务则使用了去中心化的协调机制。这种基于分区的并发控制也不是新的 idea,相关工作最早可以追溯到 1992 年 Hector Garcia-Molina 的一篇 paper。

总体而言,在并发控制方面,NewSQL 系统主要通过工程实现的改进,而非理论创新,来适应现代硬件和分布式环境。

outside_default.png

二级索引

一张表的二级索引包含了这张表里不同于主键的一个或若干个键,这可以加速数据库在执行非主键或分区键的查询。对于传统的数据库,所有的数据都存在一起,支持二级索引并不是什么很难的事情。但是对分布式数据库来说,支持二级索引的难点在于二级索引里同一个键所对应的数据不一定在同一个节点上。分布式数据库在设计二级索引时有两个难点:系统在哪里存储二级索引,以及在事务中如何维护索引。在中心化的事务协调模式中,例如 sharding 中间件架构,二级索引可以存储在 coordinator 节点中。这种方式的好处在于整个系统中只有一个版本的索引,并且维护起来也非常简单。

几乎所有基于新架构的 NewSQL 系统都使用了去中心化的、分区的二级索引,每个节点只会保存索引的一部分而不是全量索引。分区索引和备份全量索引的 tradeoff 在于:前者在查询时可能需要扫描多个节点上的索引来确定需要处理的数据,而更新时只需要对应节点上的索引就可以了;后者在查询时任意一个节点都是全量的,只需要扫描一次,但是更新却需要把数据同步到所有节点。

Clustrix 实现了一种去中心化的混合二级索引。系统首先在每个节点都维护了一个粗粒度的、全量备份的二级索引,这个索引负责把索引键的某个范围映射到一个分区列表,这允许系统在查询时先根据键值找到需要处理的分区;在每个分区上系统再维护了一个细粒度的分区二级索引,这个索引负责把数据按照键值精确映射到具体的元组上。

某些 NewSQL 系统也可能不支持索引,对于开发者来说最简单的做法就是使用一个第三方的缓存服务(例如 Memcached),但是由于数据库不能主动地去更新缓存里的东西,维护索引的工作就需要在应用里进行。

outside_default.png

副本

保证数据库高可用的最好办法就是对数据库进行复制。所有的数据库系统,包括 NewSQL 系统,都支持某种程度的备份。DBaaS 系统在这一点上有独特的优势,因为他们对用户隐藏了副本的所有细节,用户不需要操心节点间的日志是否同步。

对于数据库副本来说,有两个关键的设计决策。第一个数据库如何保证不同节点间的一致性。在强一致性数据库系统中,当一个事务修改了某些数据,那么在所有节点接受这个修改之前,这个事务都不会被提交。这样做的好处在于一旦事务提交了,这个事务的任何修改在任何节点上都是可见的。同时,当有节点宕机时,不会有任何修改被丢失。但是维护这样的强一致性可能会要求系统使用像两阶段提交这样的原子提交协议,这会带来比较大的性能开销,特别是在出现了网络故障的情况下。这也就是为什么 NoSQL 数据库更喜欢使用弱一致性模型,这样就无需等待所有节点都成功后修改才能提交事务。几乎所有的 NewSQL 系统都支持强一致性的副本,但是他们在理论上并没有什么新奇的。状态机复制的相关理论在 1970 年代就已经开始被研究,1980 年代的 NonStop SQL 是第一个使用强一致性模型的分布式数据库系统。

除了数据库系统什么时候将更新传播给副本,第二个问题是如何执行这个传播过程。第一种是 active-active 备份,在这种模式下所有的副本同时处理相同的请求。第二种则是 active-passive 备份,在这种模式下事务会先在一个节点中被执行,然后这个节点将最终的结果传播给其他节点。大部分的 NewSQL 数据库系统都选择了第二种方式,这是因为他们都实现了非确定性的并发控制协议,如果在所有副本上同时执行相同的请求,不同的事务在不同节点上的执行顺序可能是不确定的,最终会导致不同副本的结果不一致。

NewSQL 系统和之前系统的一个很大的不同点在于它们考虑了在广域网(WAN)上如何进行备份,这是因为在现代的运行环境中将系统在跨地域的多个数据中心部署是很常见的。但是由于在广域网上提供同步更新会导致性能严重下降,因此大部分的 NewSQL 系统选择在广域网上提供异步更新。Spanner 和 CockroachDB 是两个在广域网上优化了强一致性事务的系统。

outside_default.png

故障恢复

在故障恢复技术上,传统数据库关注如何保证修改没有丢失,而更新的数据库则关注如何减少宕机的时间,因为现代的互联网应用希望永远在线。

传统数据库系统进行恢复的过程大致是,数据库加载最近的 checkpoint,然后从磁盘上读取 WAL 并重放,最后恢复成宕机前的状态。这种模式的典型方法就是由 IBM 在 1990 年代提出的 ARIES 协议,几乎所有的数据库都实现了它的某些变种。

在分布式数据库系统中,这样的方法变得不太可行。这是因为当 master 节点宕机了之后,集群会选出新的节点作为 master 继续运行。如果原来的 master 恢复时只读取本地的 checkpoint 和 wal,那就会导致更新丢失。为了正确恢复,有两种方法来实现。一种是宕机的节点先在本地读取 checkpoint 和 wal 进行恢复,然后再从集群里拉取日志更新那些它没有的数据,只要获取并应用日志的速度比系统接收外界修改的速度快,那么最终就可以恢复成功。还有一种方式就是宕机节点直接丢弃自己的 checkpoint 和 wal,从集群的 master 中获取一个 checkpoint 并加载,然后再获取后续的 wal。这样做的好处是可以减少恢复的时间(如果宕机了很久,缺失的 WAL 可能会非常多),同时这套机制也可以用来进行集群扩容。

中间件架构和 DBaaS 系统通常依赖于它们原有数据库的恢复机制,但是它们也为其增加了一些领导者选举机制和其他管理功能。基于新架构的 NewSQL 系统通常会使用现成组件(ZooKeeper、Raft)和自己实现的组件(Paxos)的组合。在 1990 年代以后,这些都是分布式系统的标准技术。

未来的趋势

作者认为 NewSQL 系统未来的趋势是在新鲜数据上进行分析型查询和机器学习,这样的负载被称为实时分析(real-time analytics)或者 HTAP(hybrid transaction-analytical processing)。这样做的原因在于,现代互联网应用产生的数据在产生的那一刻就具有重要的价值,但是随着时间的推移这些数据的价值在慢慢降低。目前想要处理 HTAP 负载,主要有三种方式。

最常见的方案就是使用不同的 DBMS,一个用来处理在线事务,一个用来运行分析查询。在这种架构中,前端 OLTP 数据库存储所有事务产生的新信息,然后经过 ETL 将数据加载到 OLAP 数据库中,在 OLAP 数据库里运行长时间的复杂查询。

第二种是所谓的 lambda 架构,使用一个单独的批计算系统(例如 Hadoop 或者 Spark)在历史数据上进行计算,同时使用一个流计算系统(例如 Storm 或者 Flink)来提供实时数据的计算信息。

上面这两种架构有一些问题,其中最重要的就是在不同的系统之间传递数据需要几十分钟甚至几个小时,这使得应用不能对最新的数据做出反应。第二个问题是,管理、部署、维护两套系统的开销非常大,甚至可以占到整个系统总成本的 50%。如果开发者想获取在多套系统上的数据,他们就得为每个系统都写一个查询。

第三种架构就是使用 HTAP DBMS,其可以支持高吞吐、低延迟的事务,也可以运行复杂的、长时间的 OLAP 查询。HTAP 系统和过去系统不同的一点在于,它们将 OLTP 系统的优势(内存存储、无锁执行)和 OLAP 的优势(列存、向量化执行)结合在了一个系统中。

SAP HANA 和 MemSQL 是第一个在市场上以 HTAP 为卖点的 NewSQL 系统。HANA 通过使用多个执行引擎来实现这个目标,它有一个行存引擎来执行事务,以及一个列存引擎来执行 OLAP 查询。MemSQL 有两个不同的 StorageManager,分别负责行存和列存,但是他们共享同一个执行引擎。HyPer、VoltDB、S-Store 等系统也在不同程度上支持了 HTAP 负载。作者预测,2000 年代开发的 OLAP 数据库也会开始支持 OLTP 负载。

当然,HTAP 系统的兴起不代表过去 OLAP 系统会消失,因为目前这类系统仍然扮演着多个前端数据库的统一后端。但是最终,未来数据库的用户无需在不同系统间移动数据就可以在多个 OLTP 数据库甚至是多个供应商的数据库中执行 OLAP 查询。

尾巴

从文中的分析可以看出,NewSQL 系统并非现有系统架构的根本性改变,而是数据库技术持续发展的演进。这些系统所采用的大多数技术都已存在于学术界和工业界先前的 DBMS 中,但许多技术以前只在单个系统中一次实现一项,而不是全部集成在一起。因此,这些 NewSQL DBMS 的创新之处在于它们将这些想法整合到单一系统中,要做到这一点绝非在工程上微不足道的努力。NewSQL 的产生是时代的产物,因为现在的分布式计算资源丰富且廉价,互联网等应用对数据的需求也大大增加。

还有一个比较有趣的点在于 NewSQL 系统的市场份额,因为传统数据库厂商有钱且根基深厚,NewSQL 系统很难获取这些市场。在过去已经有不少的 NewSQL 公司倒闭(例如 GenieDB、Xeround、Translattice)或者转去做别的领域(例如 ScaleBase、ParElastic)。作者根据与这些公司的交流,认为这种现象的原因是相比那些选择 NoSQL 数据库的公司,使用事务处理业务的公司通常都是开发企业级应用的,他们相比互联网应用对数据库的选择更加保守。NewSQL 系统的目标是代替那些已有的数据库系统,而 NoSQL 则是在那些新的应用中使用。

2000 年代发展的 OLAP 数据库创业公司大多被主流的大公司所收购,而目前只有一家 NewSQL 公司被收购(2016 年 3 月 Tableau 收购了 HyPer 背后的创业公司)。大部分的大公司选择改进自己的系统,而不是直接收购 NewSQL 公司。例如 Microsoft 在 2014 年为 SQL Server 增加了内存引擎 Hekaton 来改善 OLTP 性能,Oracle 和 IBM 也为他们的系统增加了列存插件,也许不久的将来就会增加 In-memory OLTP 功能。

长远来看,作者认为下面四类数据库:

  • 1980-1990 年代开发的老一代数据库

  • 2000 年代开发的 OLAP 数据仓库

  • 2000 年代开发的 NoSQL 数据库

  • 2010 年代开发的 NewSQL 数据库

它们的特征会在未来得到融合。预计这些重要系统将会支持某种形式的关系模型和 SQL(如果他们还没有的话),以及像 HTAP DBMS 一样同时支持 OLTP 操作和 OLAP 查询。当这种情况发生时,这些所有的标签就都没有意义了。

总结

这篇文章是一篇很好的回顾性文章,带我们了解数据库系统的演进过程,NewSQL 系统的一些核心技术及未来的发展趋势。我对这篇文章里印象最深刻的是作者多次提到 "... is not a new idea",在几十年前 NewSQL 系统里的许多核心技术就已经被提出和实践了。这些技术之所以过去没有得到广泛关注,而现在则重新受到重视,很大程度上是因为硬件的发展和应用的需求变化,这大概就是时势造英雄吧。这篇文章让我回想起今年我思考的一个问题:如果抛开硬件的进步(更快的计算设备、SSD 、RDMA 等),仅在软件层面,存储系统和数据库系统在过去二十年里有多少进步?

另一个方面来说,数据库系统演进的这段历史也让我意识到了数据库技术的发展方向始终是以解决应用侧的痛点为目标的。今年在面试的时候被问到了一个问题:“你认为未来 30 年最好的时序数据库应该是怎么样的?”当时的我并没有回答出来。现在再回过头看这个问题,其实数据库如何发展也许并不取决于数据库自身,而是取决于应用对数据库提出了什么样的要求。最好的时序数据库是什么样的,取决于业务层需要什么样的数据库。我认为这和我在阿里云实习的时候老板们常说的“客户第一”所表达的意思某种程度上是一样的。

Apache IoTDB 是一款低成本、高可用的物联网原生时序数据库,采用端边云协同的轻量化结构,支持一体化的物联网时序数据收集、存储、管理与分析,具有多协议兼容、超高压缩比、高通量读写、工业级稳定、极简运维等特点。目前已服务规上工业企业超过 1000 家

作为全球性开源项目,截至目前,Apache IoTDB 已拥有 262 名贡献者、4.1K Stars、951 Forks、9937 Commits。我们为大家提供了参与指南,欢迎越来越多的小伙伴助力 Apache IoTDB 项目的不断发展与前进,迈出加入 Apache IoTDB 社区的第一步!

【社区同学好文分享】[SIGMOD Record 2016] NewSQL 究竟新在哪里_第1张图片

你可能感兴趣的:(【社区同学好文分享】[SIGMOD Record 2016] NewSQL 究竟新在哪里)