申砾:细说分布式数据库的过去、现在与未来

随着大数据这个概念的兴起以及真实需求在各个行业的落地,很多人都热衷于讨论分布式数据库,今天就这个话题,主要分为三部分:第一部分讲一下分布式数据库的过去和现状,希望大家能对这个领域有一个全面的了解;第二部分讲一下 TiDB 的架构以及最近的一些进展;最后结合我们开发 TiDB 过程中的一些思考讲一下分布式数据库未来可能的趋势。

一、分布式数据库的历史和现状

申砾:细说分布式数据库的过去、现在与未来_第1张图片
1dbe000048ec26920c87.jpg-24.3kB

1、从单机数据库说起

关系型数据库起源自 1970 年代,其最基本的功能有两个:

  • 把数据存下来;

  • 满足用户对数据的计算需求。

第一点是最基本的要求,如果一个数据库没办法把数据安全完整存下来,那么后续的任何功能都没有意义。当满足第一点后,用户紧接着就会要求能够使用数据,可能是简单的查询,比如按照某个 Key 来查找 Value ;也可能是复杂的查询,比如要对数据做复杂的聚合操作、连表操作、分组操作。往往第二点是一个比第一点更难满足的需求。

在数据库发展早期阶段,这两个需求其实不难满足,比如有很多优秀的商业数据库产品,如Oracle/DB2 。在 1990 年之后,出现了开源数据库 MySQL 和 PostgreSQL 。这些数据库不断地提升单机实例性能,再加上遵循摩尔定律的硬件提升速度,往往能够很好地支撑业务发展。

接下来,随着互联网的不断普及特别是移动互联网的兴起,数据规模爆炸式增长,而硬件这些年的进步速度却在逐渐减慢,人们也在担心摩尔定律会失效。在此消彼长的情况下,单机数据库越来越难以满足用户需求,即使是将数据保存下来这个最基本的需求。

2、分布式数据库

所以 2005 年左右,人们开始探索分布式数据库,带起了 NoSQL 这波浪潮。这些数据库解决的首要问题是单机上无法保存全部数据,其中以 HBase/Cassadra/MongoDB 为代表。为了实现容量的水平扩展,这些数据库往往要放弃事务,或者是只提供简单的 KV 接口。存储模型的简化为存储系统的开发带来了便利,但是降低了对业务的支撑。

(1)NoSQL 的进击

HBase 是其中的典型代表。 HBase 是 Hadoop 生态中的重要产品,Google BigTable 的开源实现,所以这里先说一下 BigTable 。

BigTable 是 Google 内部使用的分布式数据库,构建在 GFS 的基础上,弥补了分布式文件系统对于小对象的插入、更新、随机读请求的缺陷。HBase 也按照这个架构实现,底层基于HDFS 。 HBase 本身并不实际存储数据,持久化的日志和 SST file 存储在 HDFS 上,Region Server 通过 MemTable 提供快速的查询,写入都是先写日志,后台进行Compact ,将随机写转换为顺序写。数据通过 Region 在逻辑上进行分割,负载均衡通过调节各个 Region Server 负责的Region区间实现,Region在 持续写入后,会进行分裂,然后被负载均衡策略调度到多个 Region Server 上。

前面提到了, HBase 本身并不存储数据,这里的 Region 仅是逻辑上的概念,数据还是以文件的形式存储在 HDFS 上,HBase 并不关心副本个数、位置以及水平扩展问题,这些都依赖于 HDFS 实现。和 BigTable 一样, HBase 提供行级的一致性,从 CAP 理论的角度来看,它是一个 CP 的系统,并且没有更进一步提供 ACID 的跨行事务,也是很遗憾。

HBase 的优势在于通过扩展 Region Server 可以几乎线性提升系统的吞吐,及 HDFS 本身就具有的水平扩展能力,且整个系统成熟稳定。但 HBase 依然有一些不足。首先, Hadoop 使用 Java 开发, GC 延迟是一个无法避免问题,这对系统的延迟造成一些影响。另外,由于HBase 本身并不存储数据,和 HDFS 之间的交互会多一层性能损耗。第三, HBase 和BigTable 一样,并不支持跨行事务,所以在 Google 内部有团队开发了 MegaStore 、 Percolator 这些基于 BigTable 的事务层。 Jeff Dean 承认很后悔没有在 BigTable 中加入跨行事务,这也是 Spanner 出现的一个原因。

(2)RDMS 的救赎

除了 NoSQL 之外, RDMS 系统也做了不少努力来适应业务的变化,也就是关系型数据库的中间件和分库分表方案。做一款中间件需要考虑很多,比如解析 SQL ,解析出 ShardKey ,然后根据 ShardKey 分发请求,再合并结果。另外在中间件这层还需要维护 Session 及事务状态,而且大多数方案并不支持跨 shard 的事务,这就不可避免地导致了业务使用起来会比较麻烦,需要自己维护事务状态。此外,还有动态的扩容缩容和自动的故障恢复,在集群规模越来越大的情况下,运维和 DDL 的复杂度是指数级上升。

