技术开发 频道

Java开发2.0:NoSQL

  【IT168 技术】在 Web 2.0 时代,NoSQL 数据存储(比如 Bigtable 和 CouchDB)从边缘进入主流,因为它们能够解决伸缩性问题,而且能够大规模解决该问题。Google 和 Facebook 只是已经开始使用 NoSQL 数据存储的两家知名公司,我们仍然处于使用 NoSQL 数据存储的早期阶段。无模式数据存储与传统的关系数据库存在根本区别,但是利用它们比您想象的要简单得多,尤其是当您从一个域模型而不是一个关系模型开始时。

  关系数据库已经统治数据存储 30 多年了,但是无模式(或 NoSQL)数据库的逐渐流行表明变化正在发生。尽管 RDBMS 为在传统的客户端 - 服务器架构中存储数据提供了一个坚实的基础,但它不能轻松地(或便宜地)扩展到多个节点。在高度可伸缩的 Web 应用程序(比如 Facebook 和 Twitter)的时代,这是一个非常不幸的弱点。

  尽管关系数据库的早期替代方案(还记得面向对象的数据库吗?)不能解决真正紧急的问题,NoSQL 数据库(比如 Google 的 Bigtable 和 Amazon 的 SimpleDB)却作为对 Web 的高可伸缩性需求的直接响应而崛起。本质上,NoSQL 可能是一个杀手问题的杀手应用程序 —随着 Web 2.0 的演变,Web 应用程序开发人员可能会遇到更多,而不是更少这样的应用程序。

  在这期 Java 开发 2.0 中,我将向您介绍无模式数据建模,这是经过关系思维模式训练的许多开发人员使用 NoSQL 的主要障碍。您将了解到,从一个域模型(而不是关系模型)入手是简化您的改变的关键。如果您使用 Bigtable(如我的示例所示),您可以借助 Gaelyk:Google App Engine 的一个轻量级框架扩展。

  NoSQL:一种新的思维方式?

  当开发人员谈论非关系或 NoSQL 数据库时,经常提到的第一件事是他们需要改变思维方式。我认为,那实际上取决于您的初始数据建模方法。如果您习惯通过首先建模数据库结构(即首先确定表及其关联关系)来设计应用程序,那么使用一个无模式数据存储(比如 Bigtable)来进行数据建模则需要您重新思考您的做事方式。但是,如果您从域模型开始设计您的应用程序,那么 Bigtable 的无模式结构将看起来更自然。

  非关系数据存储没有联接表或主键,甚至没有外键这个概念(尽管这两种类型的键以一种更松散的形式出现)。因此,如果您尝试将关系建模作为一个 NoSQL 数据库中的数据建模的基础,那么您可能最后以失败告终。从域模型开始将使事情变得简单;实际上,我已经发现,域模型下的无模式结构的灵活性正在重新焕发生机。

  从关系数据模型迁移到无模式数据模型的相对复杂程度取决于您的方法:即您从基于关系的设计开始还是从基于域的设计开始。当您迁移到 CouchDB 或 Bigtable 这样的数据库时,您 的确会丧失 Hibernate(至少现在)这样的成熟的持久存储平台的顺畅感觉。另一方面,您却拥有能够亲自构建它的 “绿地效果”。在此过程中,您将深入了解无模式数据存储。

  实体和关系

  无模式数据存储赋予您首先使用对象来设计域模型的灵活性(Grails 这样的较新的框架自动支持这种灵活性)。您的下一步工作是将您的域映射到底层数据存储,这在使用 Google App Engine 时再简单不过了。

  在文章 “Java 开发 2.0:针对 Google App Engine 的 Gaelyk” 中,我介绍了 Gaelyk —— 一个基于 Groovy 的框架,该框架有利于使用 Google 的底层数据存储。那篇文章的主要部分关注如何利用 Google 的 Entity对象。下面的示例(来自那篇文章)将展示对象实体如何在 Gaelyk 中工作。

  清单 1. 使用 Entity 的对象持久存储

def ticket = new Entity("ticket")

ticket.officer
= params.officer

ticket.license
= params.plate

ticket.issuseDate
= offensedate

ticket.location
= params.location

ticket.notes
= params.notes

ticket.offense
= params.offense

  这种对象持久存储方法很有效,但容易看出,如果您频繁使用票据实体 —例如,如果您正在各种 servlet 中创建(或查找)它们,那么这种方法将变得令人厌烦。使用一个公共 servlet(或 Groovlet)来为您处理这些任务将消除其中一些负担。一种更自然的选择 —我将稍后展示 —将是建模一个 Ticket对象。

0
相关文章