在他看来,下面几类数据库在云中工作很好:
- 数据仓库型特定数据库,为批量数据处理和Map/Reduce作业设计的
- 简单,可扩展和快速的键值对存储
- 包含比键值对存储更丰富特性的数据库,填补了传统RDBMS的空白,并提供良好的性能和扩展性(如文档数据库)
博主Nati Shalom同意Merriman,事实上应用领域如云计算等对NoSQL数据库是助力:“过去是只有少数相当高端的组织面对的利基问题,随着社交网络和云计算的引入更为普遍了([ Sha09a ])。
RDBMS加缓存层模式/工作区 vs. 考虑扩展性从零开始构建系统 在他的文章“MySQL和Memcached:一个时代的结束?”中,Todd Hoff说“在云出现前,关系型数据库为主的世界”的可扩展性是“利用MySQL和memcached”的一个问题:
“对MySQL分片以处理高写入负载,再memcached中缓存对象以处理高读负载,然后写了大量的胶水代码使其全部工作在一起。那曾经是艺术,那曾经是必须这样做的。今天许多主要网站的架构仍遵循这种模式,很大程度上是因为在投入足够的力气时,它可以工作。”([ Hof10c ])
但随着可扩展性要求的增长,这些技术越来越不能够适应他们。此外,随着NoSQL数据存储的发展Hoff得出结论:“看远一点,很明显MySQL + memcached的时代正在过去。它将坚持一段时间。旧技术很少完全消失。”([ Hof10c ])。作为例子,他列举了大网站和玩家走向非关系数据存储包括LinkedIn、Amazon、Digg和Twitter。Hoff提到以下使用NoSQL解决方案的原因,已在本文前面解释:
- 关系数据库在读时计算,这对大型网络应用(如Digg)被认为是错误的。NoSQL数据库因此不提供或避免复杂的读操作。
- 应用程序的线性特性需要经常等待从数据存储的I/O,这对可扩展性和低响应时间不利。
- 大数据量和高的生长因子促进Twitter开始使用Cassandra,它被设计为可操作大尺度数据。
- 此外,像Twitter这样的公司运行和维护系统的运营成本不断上升。这种规模的网络应用因而“需要一个可以以更自动化的方式来发展并高度可用的系统”(在[ hof10c ]引用)。
由于这些原因以及MySQL和memcached时代的“笨拙性”(Hoff所谓的),现在的大型(网络)应用程序可以利用从头开始建立可扩展性的、非阻塞和异步数据库I/O、海量数据、维护和操作任务的自动化处理的系统。他认为这些系统是更好的替代品,相比RDBMS加对象缓存。Amazon的James Hamilton同意这一声明,对许多大型网站的可扩展性,从零开始是至关重要的,甚至比与传统RDBMS相比缺少部分特性的劣势更重要:
“扩展第一的应用程序是那些绝对必须不受约束地扩展,且无约束扩展这件事比更多的特性更重要。这些应用有大规模大型网站如Facebook、MySpace、Gmail、Yahoo和Amazon。一些网站实际上是利用关系数据库,但很多不是。所有这些服务的共同主题是,扩展比特性更重要,他们没有可能运行在一个单独的RDBMS上。”(参见[ Ham09 ]引用[ Sha09a ])
昨日的需要 vs. 今日的需要 在关于CouchDB的讨论中,Lehnardt和Lang指出对于数据存储的需要已经发生了很大的变化([ PLL09 ];这一论点由Stonebraker进一步迭代,见下文)。在上世纪60和70年代的数据库被设计为单一的大型高端机器。与此相反,今天,许多大型(网络)公司使用可能会故障的商用硬件。因此应用程序被设计来处理这样的故障,被认为是“操作的标准模式”,就像Amazon指出的(参见[ DHJ+07,205页])。此外,关系数据库适合的数据是刚性结构的关系,并允许用一个复杂语言表示的动态查询。Lehnhardt和Lang指出,今天,特别是在网络领域,数据既不是严格的结构,也不需要动态查询,大多数应用程序已经使用准备语句或存储过程。因此,数据库内预定义查询和动态赋值给变量是足够的([ PLL09 ])。
此外,关系数据库最初设计为集中部署,而不是分布。虽然对集群的强化已被加入,它仍然是通过传统的没有分布式的概念开始设计(像如下提出的“网络计算的设施”问题)。作为一个例子,通常同步未有效地实现,而是需要昂贵的协议,如两或三阶段提交。Lehnhardt和Lang看到的另一个困难是,关系数据库集群的尝试是“透明”的应用。这意味着应用程序不应该包含任何它在和一个单独的机器或一个集群进行交谈的概念,所有分布式的方面都试图从应用程序中隐藏。他们质疑这种保持应用程序感知不到任何分布式的后果的方法,如在著名的八个分布式计算的谬误中描述的([ Gos07 ] ):
“基本上每个人,当他们初次构建一个分布式应用程序时,会做出以下八假设。它们在长期运行过程中都被证明是错误的,都会导致大麻烦和痛苦的学习经验:
1、网络是可靠的
2、延迟是0
3、带宽是无限的
4、网络是安全的
5、拓扑是不变的
6、有一个管理员
7、传输的消耗是0
8、网络是同构的”
虽然典型的使用RDBMS的业务应用程序,在大多数情况下,尝试在应用中隐藏分布式细节(例如:通过集群、持久层做对象关系映射),但许多大型网络公司和大部分的NoSQL数据库不追求这种方法。相反,他们让应用程序知道并利用它们。这在Lehnardt和Lang眼中被认为是一个范式转变(参见[ PLL09 ])。
进一步的动机 除了上面提到的,David Intersimone看到NoSQL潮流的以下三目标([ Int10 ]):
- 获得较关系数据库小的的开销和内存占用
- 通过Web技术和RPC调用访问
- 数据查询的可选形式
2.1.2 理论工作
在广泛采用的论文“架构时代的终结”([ SMA+07 ] )中,Michael Stonebraker等得人出结论“现有的RDBMS的代码,试图成为一个’一刀切’解决方案,事实上不擅长于任何事”。在这种情况下没有任何东西意味着他们能与超越他们“1–2个数量级”([ Sc05 ]、[ SBc+07])的“数据仓库、数据流处理、文本和科学数据库市场的专用引擎”竞争,在他们熟悉的业务数据处理/在线事务处理(OLTP)市场也表现不好,其中一个麻省理工开发的名叫H-Store的原型在TPC-C基准上打败RDBMS将近两个数量级。由于这些结果,他们得出结论,RDBMS是“应退休的25岁的遗留代码,取而代之的是一系列‘从零开始’研发的专用引擎。数据库管理系统供应商(和研究界)应该开始用一张白纸为明天的要求设计系统,而不是继续为昨天的需求推动代码行和架构设计”。但Stonebraker等人如何得出这个结论?他们在关系型数据库管理系统中发现什么固有的缺陷?他们为“完全重写”提供什么建议?
首先,Stonebraker等认为,RDBMS架构已经超过25年,当时硬件特性、用户需求和数据库市场与今天的不同。他们指出,“流行的RDBMS全部能追朔到20世纪70年代的System R”:IBM的DB2是一个System R的直系后代,微软的SQL Server从Sybase System 5进化而来(另一个System R的直系后代),Oracle在其第一个版本中实现了System R的用户界面。因而,System R的架构已经被70年代的硬件特性影响了。那以后,处理器速度、内存和磁盘的大小有显著增加,这些因素今天已经不像过去那样限制程序。然而,硬盘和内存间的带宽并不像CPU速度、内存和磁盘大小那样增加得快。Stonebraker等批评,硬件领域的发展没有影响RDBMS的架构。尤其是以下的System R的架构特点仍然在今天的RDBMS中可以找到:
- 面向磁盘的存储和索引结构
- 多线程来隐藏时延
- 基于锁的并发控制机制
- 基于日志的恢复
在这方面,他们强调说,虽然“过去几年有了一些延伸,包括支持压缩、共享磁盘架构、位图索引、支持用户定义的数据类型和操作,但从一开始就没有任何系统的重新设计”。
其次,Stonebraker等人指出,自20世纪70年代以来,新的市场和用例已经出现,但可用的只有商业数据处理。这些新兴市场的例子包括“数据仓库、文本管理和流处理”,“它们的需求与商业数据处理有很大的不同”。在先前的文章([ Sc05 ])他们已经说明了RDBMS“会在一些应用领域被专业的架构超过一个数量级或更多,包括:
- 文本(专业引擎如Google,Yahoo等)
- 数据仓库(列存储如Vertica,Monet等)
- 流处理(流处理引擎如StreamBase和Coral8)
- 科学和智能数据库(数组存储引擎如MATLAB和ASAP)”
他们继续注意到,过去几十年用户界面和使用模式也改变了,从“操作员输入查询”的终端到富客户端和网络应用程序,今天互动查询和直接的SQL接口是罕见的。
Stonebraker等现在给出了“目前RDBMS的架构甚至不适合业务数据处理的证据”。他们设计了一个OLTP的DBMS引擎称为H-Store,其在功能上适于跑TPC-C基准,比流行商用DBMS快82倍。基于这样的证据,他们总结“它们在任何一个市场都没有竞争力。因此,他们应该被视为超过四分之一个世纪的过时技术,完全重新设计和重构是适当的下一步”。
设计考量
在一篇关于设计考量的文中,Stonebraker等人解释为什么即使在业务数据处理的老本行内RDBMS也被超越,以及他们自己的DBMS原型H-Store为何可以实现“比现有的RDBMS好得多的性能”。特别是他们的考虑反映过去几十年的硬件发展,以及它如何能或应该改变RDBMS的架构以便从更快和更大的硬件中获得好处,也给他们坚持的“完全重写”以注解。
主内存 与70年代相比,大量的主内存变得便宜,因为“OLTP数据库绝大多数是小于1TB并且增长得相当缓慢”他们得出这样的结论:这样的数据库是“现在或在不久的将来能够部署在主内存中的”。Stonebraker等人因此认为OLTP市场在今天或在不久的将来是内存数据库市场。他们因此批评,“目前RDBMS供应商用面向磁盘的解决方案处理主内存问题。总之,摩尔定律的30年已使OLTP应用程序的面向磁盘的体系结构变得过时”。虽然有些关系数据库在内存中运行(例如TimesTen,SolidDB),但这些系统也从System R继承了“包袱”——Stonebraker等人对基于磁盘的恢复日志或动态锁定的称呼,这对这些系统的性能有负面影响。
多线程和资源控制 如前所述,Stonebraker等人认为数据库是主内存市场。现在他们表示,事务通常只会影响到只有少数几个需要读/写的数据集(如TPC-C基准测试中最多200读),如果这个数据是保存在内存中且没有磁盘IO或出现用户中断,将是非常划算的。因此,他们认为在这样的主内存数据库中不需要多线程执行模型,这使得传统关系数据库中相当多的“详细代码”无关紧要,即多线程系统为了最大限度地提高中央处理器和磁盘的使用,资源管理者限制负载以避免使用消耗资源的和多线程的数据结构如并发B树。“这是一个更可靠的系统,一个有更高性能的系统”,他们说。为了避免在这样一个单线程系统中长期运行的事务,要求应用程序将此类事务分解为较小的事务,或——在分析的目的下——在为该任务优化过的数据仓库中运行这类事务。
网格计算和在线扩容 此外,Stonebraker等人概述了70年代共享内存架构、80年代共享磁盘架构、今天和未来的无共享架构的发展,这“通常被称为网格计算或刀片计算”。作为一个结果,Stonebraker等人坚持数据库必须反映这一发展,比如(和最明显的)DBMS网格中多节点间的水平分割。此外,他们主张这种网格的增量水平扩展应该无需由管理员重新加载部分或所有数据,也不停机。他们指出,这些要求显著影响了DBMS的架构,如在不影响运行事务的条件下传输数据的能力,这可能不能很容易地添加到现有的RDBMS中,但可以在新系统的设计中考虑(像比较新的数据库如Vertica)。
高可用性 Stonebraker等人陈述的下一主题是高可用性和故障转移。又一次,他们概述了这一问题的历史发展,从线下保存当灾难发生时再恢复的日志磁带,到将日志磁带挂在远程硬件上并提供灾备服务,到今天很普遍的热备份或多站点解决方案。Stonebraker等人把高可用性和内置的灾难恢复作为一个重要的功能,像他们提到的其它设计问题一样,在这些系统的架构和设计层面考虑。他们特别需要OLTP领域的DBMS具有:
1、保持多个副本一致,需要在地理位置上分散的系统上无缝运行的能力
2、开始在系统底层使用无共享的支持,用于取代SMP架构上多计算机的支持
3、支持无共享架构的最好方式是,用“对等网络环境下的多台机器”以便“负载可以分散在多台机器,机器间的副本可用于容错”。在这样的配置中,普通操作下可以利用所有的机器资源,且故障只会导致退化的操作因为只是可用资源较少而已。相比之下,今天的HA解决方案在普通操作下有一个热备份只利用硬件资源的一部分,因为热备机器只是在等待活跃机器死掉。总之“这些观点说明应完全重新设计RDBMS引擎,使其在新架构下实现点对点的HA”,他们得出这样的结论。
在这样一个Stonebraker等人要求的高可用系统,他们看不到任何重做日志的需要,如在一个站点故障的情况下,恢复活动“可在任一站点的数据上刷新”。因此,只需要一个撤销日志以允许回滚事务。这样的撤销日志不需要储存超过一个事务的周期,因此,“可以是一个主内存数据结构,在事务提交时被丢弃”。正如“在HA的世界,将没有持久化的重做日志,只有一个短暂的撤销日志”,Stonebraker等人发现另一个潜在的机会以去掉从重做日志恢复的复杂代码;但他们也承认,这种恢复逻辑只是转化为“当失败站点恢复运行时从运行中站点得到最新数据的新功能”。
无调整 最后,Stonebraker等人指出当前的RDBMS是在一个“电脑很贵,人很便宜的时代”被设计的。今天恰恰相反,人员成本是一个IT公司的主要支出。他们特别批评说“RDBMS有大量复杂的
性能调整,这是旧时代的过时特性”但仍在使用,因为RDBMS的自动调整辅助“不会带来比一个熟练DBA的更好效果”。为取代提供这类只是为了调整而寻找更好配置的特性,Stonebraker等人需要一个数据库,没有这样的调整只有“自我的一切”(自我恢复,自我维护,自我调节等)。
关于事务,处理和环境的考虑
探讨了自上世纪70年代时设计RDBMS以来IT企业的发展历史,以及这种发展对架构的影响,Stonebraker等人现在转向其他问题,这些会对系统的性能产生不利影响:
- 重做日志持久化必须避免,因为它们是“几乎保证是一个显著的性能瓶颈”。在HA/故障恢复系统上面它们可以完全省略。
- 客户端与数据库之间通过JDBC/ODBC接口的通信是他们提到的下一个引起性能衰退的问题。取代这样的接口,他们“提倡在数据库系统中‘在进程内’运行应用程序逻辑,通过存储过程的形式”,以避免“传统的数据库客户机/服务器模式所隐含的进程间开销”。
- 他们建议进一步消除撤销日志,“不管实际情况,因为它也将是一个重要的瓶颈”。
- 解决的下一个性能瓶颈是允许并发访问的动态锁。动态锁定的成本也应减少或消除。
- 多线程的数据结构导致事务加锁。如果事务的运行时间很短,一个单线程执行模型可以消除这种闭锁与多线程数据结构的开销,只会“在性能上有小损失”。
- 最后,两阶段提交(2PC)事务应尽可能避免,由于该协议造成的网络传输回合将导致性能下降,因为它们“通常以毫秒级的时间先后发生”。
如果这些建议可以被满足,Stonebraker等人随后指出基于OLTP特点的事务和大纲(schema)特性。
事务和大纲特性
除了以上讨论的硬件特性、线程模型、分布式或可用性要求,Stonebraker等人还指出了数据库大纲的特性以及事务属性也显著影响DBMS的性能。关于数据库大纲和事务,他们认为DBMS应该利用以下特点:
树形大纲 是如下的数据库大纲:“每一个表除了一个叫根的节点,都有且只有一个与祖先节点是1-n关系的连接(join)。因此,大纲是一个1-n关系的树”。有此属性的大纲,特别容易在一个网格上的节点之间分布,“这样所有树中的等值连接跨度只有一个单一的站点”。这种模式的根表通常由它的主键分区并移动到网格的其他节点,使每个节点上有根表的分区以及其他表中该根表分区的主键值所对应的数据。
受约束树应用(CTA) 在Stonebraker等人的概念中,CTA是一个有着树形大纲的应用程序,且只执行有下列特性的事务:
1、每一个事务类中的每一个命令都有根节点主键的相等谓词
2、“对一个站点而言,每一个事务类的每一个SQL命令是本地的”
事务类是“相同的SQL语句和程序逻辑的集合,只有每个事务的运行时常量不同”,Stonebraker等人在他们的H-Store原型中预先定义了。他们进一步认为,目前的OLTP应用通常设计为CTA的,或至少可以以这种方式将其分解,并建议系统地应用大纲变换以使应用满足CTA([ SMA+07,页1153 ])。这些努力的好处是“CTA可以非常有效地执行”。
单站点事务 只能在一个节点上执行,而不需要与DBMS网格的其他节点进行通信。如受约束树应用满足这种属性。
一次性应用 完全由“可并行执行且不需要在站点中传输中间结果的事务”构成。此外,一次性应用中的查询从不使用更早的查询结果。这些属性允许DBMS分解事务“到一个单站点执行计划的集合,它可以被分派到适当的站点执行”。一个普通的使应用一次性的技术是在站点间进行垂直分表。
两阶段事务 是指这样的事务:包含第一阶段的读取操作,该操作可以根据它的结果导致事务的取消,和第二阶段的写操作,该操作保证不会造成任何完整性冲突。Stonebraker等人说,很多OLTP事务具有这种属性,因此利用它在他们的H-Store原型中替代撤消日志。
强两阶段事务 在两阶段事务之外,加入了第二阶段所有站点回滚或完成事务的属性。
事务可交换性 由Stonebraker等人定义如下:“来自相同或不同的类的两个并发事务可交换,仅当不管怎么交织时单站点的子执行计划都产生同样的最终数据库状态(假设两个事务都提交)”。
无菌事务类 是“和所有事务类(包括其自身)”可交换的事务类。
H-Store概述
讨论了数据库管理系统设计时应考虑的参数,Stonebraker等人给出H-Store原型,在TPC-C基准中性能明显优于商业数据库。他们的系统草图不在本文中重复(详细信息可以在[ SMA+07页154 ]),但一些属性应当提及:
- H-Store运行在网格上
- 表的每一行在内存中连续存放
- 使用B树索引
- 站点被划分成逻辑站点,每个对应一个CPU核
- 逻辑站点是完全独立的,具有自己的索引、元组存储和他们所在机器的主内存的分区
- 单线程工作,事务不可中断
- 仅允许运行以存储过程实现的预定义事务
- 省去了重做日志并试图尽可能避免写撤消日志;如果撤消日志无法避免它在事务提交时被丢弃
- 如果可能,查询执行计划利用上述讨论的单站点和一次性属性
- 尝试实现无调整和高可用性需求,以及通过“指定水平分区、复制位置、索引字段的全自动物理数据库设计器”实现事务的单站点变换
- 因为H-Store保存每个表的多个副本,需要事务地进行更新。读命令可以去表的任何副本,而更新是针对所有副本
- H-Store利用上述事务和大纲特性进行优化,例如在两阶段事务中省略撤消日志
TPC-C基准
当比较他们的H-Store原型与商业DBMS,Stonebraker等人应用了一些针对基准测试实现的重要技巧。首先,他们在对数据库大纲和它的副本分区时,使用了“分解模式,这样每个站点都有一个源于一个独特的仓库分区记录的子集”的方法。其次,他们讨论如何利用上面讨论的事务特性。如果基准将运行“在一个单核心,单CPU的机器”那么“每一事务类会是单站点的,且每个事务可以运行在一个单线程环境”。在一个“成对HA的站点,所有的事务类都可以当成强两阶段,这意味着所有事物将在这两个站点上成功或中止。因此,在一个单一的成对HA的站点上,ACID特性可以没有任何开销地实现”,通过进一步应用技巧,他们实现“使用[模式分区和复制的]基本策略并用上面描述的技巧增强,所有事物类成为一次性的和强两阶段的。只要我们加一个短延时,ACID特性可以在无任何并发控制开销的情况下实现。”
基于此设置,他们实现了比商业DBMS的性能好82倍。他们还分析了在商业DBMS的性能开销,发现主要是由日志和并发控制引起的。
据说Stonebraker等人仅实施TPC-C基准测试的一部分,且似乎并未调整TPC-C基准测试使之完全适合商业DBMS,就像他们为自己的H-Store原型做的,尽管他们聘请了专业的DBA调整与H-Store对比的DBMS,并尝试优化系统的日志以允许它更好地执行。
结论
鉴于他们的分析,Stonebraker等人得出这样的结论:“我们正走向一个至少有5个(可能更多)专用引擎和‘一刀切’的过时系统死亡的世界”。这适用于关系模型以及它的查询语言SQL。
Stonebraker等人说与“DBMS世界中只包含业务数据处理”的上世纪70年代相反,如今至少有以下市场需要专用DBMS:
1、数据仓库 通常有星形或雪花形模式,如“一个中心事实表与周围的维度表作1-n连接,并可能进一步的与第二层的维度表作1-n连接,等等”。这些数据可以很容易地使用关系模型建模,但Stonebraker等人建议一个实体关系模型对建模和查询来说将更简单、更自然。
2、流处理 这个市场有不同的需求,即“高速处理信息流[和]关联这样的流与存储的数据”。一个SQL的泛化称为StreamSQL,允许使用SQL的FROM语法混合流和关系型数据,引发了一些热情,并被建议当作此领域的标准。Stonebraker等人还提到在流处理中经常需要流数据是扁平的(如一些新闻机构提供的数据流),但也有层次化结构数据的需要。因此,他们“期待流处理厂商更积极地进军层次数据模型”,“他们一定会偏离Ted Codd原则”。
3、文本处理 是一个关系型数据库从未被用到的领域
4、面向自然科学的数据库 因为基础数据结构的原因更可能支持向量而不是表
5、半结构化数据 该领域有用的数据模型仍在讨论。一些建议包括XML大纲(因为其复杂性争论激烈)和RDF
“当关系模型为‘一刀切’的世界而设计,我们设想的各种专业系统可以让我们重新思考什么样的数据模型将更适合他们的特定需求”,Stonebraker等总结道。
关于DBMS查询语言他们反对“一刀切的语言”如SQL,在他们看来,根本没有需要SQL的用例:在OLTP市场即席查询很少或不需要,应用程序以预备语句方式查询,或查询逻辑以存储过程形式被部署到DBMS中。与此相反,其他DBMS市场如数据仓库需要复杂的即席查询能力,这是SQL不能满足的。为此,Stonebraker等人看不到还需要这样的语言。
针对上述市场中的专业DBMS,他们进一步探讨如何将这些语言与编程语言集成,且反对“连接到任何编程语言”的数据子语言如JDBC和ODBC做的。“[这]导致了高开销的接口”。Stonebraker等人因此建议“在编程语言中嵌入数据库的功能”。这样的语言嵌入例子包括,上世纪70年代的Pascal R和Rigel,或今天微软在.NET平台的LINQ方法。关于语言整合这样的能力,他们喜欢他们所谓的“小语种”如Python,Perl,Ruby和PHP,他们“开放源码,可以通过社区改进”,此外“比目前通用的语言(被看作编程语言世界中的一刀切的方案)更容易修改”。他们的H-Store原型中的存储过程计划从C++迁移到Ruby。
2.1.3 主要驱动
在过去的几年中NoSQL潮流吸引了大量的企业和项目。特别运行大型和高频网站的大网络公司或企业已经从关系数据库(通常有一个缓冲层典型地如memcached,参见[ Hof10c ],[ Hof10b ])切换到非关系数据存储。例子包括最初由Facebook开发的Cassandra([ Apa10d ])且今天还被Twitter和Digg使用([ Pop10a ]、[ Eur09 ]),LinkedIn开发和使用的Project Voldemort,存储云服务如NoSQL存储Amazon SimpleDB([ Ama10b ]),以及Ubuntu One,一种基于CouchDB的云存储和同步服务([ Can10c ]、[ Hof10c ])。这些NoSQL数据存储的用户,天然地对他们使用的非关系型解决方案的进一步发展非常感兴趣。然而,最流行的NoSQL数据存储所采用的思想是Google的Bigtable([ CDG+06 ])或Amazon的Dynamo([ DHJ+07 ]);Bigtable启发的NoSQL存储通常被称为列存储(例如HyperTable,HBase),而Dynamo主要影响键/值存储(如Cassandra[ Apa10d ],Redis[ S+10 ],Project Voldemort[ K+10a ])。其他项目追求不同的尝试,如图形数据库形成一类自己的数据存储;和文件存储,这可以被看作是具有附加功能的键/值存储(至少允许键/值对具有不同的、通常是分层的命名空间,提供了“文档”的抽象);后者中至少一个(CouchDB)是现有文档存储如上世纪90年代的Lotus Notes的重新实现,因此没有结合当前的网络技术进行设计(这被CouchDB开发者们批评,他们又从零开始实现他们的文档存储,参见[ Apa10c ]、[ PLL09 ])。综上所述,可以得出的结论是NoSQL潮流的先驱主要是大型网络公司或运行大型网站的公司,如Facebook,Google和Amazon([ Oba09a ]),和在这一领域的其他人通过他们的想法和修改以满足自己的需求。
2.2 批评
2.2.1 商业方面的怀疑
在一篇计算机世界关于三藩的NoSQL见面会的文章,提到一些NoSQL数据库的业务相关的问题。它们中的大多数都是开源软件,被不关心许可证和商业支持问题的开发者欣赏。然而,特别是出问题后没有人可责备的情况会吓到商务人士。即使在Adobe,开发人员使用Terracotta集群替代关系数据库,也只有在让他们的经理看到了系统启动和运行时才能说服他们(参见[ Com09a ])。
2.2.2 过度宣传的NoSQL
一些企业开始谨慎面对NoSQL,因为这一潮流似乎是一个炒作,潜在地缺乏对承诺的履行。这是一种对新技术唤起热情的普遍怀疑态度,如James Bezdek在IEEE通讯中表述如下:
“每一个新的技术开头总是天真愉悦,它的发明者通常淹没在他们自己的想法中;他们最初的同僚体验了大部分狂热的热情。大多数技术过度承诺,往往不是简单地生成资金继续这项工作,资金是科学发展的一个组成部分,除了它,只有最具想象和革命性的想法使它度过胚胎阶段。炒作是过度承诺的自然伴生,大多数技术快速构建以达到炒作的顶点。之后,几乎总是对没有得到充分开发的想法的过激反应,这不可避免地导致崩溃,接下去是一个时期的冷嘲热讽。许多新技术的发展到这一点,然后消失。幸存下来的那些是因为有人发现了一个基本思想的好应用(=真实的用户利益)。”([ For10 ]引用[ Bez93 ])
三藩NoSQL见面会的参与者给出务实的建议:如果公司有一个关系数据库在工作,并且不切换到NoSQL数据库的话什么都不会失去,那就没有任何理由来取代它。即使见面会的组织者,Last.fm的Johan Oskarsson也承认,截至2009年6月Last.fm尚未在生产中使用NoSQL数据库。他还指出NoSQL数据库“目前和主流企业不相关,但一两年后可能会改变”([ Com09a ])。然而,NoSQL见面会的参与者建议如果可能的话看一下NoSQL方案,它是有意义的(例如,在开发新软件)([ Com09a ])。博主Dennis Forbes说在非关系型数据存储的发明者和开发者之间看不见任何过度热情(“他们大部分是聪明的,务实的开发者”),但使用这些技术开发人员却希望“这个潮流解决他们的弱点”。他——一个为金融、保险、电信、电力等行业做传统的关系数据库开发——却说“无疑是很多奇妙的工作发生的NoSQL阵营中,很关注可伸缩性”。另一方面,在他博客的评论中批评说:“争论的是,聚会的本身,被正在或希望建立非常大的网络公司的人劫持了(都希望成为下一个Facebook),该领域的价值观和判断投射到整个数据库产业——其包括一系列使社交媒体的边缘例子也相形见绌的解决方案——这真是讽刺”([ For10 ])。(注:不懂,好像是在骂人)
2.2.3 NoSQL没有什么创新
类似于炒作的论点,对NoSQL的另一种批评是,NoSQL数据库没什么创新因为其他尝试如对象数据库已经存在了几十年。作为这个争论的例子,博主David Intersimone提到Lotus Notes可以归入早期的文档存储,且支持分布和复制而有利于并发控制的性能(除非另有说明,[ Int10 ])。一个特别有意思的例子是,CouchDB的主要开发者,Damien Katz,曾为Lotus Notes工作几年。NoSQL的拥护者认为CouchDB是“Notes的成功”,因为Notes的分布特征并没有利用当前的网络技术,软件本身也不是一个精干的数据存储而是因业务相关的特性而臃肿([ PLL09 ])。
例如Lotus Notes,商业分析或面向流处理的数据存储显示,这类关系数据库的替代品已经存在了很长的时间,博主Dennis Forbes因此批评,“一刀切”的说法只不过是一些人的挡箭牌,因为他们只使用过RDBMS作为处理所有的结构化和非结构化数据存储需求的工具([ For10 ])。
2.2.4 NoSQL代表完全的“没有SQL”
首先,很多NoSQL的主张特别是在博客上的,将这个术语和潮流看作RDBMS的完全否定和这些系统的死亡宣告。“NoSQL”术语通常与Eric Evans联系在一起,虽然他不是第一个用它(见2.1节,如[ Ell09a ])。2009年的一篇博客认为,现在这个词的意思是“不应只有SQL(Not Only SQL)”而不是“没有SQL”([ Eva09b ])。这个词已经被许多博客作者所采纳,因为它强调了数据库中的持久性不意味着只能使用RDBMS而是有替代品存在。博主Nati Shalom评论如下:“我认为我们所看到的是更多的一种现实,现有的SQL数据库方案可能不会很快消失,但同时他们不能解决世界上所有的问题。有趣的是,NoSQL这个词已经变为Not Only SQL,以代表这一思路”([ Sha09a ])。一些博主强调这个词语不精确,如Dare Obasanjo说,“还没有什么产品是‘NoSQL’数据库的确切技术定义,当事实上它不是一个关系数据库”([ Oba09a ])。其他人,如Michael Stonebraker声称,根本和SQL没半毛钱关系,应该叫“NoACID”之类,这是由Dennis Forbes提出的并在他的建议里引用了Stonebraker([ For10 ])。还有一些人如Adam Keys批评术语“NoSQL”只定义了它不代表什么趋势([ Key09 ]):“这个名字的问题是,它只定义了它不是什么。这使得它是对抗性的,它所包含或排除的东西不令人惊讶。我们看到的是,它终结了有价值的数据应该保存在某种关系数据库的假设;终结了SQL和ACID是解决我们问题的唯一工具的假设;终结了主/从模式的活力;终结了在我们的应用程序代码里编织关系模式”。他建议把这种潮流和数据存储归入“后关系型”而不是“NoSQL”:“我们看到关于应如何存储重要数据的思维爆炸;我们审视数据来看是否值得持久化;我们尝试新的语义结构、一致性和并发性。如同后现代主义是反思过去的艺术和建筑的方式,后关系型是软件开发商重新考虑自己方式的一个机会。正如后现代主义并不能否定整个艺术史,后关系型不会终结关系数据库的实用性。”([ Key09 ])。然而,像他博客的读者评论的,这个词并不比“NoSQL”更好,因为它仍只是定义这个潮流和这样的数据库不反映(或更好的:他们所省略)的东西,而不是它们主张什么。
对这个词的刺激和作为关系数据库的忽视部分的第一观念,已经带来了NoSQL支持者们许多发人深省的语句,并造成一些无益的讨论和一些激烈争论(例如[ Dzi10 ]和它的响应[ Sch10 ])。
2.2.5 Stonebraker对NoSQL数据库的关键观点
在他的博文“‘NoSQL’讨论与SQL无关”([Sto09])中,Michael Stonebraker说近期已有大量对NoSQL数据库的讨论。在他的观点里美国的NoSQL研讨背后的驱动力是文档存储和键/值存储的倡导者,在他眼中它们提供“低层、一次一条记录的DBMS接口,以取代SQL”。Stonebraker看到两个走向非关系数据存储的原因——灵活性和性能。
灵活性的争论 Stonebraker未进一步研究,但它包含下列观点:可能有这样的数据,其不符合刚性的关系模型,且和RDBMS的结构紧密绑定。对于这种数据更灵活是必要的。
性能的争论 Stonebraker描述如下:起先使用MySQL存储数据但性能随时间下降。这导致了以下选择:要么在应用程序中对多个站点上的数据碎片/分区导致“管理分布式数据的严重问题”;或从MySQL走向商业RDBMS可引起大的许可费;或甚至完全放弃RDBMS。
Stonebraker在他的博客中研究了后者。他针对“NoSQL数据库最通常考虑的负载:更新和查询密集型的OLTP负载,不是查询密集型的数据仓库负载”,或专业的负载如文档知识库。
Stonebraker看到两个选项提高OLTP事务的性能:
1、“无共享处理环境”上的自动分片实现的水平缩放。在这种情况下,性能因增加新的节点得到改善。在他看来,在过去的十年里写的RDBMS提供了“无共享的架构”,“没有人应该运行不提供这个功能的DBMS”。
2、单点OLTP性能的改进
Stonebraker集中在第二项,分析降低单点OLTP事务性能开销的来源;他的博客文章的标题表明,这些都和查询语言(SQL)无关。他说,只有一小部分的事务消耗是由有用的工作引起的,并看到五个性能开销的来源,单节点性能应优化应据此进行:
通信 应用和DBMS间通过ODBC或JDBC进行的通信。这被认为是OLTP事务开销的主要来源,通常如下描述:“基本上所有性能敏感的应用程序使用存储过程接口来运行DBMS内的应用程序逻辑,避免了应用与DBMS之间来回通信的沉重的开销”。为了减少通信开销的另一个选择是使用一个嵌入式DBMS,指的是应用程序和DBMS在同一地址空间中运行;因为强耦合,安全性和访问控制问题对“安全是一个大问题的主流OLTP”没有可行的替代,Stonebrakers认为。
日志 每个事务除修改关系型数据外由DBMS负责记录日志。由于日志文件被保存到磁盘以确保持久性,日志是昂贵的且会降低事务性能。
加锁 数据集的加锁操作会导致开销,因为加锁表的写操作只能在事务修改操作之前或之后才能发生。
闩锁 因为RDBMS中共享的数据结构(如B树、锁表、资源表)进一步增加事务开销。这些数据结构都是由多个线程访问短期锁(称为闩锁)通常用于提供并行的但谨慎的访问。
缓存管理 当讨论事务开销时缓存管理也有其责任。因传统RDBMS中的数据以固定页的方式组织,必须管理内存中的磁盘页面缓存(通过缓冲池完成),并解决数据库条目写到磁盘页(和返回)以及识别字段边界的问题。
如前所述,根据Stonebraker,通信是开销的主要来源,并远超过其他的项目(从这个调查:[ HAMS08 ]),其他项目近似相等地增加总事务成本。除了避免应用程序和数据库之间的通信,其他四个性能开销的来源必须消除,以大大提高单节点性能。
现在,无论是否是关系型的数据存储通常都有特定的主题,NoSQL数据库也需要找出上述性能开销的组成部分。在这样的背景下,Stonebraker提出下面的例子:
- 在多个站点之间数据分布且无共享的方法在关系型以及非关系型数据存储中都提供了。“显然,一个精心设计的多站点系统,无论是否基于SQL或其他,都比单站点系统更具可扩展性”,据Stonebraker说。
- 许多NoSQL数据库是基于磁盘的,实现一个缓冲池和多线程。当提供这些特性和性能时,四个性能开销来源中的两个仍然存在(锁定,缓存管理),不能被消除。
- 很多智能事务的NoSQL数据存储只提供带BASE属性(见第3章)的单记录事务。与关系型DBMS相反,ACID属性为性能而牺牲。
于是Stonebraker总结他的观点如下:“然而,一个NoSQL、基于磁盘、非ACID、多线程系统的单节点性能被限制为比设计良好的存储过程SQL的OLTP引擎略快。 本质上,ACID事务因适度的性能提升而被抛弃,且这种性能提升与SQL无关”。在他的观点中,加速DBMS的实际任务集中于消除加锁、闩锁、日志和缓冲区管理,以及支持存储过程从高级语言(如SQL)编译为低级语言。这样的系统的样子在论文“架构时代的终结:是完全重写的时候了”([SMA+07])中被阐述并已经在上文讨论了。
Stonebraker也不指望 SQL数据存储的死,而是说:“我完全期待高速度的、开源的SQL引擎在不久的将来提供自动分片。此外,他们将继续提供ACID事务以提高程序员的工作效率,降低维护成本,以及由SQL支持的更好的数据独立性”。因此“高性能不需要抛弃SQL或ACID事务”。这也“取决于消除由传统的ACID事务、多线程管理、磁盘管理带来的开销”。消除这些开销的来源“在SQL上下文或其他上下文环境中都是可能的”,Stonebraker总结。
2.2.6 运维和操作人员的需求
Schmidt在他的博客“NoSQL”的黑暗面([ Sch09 ])中认为,NoSQL的辩论被开发者的观点主宰,其通常重复着开发人员喜欢的特性和能力(如性能、用途、无模式、好的API),而操作人员和系统管理员的需求通常被遗忘在他的视线中。他报道了一些公司遇到困难特别是在以下领域:
即席数据修复 要允许对即席数据修复,首先必须有某种查询和操作语言。其次,在分布式数据库(如Project Voldemort和Cassandra)中更难以修复数据,与在一个节点上运行或有专门分片的数据存储相比。
即席数据查询 与数据修复相似,当遇到即席查询时针对特定数据存储的查询和操作是必须的,和查询集中式存储相比查询分布式数据存储更难。Schmidt指出,对一些报表任务来说MapReduce方法([ DG04 ])是合适的,但不是对每一个即席查询。此外,他看到的是文化而不是技术问题,客户已经被培训和“上瘾”使用即席查询,因而不喜欢这些手段的缺失。针对详尽报表的需求,Schmidt建议使用镜像了线上库的关系型数据库,而线上库可能因为性能和可扩展性要求而使用NoSQL存储。
数据导出 Schmidt指出,这方面NoSQL数据库之间有巨大差异。一些提供了有用的API来访问所有的数据,另一些中则不存在。他也指出,从非分布式NoSQL存储像CouchDB,MongoDB或Tokyo Tyant中导出数据,要比从分布式的如Project Voldemort或Cassandra中导出数据更容易。
Schmidt的观点在讨论“你的NoSQL指南”([ Ake09 ])中被幽默和广泛地重复,特别是恶搞了NoSQL支持者的用MapReduce风格处理每个查询需求的论点。
2.2.7 性能 vs. 可扩展性
BJ Clark介绍了一个在各种NoSQL数据库和MySQL间的性能和可扩展性实验,发表在他的博客“NoSQL:如果它是那么容易”。首先,他定义可扩展性为“在保持比例的前提下改变大小,在计算机学科中这通常意味着增加吞吐量。”博主Dennis Forbes同意这一可扩展性的概念,“务实地衡量一个解决方案的能力,其以可实现的方式增长到一个最高的现实水平,同时保持可接受的服务水平”([ For10 ])。BJ Clark继续说:“扩展不是:性能。在现实中,扩展和变快没有什么关系。它只与大小有关。现在,扩展和性能典型地如此联系到一起,如果什么是高效的,它实际上可能不需要扩展。”([ Cla09 ])。
对于关系数据库Clark指出:“RDBMS的问题不是他们不扩展,是他们非常难以规模。分片是最明显的扩展方式,但分片多个能访问任意列的表会很快使人崩溃。”博主Dennis Forbes同意他,“有一些老派的关系数据库确实有扩展性问题”([ For10 ]),但使用如Adam Wiggins的技术还是有可能让它们扩展的([ Wig09 ])。
除了关系数据库的分片和典型错误的回避(如死板的规格化和不良索引导致的昂贵的连接),Forbes认为垂直缩放仍然是一种选择,它很容易且计算上有效,且能远远领先于“成队的强力核心,数百GB的内存,在成堆的SSD组成的SAN阵列上操作”。缺点是,Forbes也承认垂直缩放相对昂贵。但Forbes也主张关系数据库通过数据分区和将每台机器加入失败恢复集群实现的水平缩放,以达到冗余和可用性。考虑到约束很少且钱通常不是问题的大公司的部署情况,他以自己的经验说,“这种扩展存在于几乎所有的银行、交易系统、能源平台、零售系统等等。要声称SQL系统不能扩展,是对这样明显的证据的蔑视,无视所有的理由”([ For10 ])。Forbes主张使用自己的服务器,因为他看到一些云计算环境的人为限制,如单一实例的Amazon EC2的IO限制和相对高费用;他认为“这些金融和人为限制解释了对允许你螺旋上升的技术的强烈兴趣”([ For10 ])。
BJ Clark在他的博客上发表对一些NoSQL数据存储的评价,该评价关注于自动可扩展性(例如通过自动分片),因为他需要更新数百万个对象(他称他们为主要对象)与其他对象(他称他们为辅助对象)是1:1或1:N的依赖关系;辅助对象大多是在表的结尾处插入。
他的评价可以概括如下:
- 键/值对存储Tokyo Tyant/Cabinet和Redis不提供自动水平伸缩的特性。如果添加机器——类似memcached——必须让应用知道,然后在数据库服务器群中对数据库条目(重)哈希,以利用额外的资源。另一方面他指出,Tokyo Tyant/Cabinet和Redis的表现非常好,横向扩展的需要不会很早出现。
- 分布式键/值存储Project Voldemort自动地利用新加入集群的服务器并提供故障容错。鉴于它专注于分片和故障容错且有一个可插拔的存储架构,Tokyo Tyant/Cabinet或Redis可以作为Voldemort的存储后端。如果这些系统需要扩展的话,这也是一个可能的迁移路径。
- 文档数据库MongoDB表现出良好的性能特点,但在评价时没有自动缩放能力,因为它没有提供自动分片(在2010年8月的1.6版中已经改变,参见[ Mon10 ]和[ MHC+10b ])。
- 对于列数据库Cassandra,Clark认为它是“绝对应该,且可能在Facebook,是通过简单地添加另一台机器来扩展的(节点间互相挂钩使用Gossip协议),但OSS版本不支持一些关键的东西,像一起释放一台机器“。这一结论反映了Cassandra评价时的发展状况。
- Amazon的键/值对存储S3扩展良好,但据Clark说,它不如其他候选者那样高性能。
- MySQL,相比较而言,并不提供自动横向扩展如自动分片,但Clark指出,对于大多数应用(甚至是Web应用如Friendfeed,参见[ Tay09 ])MySQL足够快,并且是“熟悉的、无处不在的”。与Tokyo Tyant/Cabinet和Redis相比,Clark认为“它可以做Tokyo Tyant和Redis可以做的一切,且真的是没有那么慢。事实上,对于某些数据集,我见过MySQL比Tokyo Tyant执行地快得多”和“对MySQL分片与Tokyo Tyant和Redis一样容易甚至更容易,很难说他们可以在许多其他问题上赢得胜利。”
在上述评价中所提到的系统将在本文中更详细地讨论。此外必须提到的是,评估发生在2009的夏天(博客是8月发表),因此,结果反映了被评价系统在那个时候的发展状态。
Clark总结了他的研究结果,在他看来RDBMS不比“其它很多东西”更难扩展,NoSQL数据库提供的仅有的一些手段有是自动的、水平可扩展性、允许不需要操作员交互下添加机器。因此,甚至可以认为“扩展MySQL(通过MySQL Proxy来分片)和为这些NoSQL数据库做分片同样容易。”因此他没有宣布RDBMS早早死亡,提醒道MySQL仍然是在大网站如Facebook,Wikipedia和FriendFeed中使用。他建议新的应用程序使用最适合工作的工具,反映了非关系型数据库——就像关系型的一样——没有“一刀切”的解决方案:
“如果我需要报表,我不会使用任何NoSQL。如果我需要缓存,我很可能会使用Tokyo Tyant。如果我需要ACID特性,我不会使用NoSQL。如果我需要一吨值对,我会使用Redis。如果我需要事务,我会使用Postgres。如果我有一吨单一类型的文件,我可能会使用Mongo。如果我需要每天写10亿个对象,我可能会使用Voldemort。如果我需要全文搜索,我可能会使用Solr。如果我需要易变数据的全文搜索,我可能会使用Sphinx。”
2.2.8 不是所有RDBMS表现得像MySQL
NoSQL的辩论中经常发现的争议是RDBMS很难良好扩展且很难分片。这通常是通过MySQL的例子指出。此外,NoSQL数据库有时被看作MySQL加memcached方案的继任者(例如[ Hof10c ]),后者将负载从数据库带走以减少和延缓分布式的需求。关于这些典型争论博主Dennis Forbes提醒,不容易区分一般的RDBMS和MySQL,其它数据库可能更容易或更好地扩展:“MySQL不是RDBMS世界的先锋。它在高负载网站下的问题和关注很少与其他数据库系统相关”([ For10 ])。
2.2.9 批评的误解
NoSQL倡导者Ben Scofield回答了一些上面提到的批评,他认为是被误解了。他在NoSQL争论中表达的一些精辟论点回答了这些批评([ Sco09 ]):
“NoSQL只是可扩展性和/或性能。” Scofield认为,这对那些“传统主义者”(他这样称呼他们)可能是一个有吸引力的观点,认为只要让RDBMS更快和更具可扩展性就能使NoSQL数据存储过时。他声称“NoSQL除了性能和扩展外还有更多”,例如“NoSQL数据库通常为业务域建模提供更好的基础”。
“NoSQL只是文档数据库,或键值存储,或……” Scofield指出,许多NoSQL文章只介绍面向文件的数据库或键值存储,有时提到列存储。他指出“对特定情况下的每一个解决方案都可以提出好的讨论,但上述那些只是讨论某一特定类型的存储引擎。”Scofield因此批评,将讨论范围缩小到只有一类NoSQL数据库,会使得传统主义者很容易地否定整个潮流或全套不同的NoSQL方法。
“我在NoSQL能做的在关系数据库中一样能。” 考虑到Friendfeed使用MySQL的频繁争论([ Tay09 ]),Scofield指出,尽管微调一个关系型数据库是可能的,但这对所有类型的数据没有意义。“不同的应用适合不同的事情;关系数据库对关系数据是伟大的,但对非关系数据为什么要使用他们?”他问道。
“NoSQL是一个关系数据库的广泛排斥。” 前一段时间这种说法在NoSQL社区经常被听到,后来成了不常见的,Scofield赞赏:“看来我们正在走向一个多元化的方法来储存我们的数据,这是一件好事。我已经为这种做法提出了’多语言持久化’(虽然我没有杜撰一个术语),但我也喜欢如Ezra Zygmuntowicz的’LessSQL'作为标签。”
2.3 NoSQL数据库的分类和比较
在过去的几年里,各种NoSQL数据库主要由从业人员和网络公司开发,以满足他们对可扩展性的性能、维护和功能集的具体需求。已经透露的是这些数据库中的一些借鉴了Amazon的Dynamo([DHJ+07 ])或Google的Bigtable([ CDG+06 ])或两者的思想。其他一些移植了针对现代网络技术开发的现有数据库的思想如CouchDB。还有一些人追求完全不同的方案如Neo4j或HypergraphDB。
因为各种不同的方法、重叠的非功能性需求、不同的功能集,可能很难获得和维护一个非关系型数据库情况的概述。所以有各种不同的方法对NoSQL数据库分门别类,每种都有不同的类别和子类别。这里介绍一些分类方法,应当用哪一个对NoSQL数据存储分类将在后续的章节介绍。
2.3.1 按数据模型的分类法
关于NoSQL存储伸缩性的分类法,作者Todd Hoff引用了一个Stephen Yen在他的博文“NoSQL分类法的赞同”中的演示文稿([ Hof09c ])。在演示文稿“NoSQL是一个没有马的马车”([ Yen09 ])中Yen建议的分类法可以在表2.1中找到。
词汇 |
符合的数据库 |
Key-Value-Cache
|
Memcached
Repcached
Coherence
Infinispan
EXtreme Scale
Jboss Cache
Velocity
Terracoqa
|
Key-Value-Store
|
keyspace
Flare
Schema Free
RAMCloud
|
Eventually-Consistent Key-Value-
Store
|
Dynamo
Voldemort
Dynomite
SubRecord
Mo8onDb
Dovetaildb
|
Ordered-Key-Value-Store
|
Tokyo Tyrant
Lightcloud
NMDB
Luxio
MemcacheDB
Actord
|
Data-Structures Server
|
Redis
|
Tuple Store
|
Gigaspaces
Coord
Apache River
|
Object Database
|
ZopeDB
DB4O
Shoal
|
Document Store
|
CouchDB
Mongo
Jackrabbit
XML Databases
ThruDB
CloudKit
Perservere
Riak Basho
Scalaris
|
Wide Columnar Store
|
Bigtable
Hbase
Cassandra
Hypertable
KAI
OpenNeptune
Qbase
KDI
|
表2.1:分类——Stephen Yen的NoSQL分类法([Yen09])
一个类似的分类法,比上面的分类法更粗粒度和易理解,可以在文章“云数据库”([ Nor09 ])中找到。表2.2总结了他的数据仓库分类,另外包括一些只在云计算环境中可用的数据存储。
归类 |
符合的数据库
|
Distributed Hash Table, Key-Value Data Stores
|
memcached
MemcacheDB
Project Voldemort
Scalaris
Tokyo Cabinet
|
Entity-Attribute-Value Datastores
|
Amazon SimpleDB
Google AppEngine datastore
Microsoft SQL Data Services
Google Bigtable
Hadoop
HyperTable
HBase
|
Amazon Platform
|
Amazon SimpleDB
|
Document Stores, Column Stores
|
Sybase IQ
Vertica Analytic Database
Apache CouchDB
|
表2.2:分类——Ken North的归类([Nor09])
与上面的分类法类似,Rick Cattel主要按数据模型将不同的NoSQL数据库分类,见表2.3。
归类 |
符合的数据库 |
Key-value Stores
|
Redis
Scalaris
Tokyo Tyrant
Voldemort
Riak
|
Document Stores
|
SimpleDB
CouchDB
MongoDB
Terrastore
|
Extensible Record Stores
|
Bigtable
HBase
HyperTable
Cassandra
|
表2.3:分类——Rick Cattel的归类([Cat10])
2.3.2 Ben Scofield的归类
博主Alex Popescu总结了由Ben Scofield给出的一份演示文稿,该文稿给出了NoSQL数据库一个通用的带分类法的介绍,以及不同NoSQL数据库的Ruby例子([ Sco10 ])。这一分类法实际上是一个简短的NoSQL数据库非功能类型(“称为ities”)的比较,外加功能覆盖率的评分。Popescu总结了Scofield的思想,如表2.4。
|
性能
|
扩展性
|
灵活性
|
复杂性
|
功能性
|
Key-Value Stores
|
high
|
high
|
high
|
none
|
variable (none)
|
Column stores
|
high
|
high
|
moderate
|
low
|
minimal
|
Document stores
|
high
|
variable (high)
|
high
|
low
|
variable (low)
|
Graph databases
|
variable
|
variable
|
high
|
high
|
graph theory
|
Relational databases
|
variable
|
variable
|
low
|
moderate
|
relational algebra
|
表2.4:分类——Scofield和Popescu的分类法及比较([Pop10b], [Sco10])
2.3.3 可扩展性、数据和查询模型、持久化设计的比较
在博客“NoSQL生态系统”中Jonathan Ellis讨论了NoSQL数据存储的三个重要方面:
1、可扩展性
2、数据和查询模型
3、持久化设计
可扩展性
Ellis认为,通过数据副本和这些副本上的负载分布很容易实现读操作的可扩展。因此,他只研究
真正分布式和提供自动数据分区的数据库的写操作扩展。当数据大小超过单一机器的能力时,
如果不愿意手动分区的话后者系统似乎是他唯一的选择(这不是一个好主意,根据[ Oba09b ])。对于相关的提供自动分片的分布式系统,Ellis看到两个重要特点:
- 支持多数据中心
- 添加机器到现有群集的可能性,对使用该群集的应用程序透明
根据这些特点Ellis比较了一些实现这些要求的真分布式和自动分片的NoSQL数据库(参见表2.5)。
数据存储
|
在线添加机器
|
多数据中心支持
|
Cassandra
|
X
|
X
|
HBase
|
X
|
|
Riak
|
X
|
|
Scalaris
|
X
|
|
Voldemort
|
|
Some code required
|
表2.5:分类——扩展性对比([Ell09a])
以下的NoSQL存储已被排除在这种比较外,因为他们在分布式上不满足Ellis的要求(在2009年11月他发布博客的时间):CouchDB,MongoDB,Neo4j,Redis和Tokyo Cabinet。然而据他说,这些系统可以作为一个分布式系统的持久层使用。文档数据库MongoDB和CouchDB支持有限的自动分片,在他调查的时间(MongoDB开箱,CouchDB通过划分/聚类框架Lounge)。关于Tokyo Cabinet,Ellis说它可以用作Project Voldemort的存储后端。
数据和查询模型
Ellis研究的第二个领域是数据模型和不同的NoSQL存储提供的查询API。表2.6显示了他的调查结果,指出了各种数据模型和查询APIs的巨大差别。
数据存储
|
数据模型
|
查询API
|
Cassandra
|
Columnfamily
|
Thrift
|
CouchDB
|
Document
|
map/reduce views
|
HBase
|
Columnfamily
|
Thrift, REST
|
MongoDB
|
Document
|
Cursor
|
Neo4j
|
Graph
|
Graph
|
Redis
|
Collection
|
Collection
|
Riak
|
Document
|
Nested hashes
|
Scalaris
|
Key/value
|
get/put
|
Tokyo Cabinet
|
Key/value
|
get/put
|
Voldemort
|
Key/value
|
get/put
|
表2.6:分类——数据模型和查询API的比较([Ell09a])
Ellis对这些系统的数据模型和查询API进行了以下评论:
- Columnfamily模型,由Cassandra和HBase实现,是由Google的Bigtable论文第二节的相关段落得到启发([ CDG+06,2页])。Cassandra与HBase相反省略了历史版本,引入了超列的进一步概念。在Cassandra和HBase里列是稀疏的,这意味着他们可能有不同数量的单元,且列不必预先定义。
- 键/值模型是最容易实现的,但可能是低效的,如果一个人只对请求或更新与某个键相关的部分值感兴趣。此外,在键/值存储上很难构建复杂的数据结构(正如Ellis在另一篇博客中描述的,参见[ Ell09b ])。
- Ellis将文档数据库看做是键/值存储的下一步,因为它们允许嵌套的值。他们允许比键/值存储更效率地查询数据结构,因为当他们请求一个键时不需要返回整个BLOB值。
- 图数据库Neo4j具有独特的数据模型,因对象及其关系被作为一个图的节点和边来建模和持久化。适合此模型的查询可能比其它数据存储上相同的查询快三个数量级(由Emil Eifrem,Neo4j背后公司的首席执行官,参见[ Eif09 ])。
- Scalaris在所评价的键/值存储中是独一无二的,因为它允许多个键上的分布式事务。
持久化设计
Ellis对比他所选的NoSQL数据存储的第三方面,是他们储存数据的方式(见表2.7)。
数据存储
|
持久化设计
|
Cassandra
|
Memtable / SSTable
|
CouchDB
|
Append-only B-tree
|
HBase
|
Memtable / SSTable on HDFS
|
MongoDB
|
B-tree
|
Neo4j
|
On-disk linked lists
|
Redis
|
In-memory with background snapshots
|
Riak
|
?
|
Scalaris
|
In-memory only
|
Tokyo Cabinet
|
Hash or B-tree
|
Voldemort
|
Pluggable (primarily BDB MySQL)
|
表2.7:分类——持久化设计的比较([Ell09a])
Ellis认为持久化设计对估计何种负载下这些数据库会表现得好是特别重要的:
内存数据库非常快(如Redis可在单机达到每秒100000次操作),但数据的大小天生的受RAM大小限制。另一个缺点是耐久性可能成为一个问题,因为潜在地大量数据可能在两次磁盘写中间丢失(例如由于服务器崩溃或掉电)。Scalaris通过复制解决这个问题——但它不支持多个数据中心——掉电的威胁依然存在。
内存表和SSTables以如下方式工作:在写入一个只能追加的提交日志以确保耐久性后,写操作在内存中缓存(在内存表内)。经过一定数量的写,内存表作为一个整体被刷新到磁盘(这时被称为SSTable;这些想法都来自Google的Bigtable论文,参见[ CDG+06,5.3和5.4节 ])。这一持久化策略具有与内存数据库相媲美的性能特点(因为——与基于磁盘的策略相比——由于追加日志和将整个内存表写回磁盘减小了寻道时间),且避免了纯内存数据库的耐久性问题。
B树因为能提供一个强大的索引支持已在数据库中使用。他们在磁盘上的性能特性不是很正面,原因是读写操作所需的大量寻道。文档数据库CouchDB内部使用B树,但通过只追加到B树试图避免寻道的开销,这意味着一次只能有一个写操作的缺点,因为这种情况下并发读B树的不同段是不允许的。
基于用户需要的分类法
Todd Hoff([Hof09b])引用博主James Hamilton提供了一种不同的划分NoSQL数据库的方法([Ham09]),根据用户需求划分数据库:
特性第一 这一类的数据库提供了一个(大)量的高层次的特性,使
程序员的工作更容易。不足之处是他们很难扩展。例子包括:Oracle,Microsoft SQL Server,IBM DB2,MySQL,PostgreSQL,Amazon RDS。
扩展第一 这种类型的数据库从一开始就需要扩展。不足之处是,他们缺乏特定的特性且把责任还给程序员。例子包括:Project Voldemort,Ringo,Amazon SimpleDB,Kai,Dynamite,Yahoo PNUTS,ThruDB,Hypertable,CouchDB,Cassandra,MemcacheDB。
简单结构存储 这个类包含键/值对存储,强调存储和检索任意结构的集合。根据Hamilton他们的缺点是“通常不具有其他系统的功能或可扩展性”。例子包括:文件系统,Cassandra,BerkelyDB,Amazon SimpleDB。
特定目的优化的存储 这些数据库被设计和建造以擅长做一件事,如数据仓库或流处理。这样的数据库的例子有:StreamBase,Vertica,VoltDB,Aster Data,Netezza,Greenplum。
Hamilton和Hoff认为,这种分类法对将一类数据库和特定用例匹配是有用的。虽然这种分类是不完整的,如不包含图数据库,且如何符合上述四类是不明确的。此外,重要的是要注意,一些
数据库可以在不同的类中找到(Cassandra,SimpleDB),因此这样的分类不提供一个确定的区别使每个数据库只归入一个类(这——在作者看来——在NoSQL数据库领域即使不是不可能至少也很困难)。
2.3.4 本文的分类法
考虑基本概念和下一章中的NoSQL数据库技术后,接下去的章节将研究各种类别的非关系型数据存储,并审视特定的产品。这些产品以他们的数据结构来分类,追随上面所提到的Yen,North和Cattell的分类法(参见2.3.1),这也被本文的其他多数资料来源共享。在这篇文章中使用的分类是:键/值存储、文档数据库和面向列的数据库。