2.1 保持组件简单以促进重用
如果你和关系型数据库打交道,那么你应该知道它们是多么复杂。一开始,它们是一个简单的系统,当被请求时,从单一的平面文件返回一个被选择的行即可。随着时间的迁移,它们需要管理不止一张表、执行连接操作、对查询进行优化、复制事务、运行存储过程、设置触发器、保证安全性、维护索引等。对于这些复杂的问题,NoSQL系统另辟蹊径,通过在网络中构建简单的分布式应用来满足不同维度的需求。保持架构级别的组件简单使得在不同的应用中可以重用这些组件,帮助开发人员理解和测试,而且应用的架构迁移也变得更容易。
NoSQL的观点认为,简单就是好的。构建一个应用时,并不需要在一个软件中包含所有的功能,应用的功能可以被分发到多个NoSQL(或者SQL)数据库上完成,这些系统由许多简单工具组成并具有简单的接口和清晰定义的功能。NoSQL产品遵循的原则是做好几件事。为了说明这一点,我们来看看系统是如何通过清晰定义的功能构建而成,并关注基于这些功能组合成新的功能是多么地容易。
如果你对UNIX操作系统熟悉的话,你应该对UNIX管道的概念不陌生。UNIX管道是一组相互连接的进程,前一个进程的输出正好是下一个进程的输入。与 UNIX 管道类似,NoSQL 系统由许多协同工作的功能模块构成。如图2-1所示,这是一个由一些小功能通过UNIX管道连接用来统计书中出现·figure·单词的次数。
图2-1 UNIX管道是个复用一些简单功能以实现新功能的例证。该图显示将一个目录中的所有章节文件连接起来并对所有章节的图片数量进行统计。通过使用UNIX管道,我们可以将3个简单的命令拼接成一个字符串:连接(·cat·)、搜索函数(·grep·)和单词计数(·wc·)。没有多余的代码,每一个函数接受前一个函数的输出并进行处理
这个例子的显著特点是通过键入 40 来个字符你就可以创建一个有用的函数。如果是在不支持UNIX风格函数的系统中,情况就困难得多。事实上,在原生XML数据库上执行的查询可能还会比这条命令更短,但这并不是通用的。
许多NoSQL系统都遵循利用协同工作的模块化组件这一思想。为了取代单一的大型数据库层,它们经常采用通过重新组合许多更加简单的模块的方法来满足不同应用的需求。例如,某一个功能允许通过内存(或者是memcache)共享对象,另一个功能负责运行批处理作业(如MapReduce作业),还有一个功能负责存储二进制文档(以键值对的方式存储)。我们注意到大多数UNIX管道的设计宗旨是在单一的处理器之上通过拼接线性的管道来达到传输面向行的数据流。而NoSQL的组件,尽管模块化,却不仅仅是一系列的线性管道组件。它们专注于那些常用于增强分布式Web服务的高效的数据服务。NoSQL系统可以是文档、消息、消息存储、文件存储或者是通过通用的API提供基于REST、JSON或XML的Web服务,它们还提供装载、验证、转换和输出海量数据的工具,而UNIX管道实际上是被设计成只能在单处理器之上工作。
标准观察:用来处理结构化数据的通用管道
你这时候可能会问是否还能用UNIX管道背后的思想来处理结构化数据。如果你使用的是JSON或者是XML的标准,那么答案是肯定的。并且W3C已经意识到管道的思想可以用来处理任意非结构化的数据以满足通用的需求,他们提供了管道式处理数据的标准:XProc。一些NoSQL数据库已经内建并实现了XProc作为它们架构的一部分。XProc标准允许一个NoSQL内建的数据转换管道不经任何修改就可以连接到其他XProc系统。可以通过http://www.w3.org/TR/xproc/找到更多有关XProc的信息。另外还有一个XML语法风格的UNIX脚本工具:XMLSH。可以通过http://www.xmlsh.org找到更多有关XMLSH的信息。
关于NoSQL系统的简单功能的概念将是反复出现的主题。哪怕是NoSQL系统不能在单一系统中满足所有的需求,也要敢于建议使用或者真正去使用NoSQL系统。可以把它们看作是工具的集合,如果对它们的组合使用方法了解越多,它们会变得越有用。接下来,我们将来看到这个简单的概念对于基于NoSQL的应用层的开发的重要性。