国内开发者在这个领域有过很多的著名的项目,比如阿里的 Cobar 、 TDDL ,后来社区基于Cobar 改进的 MyCAT , 360 开源的 Atlas 等,都属于这一类中间件产品。在中间件这个方案上有一个知名的开源项目是 Youtube 的 Vitess ,这是一个集大成的中间件产品,内置了热数据缓存、水平动态分片、读写分离等,但这也造成了整个项目非常复杂。

另外一个值得一提的是 PostgreSQL XC 这个项目,其整体的架构有点像早期版本的OceanBase ,由一个中央节点来处理协调分布式事务,数据分散在各个存储节点上,应该是目前 PG 社区最好的分布式扩展方案,不少人在基于这个项目做自己的系统。

3、NewSQL的发展

2012 ~ 2013 年 Google 相继发表了 Spanner 和 F1 两套系统的论文,让业界第一次看到了关系模型和 NoSQL 的扩展性在一个大规模生产系统上融合的可能性。 Spanner 通过使用硬件设备( GPS 时钟+原子钟)巧妙地解决时钟同步的问题,而在分布式系统里,时钟正是最让人头痛的问题。Spanner 的强大之处在于即使两个数据中心隔得非常远,也能保证通过TrueTime API 获取的时间误差在一个很小的范围内( 10ms ),并且不需要通讯。 Spanner 的底层仍然基于分布式文件系统,不过论文里也说是可以未来优化的点。

Google 的内部的数据库存储业务,大多是 3 ~ 5 副本,重要的数据需要 7 副本,且这些副本遍布全球各大洲的数据中心,由于普遍使用了Paxos ,延迟是可以缩短到一个可以接受的范围(写入延迟 100 ms以上),另外由 Paxos 带来的 Auto-Failover 能力,更是让整个集群即使数据中心瘫痪,业务层都是透明无感知的。 F1 是构建在 Spanner 之上,对外提供了 SQL 接口, F1 是一个分布式 MPP SQL 层,其本身并不存储数据,而是将客户端的 SQL 翻译成对KV 的操作,调用 Spanner 来完成请求。

Spanner 和 F1 的出现标志着第一个 NewSQL 在生产环境中提供服务,将下面几个功能在一套系统中提供:

1、SQL 支持

2、ACID 事务

3、水平扩展

4、Auto Failover

5、多机房异地容灾

正因为具备如此多的诱人特性,在 Google 内部,大量的业务已经从原来的 BigTable 切换到Spanner 之上。相信这对业界的思路会有巨大的影响,就像当年的 Hadoop 一样, Google 的基础软件的技术趋势是走在社区前面的。

Spanner/F1 论文引起了社区的广泛的关注,很快开始出现了追随者。第一个团队是CockroachLabs 做的 CockroachDB 。 CockroachDB 的设计和 Spanner 很像,但是没有选择 TrueTime API ,而是使用 HLC( Hybrid logical clock ),也就是 NTP +逻辑时钟来代替 TrueTime 时间戳,另外 CockroachDB 选用 Raft 做数据复制协议,底层存储落地在RocksDB 中,对外的接口选择了 PG 协议。

CockroachDB 的技术选型比较激进,比如依赖了 HLC 来做事务,时间戳的精确度并没有办法做到 10 ms内的延迟,所以 Commit Wait 需要用户自己指定,其选择取决于用户的 NTP 服务时钟误差,这点对于用户来说非常不友好。当然 CockroachDB 的这些技术选择也带来了很好的易用性,所有逻辑都在一个组件中,部署非常简单,这个是非常大的优点。

另一个追随者就是我们做的 TiDB 。这个项目已经开发了两年时间,当然在开始动手前我们也准备了很长时间。接下来我会介绍一下这个项目。

二、 TiDB 的架构和最近进展##

TiDB 本质上是一个更加正统的 Spanner 和 F1 实现,并不 CockroachDB 那样选择将 SQL 和KV 融合,而是像 Spanner 和 F1 一样选择分离。下面是 TiDB 的架构图:


申砾:细说分布式数据库的过去、现在与未来_第2张图片
640.png-33kB

