1.3 分布式存储系统
与单机系统类似,分布式系统的存储也分为两个层次:第一个层次是文件级的,即分布式文件系统,如GFS(Google File System)、HDFS(Hadoop Distributed File System)、TFS(Taobao File System)等;第二个层次是在文件系统之上的进一步抽象,即数据库系统。不过,分布式系统下的数据库远比单机的关系型数据库复杂,因为数据被存储在多个节点上,如何保证其一致性就成了关键,所以,分布式系统下的数据库采用的大都是最终一致性[6],而非满足ACID[7]属性的强一致性。
由于对一致性支持的不同,传统的ACID理论就不再适用了,于是,Eric Brewer提出了一种新的CAP[8]理论。CAP理论听起来高大上,但实际上并没有那么复杂。它的意思是,在分布式系统里,没有办法同时达到一致性、可用性和网络分区可容忍性,只能在三者中择其二。
不过,要注意CAP中的C和A与ACID中的C和A的含义是不同的(如表1-1所示),网络分区可容忍性的含义较为晦涩,是指一个分布式系统中是否允许出现多个网络分区。换言之,如果网络断了,一个系统中的多个节点被分成了多个孤岛,这允许吗?如果允许,就满足网络分区可容忍性,否则就不满足。
表1-1 CAP与ACID中的C和A的不同
对于CAP理论,其实很好理解。我们可以想一想,如果需要满足网络分区可容忍性,即允许孤岛的存在,那么当孤岛产生时,只能要么继续提供服务(即满足可用性),要么停止服务(即满足一致性),其他的情况也类似。然而,在分布式系统中,由于孤岛的不可避免性,因此实际的系统只能在一致性和可用性中选择其一,即只能是满足一致性和网络分区可容忍性或者满足可用性和网络分区可容忍性的系统。
采用最终一致性的数据库系统,统称为NoSQL(Not only SQL)系统。根据数据模型的不同,NoSQL系统又分为以下几大类:
- 基于键值对的(如Memcached、Redis等);
- 基于列存储的(如谷歌的Bigtable、Apache HBase、Apache Cassandra等);
- 基于文档的(如MongoDB、CouchDB等);
- 基于图的(如Neo4j、OrientDB等)。
近几年,还涌现出一类称为NewSQL的系统(如谷歌的Megastore、谷歌的Spanner、阿里巴巴的OceanBase和PingCAP TiDB),号称既满足关系型数据库的ACID属性,又可以如NoSQL系统那般水平伸缩。然而,这些系统本质上还是满足最终一致性的NoSQL系统,只不过,它们将可用性和一致性处理得非常好,在外界看来,似乎同时满足了可用性和一致性,实则只是在实现上做了“手脚”,将不一致性“隐藏”起来,并将其“默默”地消化掉。
例如,谷歌Megastore将同一数据的不同分区存放在不同的数据中心中,在每个数据中心内部,属于同一个分区的数据存放在同一个Bigtable中。借助于Bigtable对单行数据读写的事务支持,Megastore支持同一个分区内的ACID属性,但对于跨分区(即跨数据中心)的事务,则通过两阶段提交实现,因此,也是最终一致的。
再如阿里巴巴的OceanBase,它将数据分为两部分,一部分是较早的数据(称为基准数据),另一部分是最新的数据(称为增量数据),基准数据与增量数据分开存储,读写请求都由一个专门的合并服务器(Merge Server)来处理。合并服务器解析用户的SQL请求,然后生成相应的命令发给存储基准数据和增量数据的服务器,再合并它们返回的结果;此外,后台还定期将增量数据合并到基准数据中[9]。OceanBase定期将更新服务器(Update Server)上的增量数据合并到各个数据块服务器(Chunk Server)中。因此,OceanBase也是最终一致的,但通过合并服务器把暂时的不一致隐藏起来了。
因此,本质上,只有两种数据库系统,即满足ACID属性的RDBMS和满足最终一致性的NoSQL系统。所谓的NewSQL,只不过是披着SQL系统外衣(即SQL支持和ACID属性)的NoSQL系统而已。