探索云和
NoSQL 数据库设计基础
在提及数据库扩展性时,人们就会想到相对低成本的、高性能的 NoSQL(不仅是
SQL)数据库,它包含一些非常有用的特性:水平可伸缩性、对弱一致性模型的支持、更灵活的模式和数据模型,以及对简单的低级别查询接口的支持。本文将探讨
NoSQL 数据库(包括 NoSQL 系统 HBase、MongoDB 和 SimpleDB)的特性和功能概述,还将介绍云和
NoSQL 数据库的设计基础。
就创建、交流、访问内容、共享信息和购买产品而论,快速扩展的新一代基于
Internet 的服务(比如电子邮件、博客、社交媒体、搜索和电子商务)实际上重新定义了 Web 用户的行为和趋势。由于这些系统的数量的不断增多,IT
专业人士正见证着所生成数据和所消耗数据的规模的扩大,不断增长的伸缩性需求和新功能需求为传统关系型数据库管理系统
(RDBMS) 带来了新的挑战。
我们先来了解一下低成本高性能 NoSQL 数据库软件。NoSQL 数据库软件的主要特性包括:
1、能够水平扩展数据。
2、支持较弱的一致性模型( 原子性、一致性、隔离性和持久性属性之一,确保数据库事务得到可靠处理)。
3、能够使用灵活模式和数据模型。
4、支持简单的低级查询接口。
本文将探讨数据库系统的最新进展,以支持 Web 规模数据管理。本文概述了各个
NoSQL 系统备用方案的主要代表(HBase、MongoDB 和 SimpleDB)的特性和功能,以及它们对不同种类
Web 应用程序的支持情况。
云数据库设计基础
云计算如何改变人们与数据的交互方式?
所有人都可以轻松地处理数据事务
Web 技术的最新进展使得所有用户都可以轻松地提供和使用所有格式的内容。例如:
1、构建一个个人网站(比如,Google Sites)。
2、创建一个博客(使用 WordPress、Blogger 和 LiveJournal).
3、在网络社区进行交互(使用 Facebook、Twitter、LinkedIn
等等)。
这些渠道已成为商品和工具,使更多的人能够更多元化地轻松创建、使用和传输更多数据,比如,采用博客、微博、社交网络交互、视频、音频和照片的形式,数据可以是结构化的,也可是非结构化的。
应用程序变成了分布式的、可伸缩的服务
很明显,系统和工具制造商的下一个目标是以分布式的、可扩展的、可广泛访问的
Web 服务的形式帮助实现每个应用程序。(例如,请查看 Facebook、Flickr、YouTube、Zoho
和 LinkedIn 上的这些服务)。
满足这一标准的应用程序是数据密集型的、高度交互的应用程序。例如,在撰写本文时,Facebook
宣称每个月有 8 亿活跃用户(现在可能有 1 亿)。每个用户的朋友圈大约有 130 个人。此外,约有 9
亿个注册用户交互对象,比如页面、组、活动或社区主页面。
其他规模较小的社交网络,比如 LinkedIn,主要针对专业人士,注册用户也达到了
2 亿。Twitter 宣称每月有 1 亿注册用户。假设存在这样一种情况:终极目标是使那些想要实现这个高级伸缩性和可用性的人能够轻松地实现其目标,那么如何以最少工作和资源来实现是一个挑战。
云模型简化服务部署
云计算技术是一种相对较新的模型,可托管软件应用程序(尽管云是如此完整,以至于到目前为止,很难从将它从整个数据事务系统的其余部分中分割出来)。云模型简化了耗时的硬件准备、硬件购买和软件部署过程,彻底改变了计算资源、服务商业化以及交付客户的模式。特别是,它将这类基础架构的位置转移到网上,减少了硬件和软件资源管理的相关成本。
这意味着云使得期望计算成为实用工具的长久以来的梦想得以实现,规模经济理论有助于实现有效地降低计算基础架构成本的梦想。
云计算具有许多软件应用程序部署优势,比如按使用量付费成本模型、缩短了上市时间,以及(几乎)无限资源和无限可伸缩性方面的洞察。
新发行版模型意味着更多的新数据和数据类型
实际上,云计算模型的优势为新应用程序部署开辟了新的途径,从经济学角度讲,这些应用程序在传统企业基础架构设置中不具有可行性。因此,云成为了一个日益流行的可在各个领域(比如零售、金融、新闻和社交网络)托管软件应用程序的平台。应用程序数量的增加导致所生成数据和所消耗数据的规模的扩大。这就是促使这些应用程序的云托管数据库系统成为应用程序软件栈中的关键组件的原因。
云模型导致了云数据库模型的出现
有很多系统和方法都可以用来应对在云计算环境中托管数据所带来的挑战。事实上,有三个主要技术常用于在云平台上部署软件应用程序的数据库层:
1、虚拟化数据库服务器
2、数据库即服务平台
3、NoSQL 存储系统
虚拟化的角色
虚拟化是云计算技术的关键组成部分;它允许您将物理硬件详细信息提取出来,并为高级别应用程序提供虚拟资源。
虚拟服务器通常被称为虚拟机 (VM)。VM 允许将应用程序从底层硬件和其他
VM 中隔离出来。理想情况下,每个 VM 既不知道同一物理机上运行的其他 VM 的存在,也不受它们的影响。
一般而言,资源虚拟化技术在应用程序和应用程序使用的资源之间添加了一个灵活的可编程的软件层。定义虚拟化数据库服务器的概念充分利用了这些优势,特别是当软件应用程序的现有数据库层可直接导入公共云中的虚拟机时,这些软件应用程序是专为在传统数据中心使用而设计的。
这样一个迁移过程通常只需要在部署的应用程序代码或基础架构中进行微小改变。和其他软件组件一样,在该虚拟化数据库方法中,数据库服务器被迁移到虚拟机中运行。为每个数据库副本部署一个
VM 会带来性能开销,这类开销估计小于 10%。实际上,虚拟化数据库服务器方法的一个主要优势是,应用程序可根据需要完全动态控制数据库层(数据库服务器)物理资源的分配和配置。
因此,软件应用程序可以完全利用云环境的弹性特征来实现其定义和定制的可伸缩性,并降低成本;然而,实现这些目标需要提供一个接纳控制组件
(admission control component),负责监控系统状态并根据已定义的应用程序需求和策略采取相应的措施(例如,分配更多/更少的计算资源)。该接纳控制组件最主要的一个职责就是决定何时增加或减少分配给软件应用程序的数据库服务器数量。
数据中心的多租户角色
由于超量配置以及典型企业应用程序资源需求随时间而不断发生变化 ,往往导致数据中心未得到充分利用。多租户
是托管服务的一个优化机制,在该机制中,多个用户可以合并到同一个操作系统上(一个软件实例运行在一个服务器上,但为多个客户端提供服务),因此,规模经济原理有助于有效降低计算基础架构的成本。
特别是,多租户支持资源共享,通过减少配置每个租户的需求来提高利用率,实现了负载最大化,使得多组合这个极具吸引力的机制可用于:
云供应商(能够用更少的机器服务于更多的用户)和云服务客户(不需要支付租赁一个完整服务器的费用)。
数据库即服务 是这样一个概念,第三方服务器供应商托管一个关系型数据库作为一种服务。这类服务缓解了用户购买昂贵硬件和软件、处理软件升级以及雇佣专业人员进行管理和维护的需求。
实践中,如果现有软件应用程序的底层 RDBMS 与提供的服务相兼容,那么将任何软件应用程序的数据库层迁移
到关系数据库服务中预计不会太困难。但是服务供应商可能因为各种原因带来一些限制或约束(比如,托管数据库的最大容量,可行并发连接的最大数量)。此外,软件应用程序可能在控制其应用程序的分配资源方面不够灵活(可能动态分配过多的资源来处理不断增长的工作负载,或动态减少分配资源以降低操作成本)。整个资源管理和分配过程由供应商控制,对于数据库层来说,这需要一个准确的分配计算资源计划,并通过利用云计算环境的弹性和可伸缩性来限制用户应用程序功能,从而最大限度地增加其获益。
为什么关系数据库不是最佳选择
在过去数十年中,关系数据库管理系统通常被认为是一个 “放之四海而皆准的数据库持久化和检索解决方案”。经过了广泛的研究和开发,关系数据库已经相当成熟,在各个商业领域都成功地开拓了巨大的市场并创建了许多解决方案。
不断增长的可伸缩性和新应用程序 需求为传统 RDBMS 带来了新的挑战,包括某些大规模网络应用程序对这个
“万能” 方法的不满。这个问题的解决方法是新一代的低成本、高性能数据库软件,专门设计用于挑战关系数据库管理系统优势。NoSQL
运动的一个注意原因是不同的 Web、企业和云计算应用程序的实现有不同的数据库需求,例如,不是每个应用程序都需要严格的数据一致性:
再比如:像 eBay、Amazon、Twitter 或 Facebook
这类大流量网站,对可伸缩性和高可用性都是非常严格的要求,不容妥协。对于这些应用程序,即使是最轻微的故障都会带来重大的经济后果,从而影响顾客信任。
接下来,我们将探讨 NoSQL 数据库的基本设计原理。
从不同角度看 CAP
据 CAP 理论创始人之一 Eric Brewer 说,三分之二人会对该理论产生误解,因为:
1、分区较为罕见;当系统未分区时通常不需要放弃一致性或可用性。
2、在同一个系统上,可能要采用非常细的粒度在一致性和可用性之间进行多次选择;子系统可能进行不同的选择,选择可能会随着操作、数据或用户的参与而改变。
3、和二元属性相比,这个三元属性以更连续的状态存在。现实中,比起系统是不能展示属性,还是百分百地展示属性,每个属性的必要级别对于结果来说更为重要。
换句话说,当您考虑到每个属性的细微差别,并关注根据现有参数每个属性需要什么级别才能实现特定成果时,CAP
理论最有效。当存在分区时,Brewer 提出了一个分为三步的策略来进行检测和处理:
1、检测分区。
2、输入一个明确的分区模式,限制某些操作。
3、启动恢复流程,该流程专为 “恢复一致性和弥补分区过程中造成的错误”
而设计。
NoSQL 数据库的设计原理
事实上,CAP 理论(由三个属性构成,一致性、可用性和分区容错性)表示一个分布式数据及系统最多只能选择满足其中两个属性。大多数系统最终决定放弃严格的一致性需求(关于
CAP 理论的更多进展信息,请参见 侧边栏)。特别是,他们应用了一个称为最终一致性 的宽松的一致性策略,确保在复制对象上没有新的更新时,所有访问最终都将返回最后一个更新值。如果没有故障发生,不一致性窗口的最大尺寸可能根据通信延迟、系统上的负载以及复制模式中涉及的副本数量等因素来决定。
1、在多个服务器上平行向外扩展吞吐量的功能。
2、一个简单调用层接口或协议(与 SQL 绑定形成对比)
3、支持比大多数传统 RDBMS 中的 ACID 事务更弱的一致性模型。
4、高效利用分布式索引和 RAM 进行数据存储。
5、动态定义新属性或数据模式的功能。
这些系统的设计特性主要用于实现以下系统目标:
1、可用性:该系统应可访问,甚至在出现网络故障或者整体数据中心离线的情况下也可以访问。
2、可伸缩性:该系统应能够以非常高的请求速率、非常低的延迟支持非常巨大的数据库。
4、弹性:该系统应能够从两个方向(向上扩展或向下扩展)满足不断变化的应用程序需求。此外,系统必须可以从容应对不断变化的需求和快速恢复稳定状态。
5、负载平衡:该系统应能够在服务器之间自动移动负载,以便大多数硬件资源可得到有效利用,从而避免出现资源过载。
6、故障容错:该系统应能够处理实际情况,即便是最罕见的硬件问题在某些情况下最终也变成了反常事件。硬件故障仍然是一个很严重的问题,该问题需要从数据库基础架构层上进行解决,而不是要求开发人员、管理员和操作员工构建自己的冗余解决方案。
事实上,Google 的 BigTable 和 Amazon 的 Dynamo
提供了一个启发和引导所有 NoSQL 系统开发的概念验证:
1、BigTable 证明了持久记录存储可扩展到数以千计的节点上。
2、Dynamo 率先提出了最终一致性理念,以此作为一个实现高度可用性和伸缩性的方法。
开源社区以众多系统作为回应,比如 HBase、Cassandra、Voldemort、Riak、Redis、Hypertable、MongoDB、CouchDB、Neo4j
以及其他许多项目。这些项目的主要区别在于它们关于替代设计选择的决策,比如:
1、数据模型:键/值、行存储、面向图形或面向文档。
2、访问路径优化:读密集型、写密集型,或者单键与多键。
3、数据分区:面向行型、面向列型和面向多列型。
4、并发性管理:强一致性、最终一致性和弱一致性。
5、CAP 理论:CP、CA 或 AP。
接下来,我们将简要介绍不同 NoSQL 备选系统主要代表的功能和特性:SimpleDB、HBase
和 MongoDB。
您知道一致性模型吗?
本文重点介绍的模型是最终一致性和强一致性。
最终一致性模型声明如果很长一段时间内都没发出任何改变,那么所有更新可能会最终通过系统传递,让副本具有很好的一致性。(这里有一个稍微不同的更强一些的定义:最终,对于给定接受更新和给定副本来说,要么更新到达副本,要么副本从服务中退出。)
强一致性意味着同一系列顺序中的并行进程(节点)能够看到所有访问。
弱一致性意味着所有进程可依次看到同步变量的所有访问;而其他进程上的访问可按照不同顺序出现。
立即一致性 (Immediate consistency) 意味着当更新操作向用户返回一个成功结果时,更新结果立即对所有观察者可见。它仅定义了关于更新完成后单个更新的系统状态。
SimpleDB
SimpleDB 是一个商业 Amazon Web Service (AWS),这是专为在云中提供结构化数据存储而设计的,Amazon
托管的数据库服务器集群为其提供支持。它是一个高度可用且灵活的非关系型数据存储,取消了数据库管理工作。实际上,SimpleDB
代表一个云托管的存储服务,提供了不同应用程序接口(比如 REST、API),以便 IBM? SmartCloud?
Enterprise 上托管的任何软件应用程序都可以方便地使用和访问。
在 SimpleDB 中存储数据不需要任何预定义模式信息。开发人员只需要通过
Web 服务请求存储和查询数据详细信息即可,其余工作由 SimpleDB 完成。并不强制每个数据项(数据记录)必须具有相同的字段;然而,缺乏模式有时也意味着没有相应的数据类型,因为所有数据值均被视为可变长度的字符数据。
无模式数据存储的缺点也包括数据库中缺乏自动完整性检测 (没有外键),以及不断增加的应用程序处理格式和类型转换负担。
SimpleDB 有一个定价结构,包括对数据存储、数据转换以及处理器使用收费;没有基础费用也没有最低限制。和大多数
AWS 服务类似,SimpleDB 提供了一个遵循 REST 和 SOAP 协议的原则和标准的简单 API
接口,在 REST 和 SOAP 协议中,用户通过发送一个带有请求的消息来执行特定操作。SimpleDB
服务器可完成这些操作,除非出现一个错误,否则以成功代码和结果数进行响应。响应数据是一个 XML 格式的
HTTP 响应包,有标头、存储元数据以及一些有效负载。
在 SimpleDB 中,数据存储的顶级抽象元素是域(domain)。域
大体上类似于数据表,您可以根据需要在其中创建和删除域。这里没有创建域的设计或配置选项,惟一可设置的参数是域名。
在 SimpleDB 域中所有数据都以 “键-值” 属性对的形式存储。每个属性对与一个充当数据表行的项相关联。属性名类似于数据库列名,但不同项(行)可能包含不同的属性名,这使得用户可以在一些项中自由存储不同属性,无需改变其他没有相同属性的条目的布局。在常见模式更改或模式演化的情况下,这一灵活性使得您可以轻松地添加新的数据字段。
除此之外,每个属性不止一个值(多值属性),而是具有一组值。在这种情况下,您要做的就是将另一个属性添加到该条目,并使用带不同属性值的相同属性名。在添加每个值后,它们会被自动索引,但是没有显式索引进行维护,因此没有任何类型的维护工作要做。另一方面,您对创建的索引没有任何直接控制。
Java? 代码片段是一个创建 SimpleDB 域的示例:
SimpleDB simpleDB = new SimpleDB(accessKeyID, secretAccessKey); try { simpleDB.createDomain("employee"); System.out.println("create domain succeeded"); } catch (SDBException e) { System.err.printf("create domain failed"); } |
在该示例中,变量 accessKeyID 和 secretAccessKey
代表连接用户的 AWS 证书,employee 代表创建的域名。SimpleDB 支持的其他域操作包括:
1、DeleteDomain 操作,永久删除与现有命名域有关的所有数据。
2、ListDomains,返回与用户账户相关的所有域清单。
3、DomainMetadata 操作,返回特定域的详细信息,比如:
4、ItemCount,返回域中所有条目数量
5、AttributeNameCount,返回域中所有惟一属性名数量,而AttributeValueCount,返回域中所有名/值对的数量。
下列代码片段展示了一个使用 PutAttribute 操作存储数据的示例:
SimpleDB simpleDB = new SimpleDB(accessKeyID, secretAccessKey); ItemAttribute[] employeeData = new empAttribute[] { new ItemAttribute("empID", "JohnS"), new ItemAttribute("first_name", "John"), new ItemAttribute("last_name", "Smith"), new ItemAttribute("city", "Sydney"), }; try { Domain domain = simpleDB.getDomain("employee"); Item newItem = domain.getItem("E12345"); newItem.putAttributes(Arrays.asList(employeeData)); System.out.println("put attributes succeeded"); } catch (SDBException e) { System.err.printf("put attributes failed"); } |
可使用以下 Java 代码片段取回之前存储的数据:
SimpleDB simpleDB = new SimpleDB(accessKeyID, secretAccessKey); try { Domain domain = simpleDB.getDomain("users"); Item item = domain.getItem("E12345"); String fname = user.get("first_name "); String lname = user.get("last_name "); String city = user.get("city"); System.out.printf("%s %s %s", fname, lname, city); } catch (SDBException e) { System.err.printf("get attributes failed"); } |
SimpleDB 支持的其他数据控制操作包括:
1、BatchPutAttributes 操作,支持在一个调用中存储多个条目数据。
2、DeleteAttributes 操作,删除之前在 SimpleDB 中存储的条目数据。
SimpleDB Select API 使用一种类似于 SQL Select 语句的查询语言。该查询语言使得
SimpleDB Select 操作为大家所熟知,对用户来说,该语句非常容易理解。请注意这样一个问题,该语言仅支持在单一域范围内发布查询(没有链接、多域或子选择查询)。例如,该
SimpleDB 选择语句可在底层域检索最受欢迎的电影:
SELECT * FROM movies WHERE rating > '04' ORDER BY rating LIMIT 10 |
在该示例中,movies 代表域名,rating 是该域条目的一个过滤属性。因为在 SimpleDB
中每个属性都有一个索引,所以可以使用索引来优化每个查询谓词的评估。作为查询执行计划的一部分,SimpleDB
会尝试动态选择每个查询的最佳索引。
SimpleDB 通过使用复杂复制和后台故障恢复机制来实现,因此,当您使用 SimpleDB 时就会有一个高可用性保证,保证您的数据被自动复制到不同位置。用户不需要执行其他任何额外操作,也不需要成为高可用性专家,甚至不需要了解复制技术细节就可以实现高可用性目标。
对于每个用户读取请求来说,SimpleDB 支持两种选择:最终一致性或强一致性。一般而言,使用一致性读操作选项可消除请求一致性窗口。一致性读操作的结果可确保返回最新的值。大多数情况下,一致性读操作并不比最终一致性读操作慢,但是在某些场合(例如,大量工作负载),一致性读操作可能显示更高的延迟或更低的带宽。SimpleDB
不提供任何关于最终一致性窗口的保证,但通常不超过一秒。
当使用 SimpleDB 服务时,有不少限制,用户需要考虑:
1、每个域的最大存储容量为 10GB。
2、每个域的最大属性值是 10 亿。
3、每个条目的最大属性值是 256。
4、域名、属性名或值的最大长度为 1024 字节。
5、对于查询:
1.最大查询执行时间是 5 秒。
2.最大查询结果是 2500。
3.最大查询响应大小为 1MB。
HBase
Apache HBase,是一个 Hadoop 数据库,一个管理结构化数据分布式存储系统,专为跨水平可伸缩商业机器扩展到一个非常大的尺寸而设计。它是一个
Apache 项目,忠实地实现了 BigTable 存储基础架构的克隆(BigTable 理念的其他克隆包括
Apache Cassandra 项目和 Hypertable 项目)。事实上,HBase 群集可在任何
IaaS 云服务供应商上安装和运行,比如 IBM SmartCloud Enterprise;IBM InfoSphere?
BigInsights? 构建于 Hadoop 之上,用于提供必要的面向企业的功能。
HBase 于 2007 年发布,是一个稀疏的、分布式的、持久化的多维分类映射。该映射可通过行键、列键或者时间戳来进行索引。映射中的每个值都是一个未解释的字节数组,因此,客户通常需要将各种形式的结构化和非结构化数据序列化到这些字符串中。反映一些主要
HBase 设计决策的具体示例可在某些场景中找到,在这些场景中,需要将大量 Web 页面的副本存储到一个表中。
图 1 展示了该表的一个示例,其中 URL 被用作列键,Web 页面内容被存储在一个单独列中,该列存储了页面的多个版本,根据页面捕获时间戳进行存储。
图 1. HBase 表中的样例记录
表中的行键可以是任意字符串,其中单一行键下数据的每个读操作或写操作都是原子的。HBase 按照字典顺序通过行键来维护数据,其中一个表的行区间是动态分区的。使行键始终有序可为您提供类似关系数据库中发现的主键索引之类的内容。
原始 BigTable 实现只考虑单一索引,HBase 增加了辅助索引支持。每个行区间都位于每个表中,被称为一个
tablet,代表分布式和负载平衡单元。短小的行区间读取是有效的,通常只需要与少数几个机器通信。
您知道稀疏数据集吗?
我刚刚在文章中提到过稀疏数据集,我想我已经定义其含义。稀疏数据矩阵 是一个重要数据或者连接分布密度较低的矩阵。正如我在文本中所说的,大多数值为空。(从另一个角度来说,在密集数据矩阵中,大多数值是非空的。)稀疏数据矩阵对存储的影响如下:
稀疏矩阵容易压缩,占用较少的存储空间。
用于处理密集矩阵的算法实际上速度很慢,有着相当大的计算开销;成本高昂的工作在稀疏矩阵中常常被浪费。
HBase 可以有无限个列,被分组到称之为列簇 (column families) 的集合中,这些列簇代表了访问控制的基本单元。数据被存储在列中,如果值为空则不需要存储值,因此
HBase 非常适合稀疏数据集。每个列值(单元)既可由系统暗中加上时间戳,也可由用户显式设置。这意味着每个单元可以包含同一数据的多个版本,这些数据是通过时间戳机型索引的。用户可以灵活地指定保存多少个版本。这些版本以时间戳降序进行存储,以便可以首先读取最新的版本。综上所述您就会发现,可以采用下列方式表达数据访问:
(Table, RowKey, Family, Column, Timestamp) --> Value |
短小的行区间读取需要较少的通信,这一事实可能影响到查询的开发,因此它们适用于可用网络资源。在物理层上,HBase
使用 Hadoop 分布式文件系统代替 Google 文件系统。将更新放在内存中,以便定期将它们写入磁盘文件中。
HBase 中的可伸缩性和负载平衡基本单元被称为一个区域 (region)。区域本质上是存储在一起的连续行区间。当区间太大时,区间就会被系统动态分割;另外也可以将区间合并到一起,以减少区间数量和所需的存储文件。
最初,一个表只有一个区域;随着您不断向其中添加数据,系统需要对其进行监控,以确保您不会超过配置的最大限制。如果超过了该限制,就会从区域的中间键处将区域分割成基本相等的两个区域。每个区域完全由一个区域服务器提供服务,每个服务器随时可为多个区域提供服务。
分割和服务区域可被认为是自动-分片,这是其他系统提供的一项技术。当系统正常运行时,可进行区域服务器添加或删除。服务器所有人负责将区域分配到区域服务器,可使用
Apache ZooKeeper(一个可靠的、高度可用的、持久化的、分布式协调服务)来完成这项任务。除此之外,它还可以处理模式变更,比如表和列簇创建。
在 HBase 中,对于每一行来说,必须确保使数据发生变化的所有操作是原子的。它使用开放式并行控制,如果与其他更新发冲突,则终止所有操作。这会影响同一行的其他所有并发读写操作,因为它们要么读取一个一致的最后突变,要么需要等待才能应用其更改。对于数据存储和访问,HBase
提了供一个 Java API、一个 Thrift API、一个 REST API 和一个 JDBC/ODBC
连接。
以下代码片段显示了在 HBase 中存储数据的示例:
Configuration conf = HBaseConfiguration.create(); HTable table = new HTable(conf, "employee"); Put put = new Put(Bytes.toBytes("E12345")); put.add(Bytes.toBytes("colfam1"), Bytes.toBytes("first_name"), Bytes.toBytes("John")); put.add(Bytes.toBytes("colfam1"), Bytes.toBytes("last_name"), Bytes.toBytes("Smith")); put.add(Bytes.toBytes("colfam1"), Bytes.toBytes("city"), Bytes.toBytes("Sydney")); table.put(put); |
该示例在 employee 表中创建了一个行,添加了一个包含三个列的列簇 (first_name、last_name
和 city),在创建的列中存储数据值,并将该列行添加到 HBase 表中,以下代码片段展示了一个从 HBase
检索数据的示例:
Configuration conf = HBaseConfiguration.create(); HTable table = new HTable(conf, " employee"); Get get = new Get(Bytes.toBytes("E12345")); get.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("first_name ")); Result result = table.get(get); byte[] val = result.getValue(Bytes.toBytes("colfam1"), Bytes.toBytes("first_name ")); System.out.println("Employee's first name is: " + Bytes.toString(val)); |
除此之外,HBase 提供一组丰富的 API 函数,比如,Delete 函数,用于删除任何键的属性值:DeleteColumn
函数,用于删除整个列:DeleteFamily 函数,用于删除整个列簇,包括其中包含的所有列。此外,还有一组批处理操作
Put、Get 和 Delete 函数,以及结果扫描操作。
MongoDB
MongoDB 是一个分布式、无模式、面向文档的数据库,由 10gen 公司推出。它可以存储二进制 JSON
文档(BSON),BOSN 是二进制编码的 JSON 类对象。BSON 支持带有嵌入对象和数组的嵌套对象结构。类似于
HBase,MongoDB 和 CouchDB 集群可在任何 IaaS 供应商平台(比如,IBM SmartCloud
Enterprise)上安装和运行。
MongoDB 的核心是文档 概念,文档表示一组有序的键及相关值集合;集合 是一组文档。在关系数据库中,如果文档是一个
MongoDB 模拟,那么集合可被认为是一个表的模拟。
集合是无模式的。这意味在一个集合中,文档可有任意数量的不同 “形状”。例如,以下文档都可以存储在一个集合中:
{"empID" : "E12345", "fname" : "John", "lname" : "Smit", "city" : "Sydney", "age": 32} {"postID" : "P1", "postText" : "This is my blog post"} |
请注意,前一个文档不仅有不同的结构和值类型,还有完全不同的键。
MongoDB 将集合分组到不同的数据库中。一个 MongoDB 实例可托管集合数据库,每个都被认为是完全独立的。insert
函数可以将一个文档添加到一个集合中。下列代码片段展示了将一个 post 文档插入博客集的示例:
post = {"title" : "MongoDB Example", "content" : "Insertion Example ", "author" : :"John Smith"} db.blog.insert(post) |
将博客文档保存到数据库后,可以通过在调用集合中的 find 方法来检索该文档:db.blog.find("title"
: "MongoDB Example")。
find 方法将会返回集合中满足过滤条件的所有文档。如果只想查看其中一个文档,可以使用 findOne
方法:db.blog.findOne()。
如果想要修改该文档,可以使用 update 方法,该方法带有(至少)两个参数:
1、该标准将找到要更新的文件。
2、新文档。
以下代码片段展示了一个更新博客文章内容的示例:
post = {"content" : "Update Example"} blog.update({{title : " MongoDB Example "}, post } |
您知道分片吗?
数据库分片 (shard) 是一个数据库的水平分区或者搜索引擎。每个独立分区都可以是一个分片。数据库表的一行可以单独保存,不再被分割成几列(标准化),每个分区(分片)可位于一个独立数据库服务上或不同的物理位置。
分片的优势是:
1、每个数据库中表的行数有所减少。
2、索引的减少通常可以提高搜索性能。
3、数据库可分布到大量机器上(这也可增加性能)。
4、分片细分可与真实数据访问模式相关联,尽管这并不常见。(例如,欧洲销售代表访问的欧洲数据、亚洲销售访问的亚洲数据;每个代表只需查询相关的分片即可,这使得查询更为高效。)
在实践中,分片相当复杂。作者兼开发人员 Andy Glover 在这篇 developerWorks
文章中提供了一个完整的 分片概述 。
请注意,MongoDB 只提供最终一致性保证,因此,一个进程可能读取了文档的旧版本,即使另一个进程已经执行了更新操作。此外,它不提供事务管理,这就导致当一个进程读取文档并将修改写入数据库时,另一个进程也有可能在第一个进程读和写操作之间对同一个文档进行了更新。
remove 方法将从数据库中彻底删除文档。如果没有调用参数,则将删除集合中的所有文档。如果指定了参数,则只删除指定删除的文档。以下代码片段将会删除样例博客文章的示例:db.blog.remove({title
: " MongoDB Example "})。
您可以使用 ensureIndex 方法创建索引。以下代码片段展示了一个使用标题信息为博客文章建立索引的示例:db.people.ensureIndex({"title
" : 1})。
MongoDB 也支持在多个文件上索引文档。API 接口比较丰富,且支持许多批处理操作和集合函数。MongoDB
是使用 C++ 执行的,可为很多编程语言提供驱动程序,比如 C、C#、C++、Erlang、Haskell、Java、JavaScript、Perl、PHP、Python、Ruby
和 Scala,还可以提供 JavaScript 命令行接口。
Apache CouchDB 项目是另一个面向文档的数据库示例,数据库模型和数据管理机制类似于 MongoDB。Apache
CouchDB 是使用 Erlang 编写的,尽管可在使用 JavaScript 编写的应用程序中使用它,但它目前并不是一个分布式数据库。该文档可作为
JSON 对象进行存储和访问。CouchDB 不支持文档类型或者不支持数据表,因此开发人员必须自己构建文档类型进行区别
,可以通过在每个文档中放置一个 type 属性来实现此操作。
CouchDB 中一个有趣的特性就是它支持定义一个确认功能,当更新或创建文档时,确认函数将被触发,以验证或确认该操作。还可以通过调整
CouchDB 来提供强一致性或最终一致性保证。
DB2 对 NoSQL 的支持
追求在云环境中实现高效的数据库管理时,使用最适合每个数据库管理任务的数据模型是最终目标,因此,在此值得一提的是,传统关系数据也支持各种
NoSQL 版本来实现此目标(我将在结束语中进一步探讨)。
例如,IBM DB2 通过一个 API 来支持 NoSQL 图形存储,该 API 支持多个调用和一个
NoSQL 软件解决方案栈。图形存储只在三个列中存储数据(一个三角形),将数据表示为一个名词、一个动词和一个名词。简单查询可以拖入与名词匹配的任何数据三角中。DB2
为图形存储提供性能增强特性,比如,将图形三角映射到一个关系数据库(不限制列数量)中,进行数据压缩、 并行执行和负载平衡等功能。
DB2 还通过 DB2 pureXML 提供了一个 NoSQL 类数据库类型、XML 数据存储,这使得以原生层次结构格式管理基于
Web 的数据更为容易。DB2 用户可以使用查询语言(比如 XPath 和 XQuery)来处理 XML
文档。该数据模型在管理信息不断改变的使用案例中会用到。
结束语
在超过四分之一世纪的时间里,关系数据库管理系统 (RDBMS) 一直是数据管理的主要模型。它们提供了极具吸引力的界面来管理和访问数据,
在许多金融、商业和 Internet 应用程序中,也证明关系数据库管理系统是非常成功的。随着 Web 规模数据管理趋势的蔓延,它们开始遭遇各种限制。
作为可供选择的数据库管理模型,NoSQL 系统具有的主要优势包括:
1、弹性伸缩:多年来,数据库管理员一直依赖纵向扩展方法,而不是横向扩展方法;随着目前事务级别和高可用性需求的不断增加,横向扩展(特别是在商用硬件上)的经济优势变得极具吸引力。NoSQL
系统设计具有透明扩展能力,可利用新节点添加优势。
2、更少的管理:NoSQL 数据库通常旨在支持诸如自动修复和简单的数据模型等特性;这会导致较低的管理和调优需求。
3、更好的经济效益:NoSQL 数据库通常使用大量廉价商品服务器来管理激增的数据和事务量。
4、灵活的数据模型:NoSQL 数据库具有更为宽松的数据模型限制(如果有的话),因此应用程序和数据库模式改动可能更小。
NoSQL 数据库仍然需要克服许多障碍,才能吸引主流企业:
1、编程模型:NoSQL 数据库提供一些专用查询和分析设施。即使一个简单的查询也需要大量的编程知识 。由于缺少声明表述支持,重要的
join 操作一直被认为是这些系统的主要限制。
2、事务支持:事务管理是功能最强大的一个 RDBMS 特性。目前,对于那些被接受用来实现任务关键系统的事务来说,NoSQL
数据库系统上的事务概念的非存在限制(limited-to-non-existent)支持是一个障碍。
3、成熟性:众所周知,RDBMS 系统具有高稳定性和丰富的功能性。相比之下,大多数 NoSQL 替代方案还处于预生产
版本阶段,很多功能尚不稳定,且无法实现。这意味着企业在进入新一波数据管理时仍需谨慎。
4、支持:企业还在寻求保障,如果系统出现故障,那么他们能够得到及时的、足够的支持。RDBMS 供应商竭尽全力提供高级支持。相比之下,很多
NoSQL 系统是开源项目,目前尚未获得支持。
5、专业人士:几乎每个 NoSQL 开发人员都处于学习阶段;当然,这种状况不会持续太长时间。但是目前寻找经验丰富的
RDBMS 程序员或管理员比寻找 NoSQL 专家更容易。
NoSQL 和 RDBMS 论战可能永远不会有明确的答案。最有可能的答案就是不同数据管理解决方案在一个应用程序中共存。例如,可以想象一个应用程序采用不同数据存储来实现不同用途的情况:
1、SQL RDBMS 存储数据量较少的高价值数据,比如用户档案和账单信息。
2、键/值对存储数据量较大且价值较低的数据,比如单击次数和日志。
3、文件存储服务用于存储用户上传资产,比如,照片、声音文件和大二进制文件。
4、文档数据库存储应用程序程序文档,比如账单。
|