数据库系统的发展和现状
按照国外一个比较权威的网站 DB-Engines 的分类,目前的数据库系统大概有 14 种之多,包括传统的关系型数据库、键值对存储数据库、文档型存储数据库、时间序列数据库、面向对象数据库、搜索引擎、图形数据库和列存储数据库等等。它们大致上可以简单划分为三大类:SQL、NoSQL 和 NewSQL。
单机数据库时代
自从 1970 年 E.F.Codd 博士在《Communication of the ACM》上发表《A Relational Model of Data for Large Shared Data Banks》论文,提出关系模型的概念,关系型数据库系统经过几十年的发展,技术已经比较成熟和完善。其中比较有代表性的产品包括甲骨文公司的 Oracle,微软公司的 SQL Server,IBM 公司的 Db2 以及惨遭收购的 MySQL。
在很长一段时间内,关系型数据库一直是大公司的专利,数据库市场一度被 Oracle、Db2 等企业数据库瓜分。直到上个世纪九十年代,MySQL 的第一个版本诞生,关系型数据库才终于有了一个开源免费的实现。虽然 MySQL 相对于 Oracle 这样的大型商业数据库来说规模较小、功能较弱,但这丝毫不影响它的受欢迎程度。甚至在 2010 年以前,互联网上流行的网站架构 LAMP 就将 MySQL 作为默认使用的数据库软件。
在 MySQL 之后,还有一个值得一提的关系型数据库系统,它就是 PostgreSQL。作为差不多和 MySQL 同期的开源关系型数据库系统,PostgreSQL 不管是代码的质量还是对 SQL 的支持都要优于 MySQL。
分布式数据库时代
随着互联网的蓬勃发展,网络服务的大流量、高并发将传统关系型数据库的弊端暴露了出来。传统关系型数据库最大的优点就是能够通过 SQL 实现复杂的查询以及对 ACID 事务的支持,这使它能够适用于那些对一致性要求很高的系统,如:银行系统、OA 系统等。但是互联网的发展以及移动互联网的兴起使得很多网络服务,例如微博、facebook 等,对于这种一致性的要求已经不是那么严格,它们更多的要求并发读写和海量存储,而传统的关系型数据库为了维护一致性所付出的代价就是读写性能较差,同时传统的关系型数据库还有一个很大的缺陷就是难以水平扩展,为了提高数据库的性能,最简单的方式就是纵向扩展,即通过升级硬件来提高磁盘 I/O 和数据库的并发性能,但是硬件升级所带来的成本提升让企业越来越难以接受,于是人们又不得不再去寻找水平扩展的方案,目前业内主流的一些做法或多或少都存在一些问题(部署、管理和配置复杂,使用限制较多,可能存在单点故障的风险等)。这时,人们急切需要一种并发读写性能强劲、具有较高伸缩性和扩展性、支持海量数据存储的数据存储系统,于是 NoSQL 应运而生。
提到 NoSQL,就不得不提及两个公司,一个是 Google,另一个就是 Amazon。
Google 应该算是最早将分布式存储技术应用到大规模生产环境的公司,目前业界的很多分布式系统的思想和实践大都来源于 Google。2003 年,Google 公布了自家使用的分布式文件系统 GFS 的一些技术细节,2006 年又发表了基于 GFS 的分布式键值对存储系统 BigTable 的论文,直接催生了 Hadoop 的生态。
Amazon 在 2007 年发表了关于 Dynamo 的论文,文中引入了最终一致性的概念、NRW 的模型以及向量时钟的应用,同时将一致性 Hash、Merkle tree 等在当时很新潮的一些技术整合起来,这些技术对后来的非关系型数据库有很大的影响,可以说是正式标志着 NoSQL 的诞生。
在 2006 年前后至今,一个比较重要的思潮就是数据库(持久化)和缓存开始有明确的分离。随着业务并发的提升,以及内存价格越来越便宜,基于内存的存储方案也逐渐普及。内存缓存也经历了从单机到分布式的过程,只不过这个过程要比关系型数据库的进化快的多,这是因为 NoSQL 从当时互联网业务模型相对简单的实际出发,抛弃了关系模型,选择了更为简单的键值对和文档类型进行存储,数据结构和查询接口更加简单,没有了复杂 SQL 以及 ACID 事务的历史包袱,灵活性和弹性扩展能力更强。
NoSQL 中的缓存方案具有代表性的就是 memcached 和 Redis。memcached 在 2009 年之前一度成为开源缓存事实上的标准,但是 Redis 的出现颠覆了缓存市场,现在大多数的缓存业务几乎都使用的是 Redis,memcached 基本上退出了历史舞台。后来因为单机 Redis 已经不能满足业务发展需求,人们又开始寻找扩展 Redis 的方案,这方面比较有代表性的就是 twitter 开源的 twemproxy,Redis 官方难产了好久才发布的 Redis Cluster 以及 2014 年国内的一个团队开源的 Codis。在缓存上,开源社区现在基本上是围绕着 Redis 及其周边扩展发展。
NoSQL 中的持久化方案比较有代表性的就是 MongoDB、HBase 和 Cassandra 了。MongoDB 在早期因为没有使用存储引擎,所以性能并不太好,但是它 Schema-less 的特性适合很多轻量级和快速变更的互联网业务,并且由于它基本上做到了开箱即用,因此使用者众多。2014 年 MongoDB 收购了 WiredTiger 并将它作为默认的存储引擎,因此性能和稳定性都有了很大的提升。HBase 作为 GFS 的正统实现,严格上来说算是一个 CP 系统,底层依赖 HDFS,能够很好地处理海量、小的、结构化数据的插入、更新以及随机读请求,但是没有提供 ACID 的跨行事务支持,并且易用性也不佳。Cassandra 是 Dynamo 的开源实现,早期由 Facebook 开发并开源,但是由于 bug 较多而被 Facebook 放弃,后来由 DataStax 重新维护并商业化。作为一个 AP 系统,Cassandra 在易用性上要优于 HBase,并且由于它的数据直接存储在磁盘上,并不依赖于分布式文件系统,各个存储节点之间自己维护复制关系,因此减少了一层 RPC 调用,延迟上要比 HBase 更有优势。
NewSQL
NewSQL 指的是一类现代关系型数据库系统,它不光能够为 OLTP(联机事务处理)提供类似 NoSQL 那样的高度扩展性,还能够提供类似传统关系型数据库的 ACID 事务的支持。
2012 年,Google 在 OSDI 上发表了 Spanner 的论文,2013 年,又在 SIGMOD 上发表了 F1 的论文。这两篇论文让业界第一次看到了关系模型和 NoSQL 的扩展性在超大规模集群上融合的可能性。
Spanner 的创新之处在于通过 GPS 和原子钟来解决时钟同步的问题。在分布式系统中,时钟是最头疼的问题,这也是为什么 Cassandra 不是一个强一致性系统的原因。Spanner 的厉害之处在于即使两个数据中心相隔很远,它们之间也不需要通信(通信代价太大,理想状态下也只是光速)就能够保证 TrueTime API 的时钟误差在一个很小的范围内(10 ms)。F1 构建在 Spanner 之上,对外提供了更加丰富的 SQL 语法,它本身并不存储数据,而是将客户端的 SQL 翻译成类似 MapReduce 的任务,通过调用 Spanner 来完成请求。总的来说,Spanner 和 F1 有以下几个特点:
- 完整的 SQL 以及 ACID 事务支持。
- 良好的弹性伸缩能力。
- 自动的故障转移和故障恢复,多机房异地灾备。
Google 论文的发表鼓舞了开源社区,许多团队争相开始实现,其中比较有代表性的包括 Ignite、VoltDB、CockroachDB、Altibase、GridGain、TiDB 等等。CockroachDB 选择了 HLC(Hybrid logical clock),也就是 NTP + 逻辑时钟来代替 TrueTime,使用 Raft 代替 Paxos 实现复制和自动容灾,底层存储依赖 RocksDB 的实现,对外接口选用 PostgreSQL 的 SQL 子集。TiDB 是国内团队 PingCAP 的开源实现,它并不像 CockroachDB 那样选择将 SQL 和 Key-Value 融合,而是像 Spanner 和 F1 一样选择分离,同时由于选择了 MySQL 协议和语法的兼容,因此很多 MySQL 社区的 ORM 框架和运维工具都可以直接应用在 TiDB 上。
其实 NewSQL 可以松散的划分为三大类,其中第一类也就是主流的就是上面说到的新的关系型数据库系统,另一类就是针对 SQL 进行了高度优化的存储引擎。这些引擎提供与 SQL 相同的编程接口,但同时提供了比内置引擎(如:InnoDB)更好的扩展性。这些新的存储引擎包括:Google 开源的 Bigtable 底层存储引擎 LevelDB、Facebook 维护并改进的 LevelDB 分支 RocksDB、Facebook 使用 RocksDB 实现的全新的 MySQL 存储引擎 MyRocks、MySQL Cluster、MariaDB Columnstore 以及具有极高压缩比的 TokuDB 等等。
还有一类是可以透明分片(Transparent sharding)的中间件,它支持跨多个节点自动拆分数据库,具有代表性的就是 ScaleBase、Vitess 和 Postgres-XC,它们差不多就是数据库分库分表中间件的尽头了。
参考
Bigtable: A Distrib uted Storage System for Structur ed Data