这样分层的思想也是贯穿整个 TiDB 项目始终的,对于测试,滚动升级以及各层的复杂度控制会比较有优势,另外 TiDB 选择了 MySQL 协议和语法的兼容, MySQL 社区的 ORM 框架、运维工具,直接可以应用在 TiDB 上,另外和 Spanner 一样,TiDB 是一个无状态的 MPP SQL Layer ,整个系统的底层是依赖 TiKV 来提供分布式存储和分布式事务的支持,TiKV 的分布式事务模型采用的是 Google Percolator 的模型,但是在此之上做了很多优化, Percolator 的优点是去中心化程度非常高,整个继续不需要一个独立的事务管理模块,事务提交状态这些信息其实是均匀分散在系统的各个 key 的 meta 中,整个模型唯一依赖的是一个授时服务器,在我们的系统上,极限情况这个授时服务器每秒能分配 400 w以上个单调递增的时间戳,大多数情况基本够用了(毕竟有 Google 量级的场景并不多见),同时在 TiKV 中,这个授时服务本身是高可用的,也不存在单点故障的问题。

申砾:细说分布式数据库的过去、现在与未来_第3张图片
640.jpg-23.1kB

上面是 TiKV 的架构图。 TiKV 和 CockroachDB 一样也是选择了 Raft 作为整个数据库的基础,不一样的是, TiKV 整体采用 Rust 语言开发,作为一个没有 GC 和 Runtime 的语言,在性能上可以挖掘的潜力会更大。不同 TiKV 实例上的多个副本一起构成了一个 Raft Group ,PD 负责对副本的位置进行调度,通过配置调度策略,可以保证一个 Raft Group 的多个副本不会保存在同一台机器/机架/机房中。

除了核心的 TiDB、TiKV 之外,我们还提供了不少易用的工具,便于用户做数据迁移和备份。比如我们提供的 Syncer ,不但能将单个 MySQL 实例中的数据同步到 TiDB ,还能将多个 MySQL 实例中的数据汇总到一个 TiDB 集群中,甚至是将已经分库分表的数据再合库合表。这样数据的同步方式更加灵活好用。

TiDB 目前即将发布 RC3 版本,预计六月份能够发布 GA 版本。在即将到来的 RC3 版本中,对 MySQL 兼容性、 SQL 优化器、系统稳定性、性能做了大量的工作。对于 OLTP 场景,重点优化写入性能。另外提供了权限管理功能,用户可以按照 MySQL 的权限管理方式控制数据访问权限。对于 OLAP 场景,也对优化器做了大量的工作,包括更多语句的优化、支持SortMergeJoin 算子、 IndexLookupJoin 算子。另外对内存使用也做了大量的优化,一些场景下,内存使用下降 75 %。

除了 TiDB 本身的优化之外,我们还在做一个新的工程,名字叫 TiSpark 。简单来讲,就是让 Spark 更好地接入 TiDB 。现在其实 Spark 已经可以通过 JDBC 接口读取 TiDB 中的数据,但是这里有两个问题:1. 只能通过单个 TiDB 节点读取数据且数据需要从 TiKV 中经过 TiDB 中转。2. 不能和 Spark 的优化器相结合,我们期望能和 Spark 的优化器整合,将 Filter 、聚合能通过 TiKV 分布式计算能力提速。这个项目已经开始开发,预计近期开源,五月份就能有第一个版本。

三、分布式数据库的未来趋势##

关于未来,我觉得未来的数据库会有几个趋势,也是 TiDB 项目追求的目标:

1、数据库会随着业务云化,未来一切的业务都会跑在云端,不管是私有云或者公有云,运维团队接触的可能再也不是真实的物理机,而是一个个隔离的容器或者「计算资源」,这对数据库也是一个挑战,因为数据库天生就是有状态的,数据总是要存储在物理的磁盘上,而数据移动的代价比移动容器的代价可能大很多。

2、多租户技术会成为标配,一个大数据库承载一切的业务,数据在底层打通,上层通过权限,容器等技术进行隔离,但是数据的打通和扩展会变得异常简单,结合第一点提到的云化,业务层可以再也不用关心物理机的容量和拓扑,只需要认为底层是一个无穷大的数据库平台即可,不用再担心单机容量和负载均衡等问题。

3、 OLAP 和 OLTP 业务会融合,用户将数据存储进去后,需要比较方便高效的方式访问这块数据,但是 OLTP 和 OLAP 在 SQL 优化器/执行器这层的实现一定是千差万别的。以往的实现中,用户往往是通过 ETL 工具将数据从 OLTP 数据库同步到 OLAP 数据库,这一方面造成了资源的浪费,另一方面也降低了OLAP 的实时性。对于用户而言,如果能使用同一套标准的语法和规则来进行数据的读写和分析,会有更好的体验。

4、在未来分布式数据库系统上,主从日志同步这样落后的备份方式会被 Multi-Paxos / Raft这样更强的分布式一致性算法替代,人工的数据库运维在管理大规模数据库集群时是不可能的,所有的故障恢复和高可用都将是高度自动化的。

你可能感兴趣的:(申砾:细说分布式数据库的过去、现在与未来)