Add New Notes
40
Zim/NonSQL/CAP原理和BASE思想.txt
Normal file
@@ -0,0 +1,40 @@
|
||||
Content-Type: text/x-zim-wiki
|
||||
Wiki-Format: zim 0.4
|
||||
Creation-Date: 2011-06-14T21:58:17+08:00
|
||||
|
||||
====== CAP原理和BASE思想 ======
|
||||
Created 星期二 14 六月 2011
|
||||
|
||||
分布式领域CAP理论,
|
||||
Consistency(一致性), 数据一致更新,所有数据变动都是同步的
|
||||
Availability(可用性), 好的响应性能
|
||||
Partition tolerance(分区容错性) 可靠性
|
||||
|
||||
定理:任何分布式系统只可同时满足二点,没法三者兼顾。
|
||||
忠告:架构师不要将精力浪费在如何设计能满足三者的完美分布式系统,而是应该进行取舍。
|
||||
|
||||
关系数据库的ACID模型拥有 高一致性 + 可靠性 丧失可用性:
|
||||
Atomicity原子性:一个事务中所有操作都必须全部完成,要么全部不完成。
|
||||
Consistency一致性. 在事务开始或结束时,数据库应该在一致状态。
|
||||
Isolation隔离层. 事务将假定只有它自己在操作数据库,彼此不知晓。
|
||||
Durability. 一旦事务完成,就不能返回。
|
||||
跨数据库事务:2PC (two-phase commit), 2PC is the anti-scalability pattern (Pat Helland) 是反可伸缩模式的,JavaEE中的JTA事务可以支持2PC。因为2PC是反模式,尽量不要使用2PC,使用BASE来回避。
|
||||
|
||||
BASE模型反ACID模型,完全不同ACID模型,牺牲高一致性,获得可用性或可靠性:
|
||||
Basically Available基本可用。支持分区失败(e.g. sharding碎片划分数据库)
|
||||
Soft state软状态 状态可以有一段时间不同步,异步。
|
||||
Eventually consistent最终一致,最终数据是一致的就可以了,而不是时时高一致。
|
||||
|
||||
BASE思想的主要实现有
|
||||
1.按功能划分数据库
|
||||
2.sharding碎片
|
||||
|
||||
BASE思想主要强调基本的可用性,如果你需要High 可用性,也就是纯粹的高性能,那么就要以一致性或容错性为牺牲,BASE思想的方案在性能上还是有潜力可挖的。
|
||||
|
||||
现在NOSQL运动丰富了拓展了BASE思想,可按照具体情况定制特别方案,比如忽视一致性,获得高可用性等等,NOSQL应该有下面两个流派:
|
||||
1. key-value存储,如Amaze Dynamo等,可根据CAP三原则灵活选择不同倾向的数据库产品。
|
||||
2. 领域模型 + 分布式缓存 + 存储 (Qi4j和NoSql运动),可根据CAP三原则结合自己项目定制灵活的分布式方案,难度高。
|
||||
|
||||
这两者共同点:都是关系数据库SQL以外的可选方案,逻辑随着数据分布,任何模型都可以自己持久化,将数据处理和数据存储分离,将读和写分离,存储可以是异步或同步,取决于对一致性的要求程度。
|
||||
|
||||
不同点:NOSQL之类的key-value存储产品是和关系数据库头碰头的产品BOX,可以适合非Java如PHP RUBY等领域,是一种可以拿来就用的产品,而领域模型 + 分布式缓存 + 存储是一种复杂的架构解决方案,不是产品,但这种方式更灵活,更应该是架构师必须掌握的。
|
||||
72
Zim/NonSQL/NoSQL数据库利弊分析/五大优势五大挑战.txt
Normal file
@@ -0,0 +1,72 @@
|
||||
Content-Type: text/x-zim-wiki
|
||||
Wiki-Format: zim 0.4
|
||||
Creation-Date: 2011-06-14T22:10:18+08:00
|
||||
|
||||
====== 五大优势五大挑战 ======
|
||||
Created 星期二 14 六月 2011
|
||||
|
||||
关系数据库模型已经流行了几十年了,但是一种新类型的数据库——被称为NoSQL,正在引起企业的注意。下面是关于它的优势和劣势的一个概述。二十多年以来,对数据库管理来说,关系数据库(RDBMS)模型一直是一个占统治地位的数据库模型。但是,今天,非关系数据库,“云”数据库,或 “NoSQL”数据库作为关系数据库以外的一些选择,正在引起大家的广泛关注。在这篇文章里,我们将主要关注那些非关系的NoSQL数据库的十大利弊:包括五大优势和五大挑战。
|
||||
|
||||
NoSQL的五大优势
|
||||
|
||||
1.灵活的可扩展性
|
||||
|
||||
多年以来,数据库管理员们都是通过“纵向扩展”的方式(当数据库的负载增加的时候,购买更大型的服务器来承载增加的负载)来进行扩展的,而不是通过“横向扩展”的方式(当数据库负载增加的时候,在多台主机上分配增加的负载)来进行扩展。但是,随着交易率和可用性需求的增加,数据库也正在迁移到云端或虚拟化环境中,“横向扩展”在commodity hardware方面的经济优势变得更加明显了,对各大企业来说,这种“诱惑”是无法抗拒的。
|
||||
|
||||
在commodity clusters上,要对RDBMS做“横向扩展”,并不是很容易,但是各种新类型的NoSQL数据库主要是为了进行透明的扩展,来利用新节点而设计的,而且,它们通常都是为了低成本的commodity hardware而设计的。
|
||||
|
||||
2.大数据
|
||||
|
||||
在过去的十年里,正如交易率发生了翻天覆地的增长一样,需要存储的数据量也发生了急剧地膨胀。O’Reilly把这种现象称为:“数据的工业革命”。为了满足数据量增长的需要,RDBMS的容量也在日益增加,但是,对一些企业来说,随着交易率的增加,单一数据库需要管理的数据约束的数量也变得越来越让人无法忍受了。现在,大量的“大数据”可以通过NoSQL系统(例如:Hadoop)来处理,它们能够处理的数据量远远超出了最大型的RDBMS所能处理的极限。
|
||||
|
||||
3.“永别了”!DBA们!
|
||||
|
||||
在过去的几年里,虽然一些RDBMS供应商们声称在可管理性方面做出了很多的改进,但是高端的RDBMS系统维护起来仍然十分昂贵,而且还需要训练有素的DBA们的协助。DBA们需要亲自参与高端的RDBMS系统的设计,安装和调优。
|
||||
|
||||
NoSQL数据库从一开始就是为了降低管理方面的要求而设计的:从理论上来说,自动修复,数据分配和简单的数据模型的确可以让管理和调优方面的要求降低很多。但是,DBA的死期将至的谣言未免有些过于夸张了。总是需要有人对关键性的数据库的性能和可用性负责的。
|
||||
|
||||
4.经济
|
||||
|
||||
NoSQL数据库通常使用廉价的commodity servers集群来管理膨胀的数据和事务数量,而RDBMS通常需要依靠昂贵的专有服务器和存储系统来做到这一点。使用NoSQL,每GB的成本或每秒处理的事务的成本都比使用RDBMS的成本少很多倍,这可以让你花费更低的成本存储和处理更多的数据。
|
||||
|
||||
5.灵活的数据模型
|
||||
|
||||
对于大型的生产性的RDBMS来说,变更管理是一件很令人头痛的事情。即使只对一个RDBMS的数据模型做了很小的改动,也必须要十分小心地管理,也许还需要停机或降低服务水平。NoSQL数据库在数据模型约束方面是更加宽松的,甚至可以说并不存在数据模型约束。NoSQL的主键值数据库和文档数据库可以让应用程序在一个数据元素里存储任何结构的数据。即使是规定更加严格的基于“大表”的NoSQL数据库(例如:Cassandra, HBase)通常也允许创建新列,这并不会造成什么麻烦。
|
||||
|
||||
应用程序变更和数据库模式的变更并不需要作为一个复杂的变更单元来管理。从理论上来说,这可以让应用程序迭代的更快,但是,很明显,如果应用程序无法维护数据的完整性,那么这会带来一些不良的副作用。
|
||||
|
||||
NoSQL的五大挑战
|
||||
|
||||
NoSQL的种种承诺引发了一场热潮,但是在它们得到主流的企业的青睐以前,它们还有许多困难需要克服。下面是NoSQL需要面对的一些挑战。
|
||||
|
||||
1.成熟度
|
||||
|
||||
RDBMS系统已经发展很长时间了。NoSQL的拥护者们认为,RDBMS系统那超长的发展的年限恰恰表示它们已经过时了,但是对于大多数的 CIO们来说,RDBMS的成熟度更加令它们放心。大多数情况下,RDBMS系统更加稳定,而且功能也更加丰富。相比之下,大多数的NoSQL数据库都是 pre-production版本,许多关键性的功能还有待实现。
|
||||
|
||||
对于大多数开发者来说,处于技术的最前沿的确是很令人兴奋的,但是企业应该怀着极端谨慎的态度来处理此事。
|
||||
|
||||
2.支持
|
||||
|
||||
企业都希望能得到这样的保证:如果一个关键性的系统出现问题了,他们可以获得及时有效的支持。所有的RDBMS供应商都在竭尽全力地提供高水平的企业支持。
|
||||
|
||||
相反,大多数的NoSQL系统都是开源项目,虽然对于每个NoSQL数据库来说,通常也会有一个或多个公司对它们提供支持,但是那些公司通常是小型的创业公司,在支持的范围,支持的资源,或可信度方面,它们和Oracle, Microsoft或IBM是无法相提并论的。
|
||||
|
||||
3.分析和商业智能化
|
||||
|
||||
NoSQL数据库现在已经可以满足现代的Web2.0应用程序的高度的可扩展性的要求了。这直接导致的结果是,它们的大多数功能都是面向这些应用程序而设计的。但是,在一个应用程序中,具有商业价值的数据早就已经超出了一个标准的Web应用程序需要的“插入-读取-更新-删除”的范畴了。在公司的数据库中进行商业信息的挖掘可以提高企业的效率和竞争力,而且对于所有的中到大型的公司来说,商业智能化(BI)一直是一个至关重要的IT问题。
|
||||
|
||||
NoSQL数据库几乎没有提供什么专用的查询和分析工具。即使是一个简单的查询,也要求操作者具有很高超的编程技术,而且,常用的BI工具是无法连接到NoSQL的。
|
||||
|
||||
像HIVE或PIG那样的新出现的一些解决方案在这方面可以提供一些帮助,它们可以让访问Hadoop集群中的数据变得更加容易,最后也许还会支持其他的NoSQL数据库。Quest软件已经开发了一个产品——Toad for Cloud Databases——它给各种NoSQL数据库提供了专用的查询功能。
|
||||
|
||||
4.管理
|
||||
|
||||
NoSQL的设计目标是提供一个“零管理”的解决方案,但是目前来说,还远远没有达到这个目标。安装NoSQL还是需要很多技巧的,同时,维护它也需要付出很多的努力。
|
||||
|
||||
5.专业知识
|
||||
|
||||
毫不夸张地说,全世界有数百万的开发者,他们都对RDBMS的概念和编程方法很熟悉,在每个业务部门中都有这样的开发者。相反,几乎每一个 NoSQL开发者都正处于学习状态中。虽然这种情况会随着时间的推移而改变,但是现在,找到一些有经验的RDBMS程序员或管理员要比找到一个NoSQL 专家容易的多。
|
||||
|
||||
结论
|
||||
|
||||
NoSQL数据库正在逐渐地成为数据库领域中不可或缺的一部分,如果使用方法得当的话,能获得很多的好处。但是,企业应该谨慎行事,要充分地认识到这些数据库的一些限制和问题。
|
||||
96
Zim/NonSQL/NoSQL架构实践(1).txt
Normal file
@@ -0,0 +1,96 @@
|
||||
Content-Type: text/x-zim-wiki
|
||||
Wiki-Format: zim 0.4
|
||||
Creation-Date: 2011-06-14T21:05:19+08:00
|
||||
|
||||
====== NoSQL架构实践(1) ======
|
||||
Created 星期二 14 六月 2011
|
||||
|
||||
怎么样把NoSQL引入到系统架构设计中,需要根据我们**系统的业务场景来分析**,什么样类型的数据适合存储在NoSQL数据库中,什么样类型的数据必须使用关系数据库存储。明确引入的NoSQL数据库带给系统的作用,它能解决什么问题,以及可能带来的新的问题。下面我们分析几种常见的NoSQL架构。
|
||||
|
||||
===== (一)NoSQL作为镜像 =====
|
||||
|
||||
不改变原有的以MySQL作为存储的架构,使用NoSQL作为辅助镜像存储,用NoSQL的优势辅助提升性能。
|
||||
{{./image1.JPG}}
|
||||
图 1 -NoSQL为镜像(代码完成模式 )
|
||||
|
||||
//写入数据的示例伪代码
|
||||
|
||||
//data为我们要存储的数据对象
|
||||
data.title=”title”;
|
||||
data.name=”name”;
|
||||
data.time=”2009-12-01 10:10:01”;
|
||||
data.from=”1”;
|
||||
id=DB.Insert(data);//写入MySQL数据库
|
||||
NoSQL.Add(id,data);//以写入MySQL产生的自增id为主键写入NoSQL数据库
|
||||
|
||||
如果有数据一致性要求,可以像如下的方式使用
|
||||
|
||||
//写入数据的示例伪代码
|
||||
//data为我们要存储的数据对象
|
||||
bool status=false;
|
||||
DB.startTransaction();//开始事务
|
||||
id=DB.Insert(data);//写入MySQL数据库
|
||||
if(id>0){
|
||||
status=NoSQL.Add(id,data);//以写入MySQL产生的自增id为主键写入NoSQL数据库
|
||||
}
|
||||
if(id>0 && status==true){
|
||||
DB.commit();//提交事务
|
||||
}else{
|
||||
DB.rollback();//不成功,进行回滚
|
||||
}
|
||||
|
||||
上面的代码看起来可能觉得有点麻烦,但是只需要在DB类或者ORM层做一个统一的封装,就能实现重用了,其他代码都不用做任何的修改。
|
||||
|
||||
这种架构**在原有基于MySQL数据库的架构上增加了一层辅助的NoSQL存储**,代码量不大,技术难度小,却在可扩展性和性能上起到了非常大的作用。只需要程序在写入MySQL数据库后,同时写入到NoSQL数据库,让MySQL和NoSQL拥有相同的镜像数据,在某些可以根据主键查询的地方,使用高效的NoSQL数据库查询,这样就节省了MySQL的查询,用NoSQL的高性能来抵挡这些查询。
|
||||
{{./image2.JPG}}
|
||||
图 2 -NoSQL为镜像(同步模式)
|
||||
|
||||
这种不通过程序代码,而是通过MySQL**把数据同步到NoSQL**中,这种模式是上面一种的变体,是一种对**写入透明**但是具有更高技术难度一种模式。这种模式适用于现有的比较复杂的老系统,通过修改代码不易实现,可能引起新的问题。同时也适用于需要把数据同步到多种类型的存储中。
|
||||
|
||||
MySQL到NoSQL同步的实现可以使用**MySQL UDF**函数,MySQL binlog的解析来实现。可以利用现有的开源项目来实现,比如:
|
||||
|
||||
MySQL memcached UDFs:从通过UDF操作Memcached协议。
|
||||
国内张宴开源的mysql-udf-http:通过UDF操作http协议。
|
||||
|
||||
有了这两个MySQL UDF函数库,我们就能通过MySQL透明的处理Memcached或者Http协议,这样只要有兼容Memcached或者Http协议的NoSQL数据库,那么我们就能通过MySQL去操作以进行同步数据。再结合lib_mysqludf_json,通过UDF和MySQL触发器功能的结合,就可以实现数据的自动同步。
|
||||
|
||||
===== (二)MySQL和NoSQL组合 =====
|
||||
|
||||
MySQL中只存储需要查询的**小字段**,NoSQL存储所有数据。
|
||||
{{./image3.JPG}}
|
||||
图 3 -MySQL和NoSQL组合
|
||||
|
||||
//写入数据的示例伪代码
|
||||
|
||||
//data为我们要存储的数据对象
|
||||
data.title=”title”;
|
||||
data.name=”name”;
|
||||
data.time=”2009-12-01 10:10:01”;
|
||||
data.from=”1”;
|
||||
bool status=false;
|
||||
DB.startTransaction();//开始事务
|
||||
id=DB.Insert(“INSERT INTO table (from) VALUES(data.from)”);//写入MySQL数据库,只写from需要where查询的字段
|
||||
if(id>0){
|
||||
status=NoSQL.Add(id,data);//以写入MySQL产生的自增id为主键写入NoSQL数据库
|
||||
}
|
||||
if(id>0 && status==true){
|
||||
DB.commit();//提交事务
|
||||
}else{
|
||||
DB.rollback();//不成功,进行回滚
|
||||
}
|
||||
|
||||
把需要查询的字段,一般都是数字,时间等类型的**小字段存储于MySQL中**,根据查询建立相应的索引,其他不需要的字段,包括大文本字段都存储在NoSQL中。在查询的时候,我们先从MySQL中查询出数据的主键,然后从NoSQL中直接取出对应的数据即可。
|
||||
|
||||
这种架构模式把MySQL和NoSQL的作用进行了融合,各司其职,让MySQL专门负责处理擅长的关系存储,NoSQL作为数据的存储。它有以下优点:
|
||||
|
||||
* 节省MySQL的IO开销。由于MySQL只存储需要查询的小字段,不再负责存储大文本字段,这样就可以节省MySQL存储的空间开销,从而节省MySQL的磁盘IO。我们曾经通过这种优化,把MySQL一个40G的表缩减到几百M。
|
||||
* 提高MySQl Query Cache缓存命中率。我们知道query cache缓存失效是**表级**的,在MySQL表一旦被更新就会失效,经过这种字段的分离,更新的字段如果不是存储在MySQL中,那么对query cache就没有任何影响。而NoSQL的Cache往往都是行级别的,只对更新的记录的缓存失效。
|
||||
* 提升MySQL主从同步效率。由于MySQL存储空间的减小,同步的数据记录也减小了,而部分数据的更新落在NoSQL而不是MySQL,这样也减少了MySQL数据需要同步的次数。
|
||||
* 提高MySQL数据备份和恢复的速度。由于MySQL数据库存储的数据的减小,很容易看到数据备份和恢复的速度也将极大的提高。
|
||||
* 比以前更容易扩展。NoSQL天生就容易扩展。经过这种优化,MySQL性能也得到提高。
|
||||
|
||||
比如手机凤凰网就是这种架构 http://www.cnblogs.com/sunli/archive/2010/12/20/imcp.html
|
||||
|
||||
===== 总结 =====
|
||||
|
||||
以NoSQL为辅的架构还是以MySQL架构的思想为中心,只是在以前的架构上辅助增加了NoSQL来提高其性能和可扩展性。这种架构实现起来比较容易,却能取得不错的效果。如果正想在项目中引入NoSQL,或者你的以MySQL架构的系统目前正出现相关的瓶颈,希望本文可以为你带来帮助。
|
||||
BIN
Zim/NonSQL/NoSQL架构实践(1)/image1.JPG
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
Zim/NonSQL/NoSQL架构实践(1)/image2.JPG
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
Zim/NonSQL/NoSQL架构实践(1)/image3.JPG
Normal file
|
After Width: | Height: | Size: 12 KiB |
98
Zim/NonSQL/NoSQL架构实践.txt
Normal file
@@ -0,0 +1,98 @@
|
||||
Content-Type: text/x-zim-wiki
|
||||
Wiki-Format: zim 0.4
|
||||
Creation-Date: 2011-06-14T21:05:19+08:00
|
||||
|
||||
====== NoSQL架构实践 ======
|
||||
Created 星期二 14 六月 2011
|
||||
|
||||
前面《为什么要使用NoSQL》和《关系数据库还是NoSQL数据库》两篇从大体上介绍了为什么要用NoSQL,何时该用NoSQL。经常有朋友遇到困惑,看到NoSQL的介绍,觉得很好,但是却不知道如何正式用到自己的项目中。很大的原因就是思维固定在MySQL中了,他们问得最多的问题就是用了NoSQL,我如何做关系查询。那么接下来,我们看下怎么样在我们的系统中使用NoSQL。
|
||||
|
||||
怎么样把NoSQL引入到我们的系统架构设计中,需要根据我们**系统的业务场景来分析**,什么样类型的数据适合存储在NoSQL数据库中,什么样类型的数据必须使用关系数据库存储。明确引入的NoSQL数据库带给系统的作用,它能解决什么问题,以及可能带来的新的问题。下面我们分析几种常见的NoSQL架构。
|
||||
|
||||
===== (一)NoSQL作为镜像 =====
|
||||
|
||||
不改变原有的以MySQL作为存储的架构,使用NoSQL作为辅助镜像存储,用NoSQL的优势辅助提升性能。
|
||||
{{./image1.JPG}}
|
||||
图 1 -NoSQL为镜像(代码完成模式 )
|
||||
|
||||
//写入数据的示例伪代码
|
||||
|
||||
//data为我们要存储的数据对象
|
||||
data.title=”title”;
|
||||
data.name=”name”;
|
||||
data.time=”2009-12-01 10:10:01”;
|
||||
data.from=”1”;
|
||||
id=DB.Insert(data);//写入MySQL数据库
|
||||
NoSQL.Add(id,data);//以写入MySQL产生的自增id为主键写入NoSQL数据库
|
||||
|
||||
如果有数据一致性要求,可以像如下的方式使用
|
||||
|
||||
//写入数据的示例伪代码
|
||||
//data为我们要存储的数据对象
|
||||
bool status=false;
|
||||
DB.startTransaction();//开始事务
|
||||
id=DB.Insert(data);//写入MySQL数据库
|
||||
if(id>0){
|
||||
status=NoSQL.Add(id,data);//以写入MySQL产生的自增id为主键写入NoSQL数据库
|
||||
}
|
||||
if(id>0 && status==true){
|
||||
DB.commit();//提交事务
|
||||
}else{
|
||||
DB.rollback();//不成功,进行回滚
|
||||
}
|
||||
|
||||
上面的代码看起来可能觉得有点麻烦,但是只需要在DB类或者ORM层做一个统一的封装,就能实现重用了,其他代码都不用做任何的修改。
|
||||
|
||||
这种架构**在原有基于MySQL数据库的架构上增加了一层辅助的NoSQL存储**,代码量不大,技术难度小,却在可扩展性和性能上起到了非常大的作用。只需要程序在写入MySQL数据库后,同时写入到NoSQL数据库,让MySQL和NoSQL拥有相同的镜像数据,在某些可以根据主键查询的地方,使用高效的NoSQL数据库查询,这样就节省了MySQL的查询,用NoSQL的高性能来抵挡这些查询。
|
||||
{{./image2.JPG}}
|
||||
图 2 -NoSQL为镜像(同步模式)
|
||||
|
||||
这种不通过程序代码,而是通过MySQL**把数据同步到NoSQL**中,这种模式是上面一种的变体,是一种对**写入透明**但是具有更高技术难度一种模式。这种模式适用于现有的比较复杂的老系统,通过修改代码不易实现,可能引起新的问题。同时也适用于需要把数据同步到多种类型的存储中。
|
||||
|
||||
MySQL到NoSQL同步的实现可以使用**MySQL UDF**函数,MySQL binlog的解析来实现。可以利用现有的开源项目来实现,比如:
|
||||
|
||||
MySQL memcached UDFs:从通过UDF操作Memcached协议。
|
||||
国内张宴开源的mysql-udf-http:通过UDF操作http协议。
|
||||
|
||||
有了这两个MySQL UDF函数库,我们就能通过MySQL透明的处理Memcached或者Http协议,这样只要有兼容Memcached或者Http协议的NoSQL数据库,那么我们就能通过MySQL去操作以进行同步数据。再结合lib_mysqludf_json,通过UDF和MySQL触发器功能的结合,就可以实现数据的自动同步。
|
||||
|
||||
===== (二)MySQL和NoSQL组合 =====
|
||||
|
||||
MySQL中只存储需要查询的**小字段**,NoSQL存储所有数据。
|
||||
{{./image3.JPG}}
|
||||
图 3 -MySQL和NoSQL组合
|
||||
|
||||
//写入数据的示例伪代码
|
||||
|
||||
//data为我们要存储的数据对象
|
||||
data.title=”title”;
|
||||
data.name=”name”;
|
||||
data.time=”2009-12-01 10:10:01”;
|
||||
data.from=”1”;
|
||||
bool status=false;
|
||||
DB.startTransaction();//开始事务
|
||||
id=DB.Insert(“INSERT INTO table (from) VALUES(data.from)”);//写入MySQL数据库,只写from需要where查询的字段
|
||||
if(id>0){
|
||||
status=NoSQL.Add(id,data);//以写入MySQL产生的自增id为主键写入NoSQL数据库
|
||||
}
|
||||
if(id>0 && status==true){
|
||||
DB.commit();//提交事务
|
||||
}else{
|
||||
DB.rollback();//不成功,进行回滚
|
||||
}
|
||||
|
||||
把需要查询的字段,一般都是数字,时间等类型的**小字段存储于MySQL中**,根据查询建立相应的索引,其他不需要的字段,包括大文本字段都存储在NoSQL中。在查询的时候,我们先从MySQL中查询出数据的主键,然后从NoSQL中直接取出对应的数据即可。
|
||||
|
||||
这种架构模式把MySQL和NoSQL的作用进行了融合,各司其职,让MySQL专门负责处理擅长的关系存储,NoSQL作为数据的存储。它有以下优点:
|
||||
|
||||
* 节省MySQL的IO开销。由于MySQL只存储需要查询的小字段,不再负责存储大文本字段,这样就可以节省MySQL存储的空间开销,从而节省MySQL的磁盘IO。我们曾经通过这种优化,把MySQL一个40G的表缩减到几百M。
|
||||
* 提高MySQl Query Cache缓存命中率。我们知道query cache缓存失效是**表级**的,在MySQL表一旦被更新就会失效,经过这种字段的分离,更新的字段如果不是存储在MySQL中,那么对query cache就没有任何影响。而NoSQL的Cache往往都是行级别的,只对更新的记录的缓存失效。
|
||||
* 提升MySQL主从同步效率。由于MySQL存储空间的减小,同步的数据记录也减小了,而部分数据的更新落在NoSQL而不是MySQL,这样也减少了MySQL数据需要同步的次数。
|
||||
* 提高MySQL数据备份和恢复的速度。由于MySQL数据库存储的数据的减小,很容易看到数据备份和恢复的速度也将极大的提高。
|
||||
* 比以前更容易扩展。NoSQL天生就容易扩展。经过这种优化,MySQL性能也得到提高。
|
||||
|
||||
比如手机凤凰网就是这种架构 http://www.cnblogs.com/sunli/archive/2010/12/20/imcp.html
|
||||
|
||||
===== 总结 =====
|
||||
|
||||
以NoSQL为辅的架构还是以MySQL架构的思想为中心,只是在以前的架构上辅助增加了NoSQL来提高其性能和可扩展性。这种架构实现起来比较容易,却能取得不错的效果。如果正想在项目中引入NoSQL,或者你的以MySQL架构的系统目前正出现相关的瓶颈,希望本文可以为你带来帮助。
|
||||
BIN
Zim/NonSQL/NoSQL架构实践/image1.JPG
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
Zim/NonSQL/NoSQL架构实践/image2.JPG
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
Zim/NonSQL/NoSQL架构实践/image3.JPG
Normal file
|
After Width: | Height: | Size: 12 KiB |
76
Zim/NonSQL/NoSQL架构实践(2).txt
Normal file
@@ -0,0 +1,76 @@
|
||||
Content-Type: text/x-zim-wiki
|
||||
Wiki-Format: zim 0.4
|
||||
Creation-Date: 2011-06-14T21:43:26+08:00
|
||||
|
||||
====== NoSQL架构实践(2) ======
|
||||
Created 星期二 14 六月 2011
|
||||
|
||||
===== (三)纯NoSQL架构 =====
|
||||
只使用NoSQL作为数据存储。
|
||||
{{./image1.jpg}}
|
||||
图 4-纯NoSQL架构
|
||||
在一些数据结构、查询关系非常简单的系统中,我们可以只使用NoSQL即可以解决**存储问题**。这样不但可以**提高性能**,还非常**易于扩展**。手机凤凰网的前端展示系统就使用了这种方案。
|
||||
__在一些数据库结构经常变化,数据结构不定的系统中,就非常适合使用NoSQL来存储__。比如监控系统中的监控信息的存储,可能每种类型的监控信息都不太一样。这样可以避免经常对MySQL进行表结构调整,增加字段带来的性能问题。
|
||||
这种架构的缺点就是数据直接存储在NoSQL中,不能做关系数据库的**复杂查询**,如果由于需求变更,需要进行某些查询,可能无法满足,所以采用这种架构的时候需要确认未来是否会进行复杂关系查询以及如何应对。
|
||||
|
||||
非常幸运的是,有些NoSQL数据库已经具有部分关系数据库的**关系查询特性**,他们的功能介于key-value和关系数据库之间,却具有key-value数据库的性能,基本能满足绝大部分web 2.0网站的查询需求。比如:
|
||||
MongoDB就带有关系查询的功能,能解决常用的关系查询,所以也是一种非常不错的选择。下面是一些MongoDB的资料:
|
||||
|
||||
《视觉中国的NoSQL之路:从MySQL到MongoDB》
|
||||
《Choosing a non-relational database; why we migrated from MySQL to MongoDB》
|
||||
最近的一次Mongo Beijing 开发者聚会也有一部分资料。
|
||||
|
||||
虽然Foursquare使用MongoDB的宕机事件的出现使人对MongoDB的自动Shard提出了质疑,但是毫无疑问,MongoDB在NoSQL中,是一个优秀的数据库,其单机性能和功能确实是非常吸引人的。由于上面的例子有详细的介绍,本文就不做MongoDB的使用介绍。
|
||||
|
||||
Tokyo Tyrant数据库带有一个名为**table的存储类型**,可以对存储的数据进行关系查询和检索。一个table库类似于MySQL中的一个表。下面我们看一个小演示:
|
||||
我们要存储一批用户信息,用户信息包含用户名(name),年龄(age),email,最后访问时间(lastvisit),地区(area)。下面为写入的演示代码:
|
||||
<?php
|
||||
$tt = new TokyoTyrantTable ( "127.0.0.1", 1978 );
|
||||
$tt->vanish ();//清空
|
||||
$id = $tt->genUid ();//获取一个自增id
|
||||
//put方法提供数据写入。 put ( string $key , array $columns );
|
||||
$tt->put ( $id, array ("id" => $id, "name" => "zhangsan", "age" => 27, "email" => "zhangsan@gmail.com", "lastvisit" =>strtotime ( "2011-3-5 12:30:00" ), "area" => "北京" ) );
|
||||
$id = $tt->genUid ();
|
||||
$tt->put ( $id, array ("id" => $id, "name" => "lisi", "age" => 25, "email" => "lisi@126.com", "lastvisit" => strtotime( "2011-3-3 14:40:44" ), "area" => "北京" ) );
|
||||
$id = $tt->genUid ();
|
||||
$tt->put ( $id, array ("id" => $id, "name" => "laowang", "age" => 37, "email" => "laowang@yahoo.com", "lastvisit" =>strtotime ( "2011-3-5 08:30:12" ), "area" => "成都" ) );
|
||||
$id = $tt->genUid ();
|
||||
$tt->put ( $id, array ("id" => $id, "name" => "tom", "age" => 21, "email" => "tom@hotmail.com", "lastvisit" =>strtotime ( "2010-12-10 13:12:13" ), "area" => "天津" ) );
|
||||
$id = $tt->genUid ();
|
||||
$tt->put ( $id, array ("id" => $id, "name" => "jack", "age" => 21, "email" => "jack@gmail.com", "lastvisit" =>strtotime ( "2011-02-24 20:12:55" ), "area" => "天津" ) );
|
||||
//循环打印数据库的所有数据库
|
||||
$it = $tt->getIterator ();
|
||||
foreach ( $it as $k => $v ) {
|
||||
print_r ( $v );
|
||||
}
|
||||
?>
|
||||
|
||||
比如我们需要查询年龄为21岁的所有用户:
|
||||
<?php $tt = new TokyoTyrantTable ( "127.0.0.1", 1978 );
|
||||
$query = $tt->getQuery (); //查询年龄为21岁的用户
|
||||
$query->addCond ( “age”, TokyoTyrant::RDBQC_NUMEQ, “21” );
|
||||
print_r ( $query->search () ); ?>查询所有在2011年3月5日之后登陆的用户:
|
||||
<?php $tt = new TokyoTyrantTable ( "127.0.0.1", 1978 );
|
||||
$query = $tt->getQuery ();
|
||||
$query->addCond ( “lastvisit”, TokyoTyrant::RDBQC_NUMGE, strtotime ( "2011-3-5 00:00:00" ) );
|
||||
print_r ( $query->search () ); ?>
|
||||
从上面的示例代码可以看出,使用起来是非常简单的,甚至比SQL语句还要简单。Tokyo Tyrant的表类型存储还提供了给字段建立普通索引和倒排全文索引,大大增强了其检索功能和检索的性能。所以,完全用NoSQL来构建部分系统,是完全可能的。配合部分带有关系查询功能的NoSQL,在开发上比MySQL数据库更加快速和高效。
|
||||
|
||||
===== (四)以NoSQL为数据源的架构 =====
|
||||
数据直接写入NoSQL,再通过NoSQL同步协议复制到其他存储。根据应用的逻辑来决定去相应的存储获取数据。
|
||||
{{./image2.jpg}}
|
||||
图 5 -以NoSQL为数据源
|
||||
纯NoSQL的架构虽然结构简单,易于开发,但是在应付需求的变更、稳定性和可靠性上,总是给开发人员一种风险难于控制的感觉。为了降低风险,系统的功能不局限在NoSQL的简单功能上,我们可以使用以NoSQL为数据源的架构。
|
||||
|
||||
在这种架构中,应用程序只负责把数据直接写入到NoSQL数据库就OK,然后通过NoSQL的复制协议,把NoSQL数据的每次写入,更新,删除操作都**复制到MySQL数据库中**。同 时,也可以通过复制协议把数据同步复制到全文检索实现强大的检索功能。在海量数据下面,我们也可以根据不同的规则,把数据同步复制到设计好的**分表分库**的 MySQL中。这种架构:
|
||||
|
||||
* 非常灵活。可以非常方便的在线上系统运行过程中进行数据的调整,比如调整分库分表的规则、要添加一种新的存储类型等等。
|
||||
* 操作简单。只需要写入NoSQL数据库源,应用程序就不用管了。需要增加存储类型或者调整存储规则的时候,只需要增加同步的数据存储,调整同步规则即可,无需更改应用程序的代码。
|
||||
* 性能高。数据的写入和更新直接操作NoSQL,实现了**写的高性能**。而通过同步协议,把数据复制到各种适合查询类型的存储中(按照业务逻辑区分不同的存储),能实现**查询的高性能**, 不像以前MySQL一种数据库就全包了。或者就一个表负责跟这个表相关的所有的查询,现在可以把一个表的数据复制到各种存储,让各种存储用自己的长处来对外服务。
|
||||
* 易扩展。开发人员只需要关心写入NoSQL数据库。数据的扩展可以方便的在后端由复制协议根据规则来完成。
|
||||
|
||||
这种架构需要考虑数据复制的延迟问题,这跟使用MySQL的master-salve模式的延迟问题是一样的,解决方法也一样。
|
||||
在这种以NoSQL为数据源的架构中,最核心的就是NoSQL数据库的复制功能的实现。而当前的几乎所有的NoSQL都没有提供比较易于使用的复制接口来完成这种架构,对NoSQL进行复制协议的二次开发,需要更高的技术水平,所以这种架构看起来很好,但是却不是非常容易实现的。我的开源项目PHPBuffer中有个实现TokyoTyrant复制的例子,虽然是PHP版本的,但是很容易就可以翻译成其他语言。通过这个例子的代码,可以实现从Tokyo Tyrant实时的复制数据到其他系统中。
|
||||
|
||||
===== 总结 =====
|
||||
以NoSQL为主的架构应该算是对NoSQL的一种深度应用,整个系统的架构以及代码都不是很复杂,但是却需要一定的NoSQL使用经验才行。
|
||||
BIN
Zim/NonSQL/NoSQL架构实践(2)/image1.jpg
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
Zim/NonSQL/NoSQL架构实践(2)/image2.jpg
Normal file
|
After Width: | Height: | Size: 12 KiB |
79
Zim/NonSQL/NoSQL架构实践(二)——以NoSQL为主.txt
Normal file
@@ -0,0 +1,79 @@
|
||||
Content-Type: text/x-zim-wiki
|
||||
Wiki-Format: zim 0.4
|
||||
Creation-Date: 2011-06-14T21:43:26+08:00
|
||||
|
||||
====== NoSQL架构实践(二)——以NoSQL为主 ======
|
||||
Created 星期二 14 六月 2011
|
||||
http://luanmad2009.s156.eatj.com/thread-988-1-1.html
|
||||
作者 孙立
|
||||
前面一篇《NoSQL架构实践(一)——以NoSQL为辅》主要介绍了以NoSQL为辅助的架构,这种架构实施起来比较简单,易于理解,由于其中也使用了传统的关系数据库,让开发者更容易控制NoSQL带来的风险。接下来我们继续深入下去,换另外一个角度,“以NoSQL为主”来架构系统。
|
||||
|
||||
===== (三)纯NoSQL架构 =====
|
||||
只使用NoSQL作为数据存储。
|
||||
{{./image1.jpg}}
|
||||
图 4-纯NoSQL架构
|
||||
在一些数据结构、查询关系非常简单的系统中,我们可以只使用NoSQL即可以解决**存储问题**。这样不但可以**提高性能**,还非常**易于扩展**。手机凤凰网的前端展示系统就使用了这种方案。
|
||||
__在一些数据库结构经常变化,数据结构不定的系统中,就非常适合使用NoSQL来存储__。比如监控系统中的监控信息的存储,可能每种类型的监控信息都不太一样。这样可以避免经常对MySQL进行表结构调整,增加字段带来的性能问题。
|
||||
这种架构的缺点就是数据直接存储在NoSQL中,不能做关系数据库的**复杂查询**,如果由于需求变更,需要进行某些查询,可能无法满足,所以采用这种架构的时候需要确认未来是否会进行复杂关系查询以及如何应对。
|
||||
|
||||
非常幸运的是,有些NoSQL数据库已经具有部分关系数据库的**关系查询特性**,他们的功能介于key-value和关系数据库之间,却具有key-value数据库的性能,基本能满足绝大部分web 2.0网站的查询需求。比如:
|
||||
MongoDB就带有关系查询的功能,能解决常用的关系查询,所以也是一种非常不错的选择。下面是一些MongoDB的资料:
|
||||
|
||||
《视觉中国的NoSQL之路:从MySQL到MongoDB》
|
||||
《Choosing a non-relational database; why we migrated from MySQL to MongoDB》
|
||||
最近的一次Mongo Beijing 开发者聚会也有一部分资料。
|
||||
|
||||
虽然Foursquare使用MongoDB的宕机事件的出现使人对MongoDB的自动Shard提出了质疑,但是毫无疑问,MongoDB在NoSQL中,是一个优秀的数据库,其单机性能和功能确实是非常吸引人的。由于上面的例子有详细的介绍,本文就不做MongoDB的使用介绍。
|
||||
|
||||
Tokyo Tyrant数据库带有一个名为**table的存储类型**,可以对存储的数据进行关系查询和检索。一个table库类似于MySQL中的一个表。下面我们看一个小演示:
|
||||
我们要存储一批用户信息,用户信息包含用户名(name),年龄(age),email,最后访问时间(lastvisit),地区(area)。下面为写入的演示代码:
|
||||
<?php
|
||||
$tt = new TokyoTyrantTable ( "127.0.0.1", 1978 );
|
||||
$tt->vanish ();//清空
|
||||
$id = $tt->genUid ();//获取一个自增id
|
||||
//put方法提供数据写入。 put ( string $key , array $columns );
|
||||
$tt->put ( $id, array ("id" => $id, "name" => "zhangsan", "age" => 27, "email" => "zhangsan@gmail.com", "lastvisit" =>strtotime ( "2011-3-5 12:30:00" ), "area" => "北京" ) );
|
||||
$id = $tt->genUid ();
|
||||
$tt->put ( $id, array ("id" => $id, "name" => "lisi", "age" => 25, "email" => "lisi@126.com", "lastvisit" => strtotime( "2011-3-3 14:40:44" ), "area" => "北京" ) );
|
||||
$id = $tt->genUid ();
|
||||
$tt->put ( $id, array ("id" => $id, "name" => "laowang", "age" => 37, "email" => "laowang@yahoo.com", "lastvisit" =>strtotime ( "2011-3-5 08:30:12" ), "area" => "成都" ) );
|
||||
$id = $tt->genUid ();
|
||||
$tt->put ( $id, array ("id" => $id, "name" => "tom", "age" => 21, "email" => "tom@hotmail.com", "lastvisit" =>strtotime ( "2010-12-10 13:12:13" ), "area" => "天津" ) );
|
||||
$id = $tt->genUid ();
|
||||
$tt->put ( $id, array ("id" => $id, "name" => "jack", "age" => 21, "email" => "jack@gmail.com", "lastvisit" =>strtotime ( "2011-02-24 20:12:55" ), "area" => "天津" ) );
|
||||
//循环打印数据库的所有数据库
|
||||
$it = $tt->getIterator ();
|
||||
foreach ( $it as $k => $v ) {
|
||||
print_r ( $v );
|
||||
}
|
||||
?>
|
||||
|
||||
比如我们需要查询年龄为21岁的所有用户:
|
||||
<?php $tt = new TokyoTyrantTable ( "127.0.0.1", 1978 );
|
||||
$query = $tt->getQuery (); //查询年龄为21岁的用户
|
||||
$query->addCond ( “age”, TokyoTyrant::RDBQC_NUMEQ, “21” );
|
||||
print_r ( $query->search () ); ?>查询所有在2011年3月5日之后登陆的用户:
|
||||
<?php $tt = new TokyoTyrantTable ( "127.0.0.1", 1978 );
|
||||
$query = $tt->getQuery ();
|
||||
$query->addCond ( “lastvisit”, TokyoTyrant::RDBQC_NUMGE, strtotime ( "2011-3-5 00:00:00" ) );
|
||||
print_r ( $query->search () ); ?>
|
||||
从上面的示例代码可以看出,使用起来是非常简单的,甚至比SQL语句还要简单。Tokyo Tyrant的表类型存储还提供了给字段建立普通索引和倒排全文索引,大大增强了其检索功能和检索的性能。所以,完全用NoSQL来构建部分系统,是完全可能的。配合部分带有关系查询功能的NoSQL,在开发上比MySQL数据库更加快速和高效。
|
||||
|
||||
===== (四)以NoSQL为数据源的架构 =====
|
||||
数据直接写入NoSQL,再通过NoSQL同步协议复制到其他存储。根据应用的逻辑来决定去相应的存储获取数据。
|
||||
{{./image2.jpg}}
|
||||
图 5 -以NoSQL为数据源
|
||||
纯NoSQL的架构虽然结构简单,易于开发,但是在应付需求的变更、稳定性和可靠性上,总是给开发人员一种风险难于控制的感觉。为了降低风险,系统的功能不局限在NoSQL的简单功能上,我们可以使用以NoSQL为数据源的架构。
|
||||
|
||||
在这种架构中,应用程序只负责把数据直接写入到NoSQL数据库就OK,然后通过NoSQL的复制协议,把NoSQL数据的每次写入,更新,删除操作都**复制到MySQL数据库中**。同 时,也可以通过复制协议把数据同步复制到全文检索实现强大的检索功能。在海量数据下面,我们也可以根据不同的规则,把数据同步复制到设计好的**分表分库**的 MySQL中。这种架构:
|
||||
|
||||
* 非常灵活。可以非常方便的在线上系统运行过程中进行数据的调整,比如调整分库分表的规则、要添加一种新的存储类型等等。
|
||||
* 操作简单。只需要写入NoSQL数据库源,应用程序就不用管了。需要增加存储类型或者调整存储规则的时候,只需要增加同步的数据存储,调整同步规则即可,无需更改应用程序的代码。
|
||||
* 性能高。数据的写入和更新直接操作NoSQL,实现了**写的高性能**。而通过同步协议,把数据复制到各种适合查询类型的存储中(按照业务逻辑区分不同的存储),能实现**查询的高性能**, 不像以前MySQL一种数据库就全包了。或者就一个表负责跟这个表相关的所有的查询,现在可以把一个表的数据复制到各种存储,让各种存储用自己的长处来对外服务。
|
||||
* 易扩展。开发人员只需要关心写入NoSQL数据库。数据的扩展可以方便的在后端由复制协议根据规则来完成。
|
||||
|
||||
这种架构需要考虑数据复制的延迟问题,这跟使用MySQL的master-salve模式的延迟问题是一样的,解决方法也一样。
|
||||
在这种以NoSQL为数据源的架构中,最核心的就是NoSQL数据库的复制功能的实现。而当前的几乎所有的NoSQL都没有提供比较易于使用的复制接口来完成这种架构,对NoSQL进行复制协议的二次开发,需要更高的技术水平,所以这种架构看起来很好,但是却不是非常容易实现的。我的开源项目PHPBuffer中有个实现TokyoTyrant复制的例子,虽然是PHP版本的,但是很容易就可以翻译成其他语言。通过这个例子的代码,可以实现从Tokyo Tyrant实时的复制数据到其他系统中。
|
||||
|
||||
===== 总结 =====
|
||||
以NoSQL为主的架构应该算是对NoSQL的一种深度应用,整个系统的架构以及代码都不是很复杂,但是却需要一定的NoSQL使用经验才行。
|
||||
BIN
Zim/NonSQL/NoSQL架构实践(二)——以NoSQL为主/image1.jpg
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
Zim/NonSQL/NoSQL架构实践(二)——以NoSQL为主/image2.jpg
Normal file
|
After Width: | Height: | Size: 12 KiB |
102
Zim/NonSQL/为什么要用非关系数据库?.txt
Normal file
@@ -0,0 +1,102 @@
|
||||
Content-Type: text/x-zim-wiki
|
||||
Wiki-Format: zim 0.4
|
||||
Creation-Date: 2011-06-14T22:12:10+08:00
|
||||
|
||||
====== 为什么要用非关系数据库? ======
|
||||
Created 星期二 14 六月 2011
|
||||
|
||||
随着互联网web2.0网站的兴起,非关系型的数据库现在成了一个极其热门的新领域,非关系数据库产品的发展非常迅速。而传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,例如:
|
||||
|
||||
1、High performance - 对数据库高并发读写的需求
|
||||
web2.0网站要根据用户个性化信息来实时生成动态页面和提供动态信息,所以基本上无法使用动态页面静态化技术,因此数据库并发负载非常高,往往要达到每秒上万次读写请求。关系数据库应付上万次SQL查询还勉强顶得住,但是应付上万次SQL写数据请求,硬盘IO就已经无法承受了。其实对于普通的BBS网站,往往也存在对高并发写请求的需求,例如像JavaEye网站的实时统计在线用户状态,记录热门帖子的点击次数,投票计数等,因此这是一个相当普遍的需求。
|
||||
|
||||
2、Huge Storage - 对海量数据的高效率存储和访问的需求
|
||||
类似Facebook,twitter,Friendfeed这样的SNS网站,每天用户产生海量的用户动态,以Friendfeed为例,一个月就达到了2.5亿条用户动态,对于关系数据库来说,在一张2.5亿条记录的表里面进行SQL查询,效率是极其低下乃至不可忍受的。再例如大型web网站的用户登录系统,例如腾讯,盛大,动辄数以亿计的帐号,关系数据库也很难应付。
|
||||
|
||||
3、High Scalability && High Availability- 对数据库的高可扩展性和高可用性的需求
|
||||
在基于web的架构当中,数据库是最难进行横向扩展的,当一个应用系统的用户量和访问量与日俱增的时候,你的数据库却没有办法像web server和app server那样简单的通过添加更多的硬件和服务节点来扩展性能和负载能力。对于很多需要提供24小时不间断服务的网站来说,对数据库系统进行升级和扩展是非常痛苦的事情,往往需要停机维护和数据迁移,为什么数据库不能通过不断的添加服务器节点来实现扩展呢?
|
||||
|
||||
在上面提到的“三高”需求面前,关系数据库遇到了难以克服的障碍,而对于web2.0网站来说,关系数据库的很多主要特性却往往无用武之地,例如:
|
||||
|
||||
1、数据库事务一致性需求
|
||||
很多web实时系统并不要求严格的数据库事务,对读一致性的要求很低,有些场合对写一致性要求也不高。因此数据库事务管理成了数据库高负载下一个沉重的负担。
|
||||
|
||||
2、数据库的写实时性和读实时性需求
|
||||
对关系数据库来说,插入一条数据之后立刻查询,是肯定可以读出来这条数据的,但是对于很多web应用来说,并不要求这么高的实时性,比方说我(JavaEye的robbin)发一条消息之后,过几秒乃至十几秒之后,我的订阅者才看到这条动态是完全可以接受的。
|
||||
|
||||
3、对复杂的SQL查询,特别是多表关联查询的需求
|
||||
任何大数据量的web系统,都非常忌讳多个大表的关联查询,以及复杂的数据分析类型的复杂SQL报表查询,特别是SNS类型的网站,从需求以及产品设计角度,就避免了这种情况的产生。往往更多的只是单表的主键查询,以及单表的简单条件分页查询,SQL的功能被极大的弱化了。
|
||||
|
||||
因此,关系数据库在这些越来越多的应用场景下显得不那么合适了,为了解决这类问题的非关系数据库应运而生,现在这两年,各种各样非关系数据库,特别是键值数据库(Key-Value Store DB)风起云涌,多得让人眼花缭乱。前不久国外刚刚举办了NoSQL Conference,各路NoSQL数据库纷纷亮相,加上未亮相但是名声在外的,起码有超过10个开源的NoSQLDB,例如:
|
||||
|
||||
Redis,Tokyo Cabinet,Cassandra,Voldemort,MongoDB,Dynomite,HBase,CouchDB,Hypertable, Riak,Tin, Flare, Lightcloud, KiokuDB,Scalaris, Kai, ThruDB, ......
|
||||
|
||||
这些NoSQL数据库,有的是用C/C++编写的,有的是用Java编写的,还有的是用Erlang编写的,每个都有自己的独到之处,看都看不过来了,我(robbin)也只能从中挑选一些比较有特色,看起来更有前景的产品学习和了解一下。这些NoSQL数据库大致可以分为以下的三类:
|
||||
|
||||
一、满足极高读写性能需求的Kye-Value数据库:Redis,Tokyo Cabinet, Flare
|
||||
|
||||
高性能Key-Value数据库的主要特点就是具有极高的并发读写性能,Redis,Tokyo Cabinet, Flare,这3个Key-Value DB都是用C编写的,他们的性能都相当出色,但出了出色的性能,他们还有自己独特的功能:
|
||||
|
||||
1、Redis
|
||||
Redis是一个很新的项目,刚刚发布了1.0版本。Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过10万次读写操作,是我知道的性能最快的Key-Value DB。
|
||||
|
||||
Redis的出色之处不仅仅是性能,Redis最大的魅力是支持保存List链表和Set集合的数据结构,而且还支持对List进行各种操作,例如从List两端push和pop数据,取List区间,排序等等,对Set支持各种集合的并集交集操作,此外单个value的最大限制是1GB,不像memcached只能保存1MB的数据,因此Redis可以用来实现很多有用的功能,比方说用他的List来做FIFO双向链表,实现一个轻量级的高性能消息队列服务,用他的Set可以做高性能的tag系统等等。另外Redis也可以对存入的Key-Value设置expire时间,因此也可以被当作一个功能加强版的memcached来用。
|
||||
|
||||
Redis的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,并且它没有原生的可扩展机制,不具有scale(可扩展)能力,要依赖客户端来实现分布式读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。目前使用Redis的网站有github,Engine Yard。
|
||||
|
||||
2、Tokyo Cabinet和Tokoy Tyrant
|
||||
TC和TT的开发者是日本人Mikio Hirabayashi,主要被用在日本最大的SNS网站mixi.jp上,TC发展的时间最早,现在已经是一个非常成熟的项目,也是Kye-Value数据库领域最大的热点,现在被广泛的应用在很多很多网站上。TC是一个高性能的存储引擎,而TT提供了多线程高并发服务器,性能也非常出色,每秒可以处理4-5万次读写操作。
|
||||
|
||||
TC除了支持Key-Value存储之外,还支持保存Hashtable数据类型,因此很像一个简单的数据库表,并且还支持基于column的条件查询,分页查询和排序功能,基本上相当于支持单表的基础查询功能了,所以可以简单的替代关系数据库的很多操作,这也是TC受到大家欢迎的主要原因之一,有一个Ruby的项目miyazakiresistance将TT的hashtable的操作封装成和ActiveRecord一样的操作,用起来非常爽。
|
||||
|
||||
TC/TT在mixi的实际应用当中,存储了2000万条以上的数据,同时支撑了上万个并发连接,是一个久经考验的项目。TC在保证了极高的并发读写性能的同时,具有可靠的数据持久化机制,同时还支持类似关系数据库表结构的hashtable以及简单的条件,分页和排序操作,是一个很棒的NoSQL数据库。
|
||||
|
||||
TC的主要缺点是在数据量达到上亿级别以后,并发写数据性能会大幅度下降,NoSQL: If Only It Was That Easy提到,他们发现在TC里面插入1.6亿条2-20KB数据的时候,写入性能开始急剧下降。看来是当数据量上亿条的时候,TC性能开始大幅度下降,从TC作者自己提供的mixi数据来看,至少上千万条数据量的时候还没有遇到这么明显的写入性能瓶颈。
|
||||
|
||||
这个是Tim Yang做的一个Memcached,Redis和Tokyo Tyrant的简单的性能评测,仅供参考
|
||||
|
||||
3、Flare
|
||||
TC是日本第一大SNS网站mixi开发的,而Flare是日本第二大SNS网站green.jp开发的,有意思吧。Flare简单的说就是给TC添加了scale功能。他替换掉了TT部分,自己另外给TC写了网络服务器,Flare的主要特点就是支持scale能力,他在网络服务端之前添加了一个node server,来管理后端的多个服务器节点,因此可以动态添加数据库服务节点,删除服务器节点,也支持failover。如果你的使用场景必须要让TC可以scale,那么可以考虑flare。
|
||||
|
||||
flare唯一的缺点就是他只支持memcached协议,因此当你使用flare的时候,就不能使用TC的table数据结构了,只能使用TC的key-value数据结构存储。
|
||||
|
||||
二、满足海量存储需求和访问的面向文档的数据库:MongoDB,CouchDB
|
||||
|
||||
面向文档的非关系数据库主要解决的问题不是高性能的并发读写,而是保证海量数据存储的同时,具有良好的查询性能。MongoDB是用C++开发的,而CouchDB则是Erlang开发的:
|
||||
|
||||
1、MongoDB
|
||||
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bjson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
|
||||
|
||||
Mongo主要解决的是海量数据的访问效率问题,根据官方的文档,当数据量达到50GB以上的时候,Mongo的数据库访问速度是MySQL的10倍以上。Mongo的并发读写效率不是特别出色,根据官方提供的性能测试表明,大约每秒可以处理0.5万-1.5次读写请求。对于Mongo的并发读写性能,我(robbin)也打算有空的时候好好测试一下。
|
||||
|
||||
因为Mongo主要是支持海量数据存储的,所以Mongo还自带了一个出色的分布式文件系统GridFS,可以支持海量的数据存储,但我也看到有些评论认为GridFS性能不佳,这一点还是有待亲自做点测试来验证了。
|
||||
|
||||
最后由于Mongo可以支持复杂的数据结构,而且带有强大的数据查询功能,因此非常受到欢迎,很多项目都考虑用MongoDB来替代MySQL来实现不是特别复杂的Web应用,比方说why we migrated from MySQL to MongoDB就是一个真实的从MySQL迁移到MongoDB的案例,由于数据量实在太大,所以迁移到了Mongo上面,数据查询的速度得到了非常显著的提升。
|
||||
|
||||
MongoDB也有一个ruby的项目MongoMapper,是模仿Merb的DataMapper编写的MongoDB的接口,使用起来非常简单,几乎和DataMapper一模一样,功能非常强大易用。
|
||||
|
||||
2、CouchDB
|
||||
CouchDB现在是一个非常有名气的项目,似乎不用多介绍了。但是我却对CouchDB没有什么兴趣,主要是因为CouchDB仅仅提供了基于HTTP REST的接口,因此CouchDB单纯从并发读写性能来说,是非常糟糕的,这让我立刻抛弃了对CouchDB的兴趣。
|
||||
|
||||
三、满足高可扩展性和可用性的面向分布式计算的数据库:Cassandra,Voldemort
|
||||
|
||||
面向scale能力的数据库其实主要解决的问题领域和上述两类数据库还不太一样,它首先必须是一个分布式的数据库系统,由分布在不同节点上面的数据库共同构成一个数据库服务系统,并且根据这种分布式架构来提供online的,具有弹性的可扩展能力,例如可以不停机的添加更多数据节点,删除数据节点等等。因此像Cassandra常常被看成是一个开源版本的Google BigTable的替代品。Cassandra和Voldemort都是用Java开发的:
|
||||
|
||||
1、Cassandra
|
||||
Cassandra项目是Facebook在2008年开源出来的,随后Facebook自己使用Cassandra的另外一个不开源的分支,而开源出来的Cassandra主要被Amazon的Dynamite团队来维护,并且Cassandra被认为是Dynamite2.0版本。目前除了Facebook之外,twitter和digg.com都在使用Cassandra。
|
||||
|
||||
Cassandra的主要特点就是它不是一个数据库,而是由一堆数据库节点共同构成的一个分布式网络服务,对Cassandra的一个写操作,会被复制到其他节点上去,对Cassandra的读操作,也会被路由到某个节点上面去读取。对于一个Cassandra群集来说,扩展性能是比较简单的事情,只管在群集里面添加节点就可以了。我看到有文章说Facebook的Cassandra群集有超过100台服务器构成的数据库群集。
|
||||
|
||||
Cassandra也支持比较丰富的数据结构和功能强大的查询语言,和MongoDB比较类似,查询功能比MongoDB稍弱一些,twitter的平台架构部门领导Evan Weaver写了一篇文章介绍Cassandra:http://blog.evanweaver.com/articles/2009/07/06/up-and-running-with-cassandra/,有非常详细的介绍。
|
||||
|
||||
Cassandra以单个节点来衡量,其节点的并发读写性能不是特别好,有文章说评测下来Cassandra每秒大约不到1万次读写请求,我也看到一些对这个问题进行质疑的评论,但是评价Cassandra单个节点的性能是没有意义的,真实的分布式数据库访问系统必然是n多个节点构成的系统,其并发性能取决于整个系统的节点数量,路由效率,而不仅仅是单节点的并发负载能力。
|
||||
|
||||
2、Voldemort
|
||||
Voldemort是个和Cassandra类似的面向解决scale问题的分布式数据库系统,Cassandra来自于Facebook这个SNS网站,而Voldemort则来自于Linkedin这个SNS网站。说起来SNS网站为我们贡献了n多的NoSQL数据库,例如Cassandar,Voldemort,Tokyo Cabinet,Flare等等。Voldemort的资料不是很多,因此我没有特别仔细去钻研,Voldemort官方给出Voldemort的并发读写性能也很不错,每秒超过了1.5万次读写。
|
||||
|
||||
从Facebook开发Cassandra,Linkedin开发Voldemort,我们也可以大致看出国外大型SNS网站对于分布式数据库,特别是对数据库的scale能力方面的需求是多么殷切。前面我(robbin)提到,web应用的架构当中,web层和app层相对来说都很容易横向扩展,唯有数据库是单点的,极难scale,现在Facebook和Linkedin在非关系型数据库的分布式方面探索了一条很好的方向,这也是为什么现在Cassandra这么热门的主要原因。
|
||||
|
||||
如今,NoSQL数据库是个令人很兴奋的领域,总是不断有新的技术新的产品冒出来,改变我们已经形成的固有的技术观念,我自己(robbin)稍微了解了一些,就感觉自己深深的沉迷进去了,可以说NoSQL数据库领域也是博大精深的,我(robbin)也只能浅尝辄止,我(robbin)写这篇文章既是自己一点点钻研心得,也是抛砖引玉,希望吸引对这个领域有经验的朋友来讨论和交流。
|
||||
|
||||
从我(robbin)个人的兴趣来说,分布式数据库系统不是我能实际用到的技术,因此不打算花时间深入,而其他两个数据领域(高性能NoSQLDB和海量存储NoSQLDB)都是我很感兴趣的,特别是Redis,TT/TC和MongoDB这3个NoSQL数据库,因此我接下来将写三篇文章分别详细介绍这3个数据库。
|
||||
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
||||
102
Zim/NonSQL/主题:NoSQL数据库探讨之一_-_为什么要用非关系数据库?.txt
Normal file
@@ -0,0 +1,102 @@
|
||||
Content-Type: text/x-zim-wiki
|
||||
Wiki-Format: zim 0.4
|
||||
Creation-Date: 2011-06-14T22:12:10+08:00
|
||||
|
||||
====== 主题:NoSQL数据库探讨之一 - 为什么要用非关系数据库? ======
|
||||
Created 星期二 14 六月 2011
|
||||
http://www.iteye.com/topic/524977
|
||||
随着互联网web2.0网站的兴起,非关系型的数据库现在成了一个极其热门的新领域,非关系数据库产品的发展非常迅速。而传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,例如:
|
||||
|
||||
1、High performance - 对数据库高并发读写的需求
|
||||
web2.0网站要根据用户个性化信息来实时生成动态页面和提供动态信息,所以基本上无法使用动态页面静态化技术,因此数据库并发负载非常高,往往要达到每秒上万次读写请求。关系数据库应付上万次SQL查询还勉强顶得住,但是应付上万次SQL写数据请求,硬盘IO就已经无法承受了。其实对于普通的BBS网站,往往也存在对高并发写请求的需求,例如像JavaEye网站的实时统计在线用户状态,记录热门帖子的点击次数,投票计数等,因此这是一个相当普遍的需求。
|
||||
|
||||
2、Huge Storage - 对海量数据的高效率存储和访问的需求
|
||||
类似Facebook,twitter,Friendfeed这样的SNS网站,每天用户产生海量的用户动态,以Friendfeed为例,一个月就达到了2.5亿条用户动态,对于关系数据库来说,在一张2.5亿条记录的表里面进行SQL查询,效率是极其低下乃至不可忍受的。再例如大型web网站的用户登录系统,例如腾讯,盛大,动辄数以亿计的帐号,关系数据库也很难应付。
|
||||
|
||||
3、High Scalability && High Availability- 对数据库的高可扩展性和高可用性的需求
|
||||
在基于web的架构当中,数据库是最难进行横向扩展的,当一个应用系统的用户量和访问量与日俱增的时候,你的数据库却没有办法像web server和app server那样简单的通过添加更多的硬件和服务节点来扩展性能和负载能力。对于很多需要提供24小时不间断服务的网站来说,对数据库系统进行升级和扩展是非常痛苦的事情,往往需要停机维护和数据迁移,为什么数据库不能通过不断的添加服务器节点来实现扩展呢?
|
||||
|
||||
在上面提到的“三高”需求面前,关系数据库遇到了难以克服的障碍,而对于web2.0网站来说,关系数据库的很多主要特性却往往无用武之地,例如:
|
||||
|
||||
1、数据库事务一致性需求
|
||||
很多web实时系统并不要求严格的数据库事务,对读一致性的要求很低,有些场合对写一致性要求也不高。因此数据库事务管理成了数据库高负载下一个沉重的负担。
|
||||
|
||||
2、数据库的写实时性和读实时性需求
|
||||
对关系数据库来说,插入一条数据之后立刻查询,是肯定可以读出来这条数据的,但是对于很多web应用来说,并不要求这么高的实时性,比方说我(JavaEye的robbin)发一条消息之后,过几秒乃至十几秒之后,我的订阅者才看到这条动态是完全可以接受的。
|
||||
|
||||
3、对复杂的SQL查询,特别是多表关联查询的需求
|
||||
任何大数据量的web系统,都非常忌讳多个大表的关联查询,以及复杂的数据分析类型的复杂SQL报表查询,特别是SNS类型的网站,从需求以及产品设计角度,就避免了这种情况的产生。往往更多的只是单表的主键查询,以及单表的简单条件分页查询,SQL的功能被极大的弱化了。
|
||||
|
||||
因此,关系数据库在这些越来越多的应用场景下显得不那么合适了,为了解决这类问题的非关系数据库应运而生,现在这两年,各种各样非关系数据库,特别是键值数据库(Key-Value Store DB)风起云涌,多得让人眼花缭乱。前不久国外刚刚举办了NoSQL Conference,各路NoSQL数据库纷纷亮相,加上未亮相但是名声在外的,起码有超过10个开源的NoSQLDB,例如:
|
||||
|
||||
Redis,Tokyo Cabinet,Cassandra,Voldemort,MongoDB,Dynomite,HBase,CouchDB,Hypertable, Riak,Tin, Flare, Lightcloud, KiokuDB,Scalaris, Kai, ThruDB, ......
|
||||
|
||||
这些NoSQL数据库,有的是用C/C++编写的,有的是用Java编写的,还有的是用Erlang编写的,每个都有自己的独到之处,看都看不过来了,我(robbin)也只能从中挑选一些比较有特色,看起来更有前景的产品学习和了解一下。这些NoSQL数据库大致可以分为以下的三类:
|
||||
|
||||
一、满足极高读写性能需求的Kye-Value数据库:Redis,Tokyo Cabinet, Flare
|
||||
|
||||
高性能Key-Value数据库的主要特点就是具有极高的并发读写性能,Redis,Tokyo Cabinet, Flare,这3个Key-Value DB都是用C编写的,他们的性能都相当出色,但出了出色的性能,他们还有自己独特的功能:
|
||||
|
||||
1、Redis
|
||||
Redis是一个很新的项目,刚刚发布了1.0版本。Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过10万次读写操作,是我知道的性能最快的Key-Value DB。
|
||||
|
||||
Redis的出色之处不仅仅是性能,Redis最大的魅力是支持保存List链表和Set集合的数据结构,而且还支持对List进行各种操作,例如从List两端push和pop数据,取List区间,排序等等,对Set支持各种集合的并集交集操作,此外单个value的最大限制是1GB,不像memcached只能保存1MB的数据,因此Redis可以用来实现很多有用的功能,比方说用他的List来做FIFO双向链表,实现一个轻量级的高性能消息队列服务,用他的Set可以做高性能的tag系统等等。另外Redis也可以对存入的Key-Value设置expire时间,因此也可以被当作一个功能加强版的memcached来用。
|
||||
|
||||
Redis的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,并且它没有原生的可扩展机制,不具有scale(可扩展)能力,要依赖客户端来实现分布式读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。目前使用Redis的网站有github,Engine Yard。
|
||||
|
||||
2、Tokyo Cabinet和Tokoy Tyrant
|
||||
TC和TT的开发者是日本人Mikio Hirabayashi,主要被用在日本最大的SNS网站mixi.jp上,TC发展的时间最早,现在已经是一个非常成熟的项目,也是Kye-Value数据库领域最大的热点,现在被广泛的应用在很多很多网站上。TC是一个高性能的存储引擎,而TT提供了多线程高并发服务器,性能也非常出色,每秒可以处理4-5万次读写操作。
|
||||
|
||||
TC除了支持Key-Value存储之外,还支持保存Hashtable数据类型,因此很像一个简单的数据库表,并且还支持基于column的条件查询,分页查询和排序功能,基本上相当于支持单表的基础查询功能了,所以可以简单的替代关系数据库的很多操作,这也是TC受到大家欢迎的主要原因之一,有一个Ruby的项目miyazakiresistance将TT的hashtable的操作封装成和ActiveRecord一样的操作,用起来非常爽。
|
||||
|
||||
TC/TT在mixi的实际应用当中,存储了2000万条以上的数据,同时支撑了上万个并发连接,是一个久经考验的项目。TC在保证了极高的并发读写性能的同时,具有可靠的数据持久化机制,同时还支持类似关系数据库表结构的hashtable以及简单的条件,分页和排序操作,是一个很棒的NoSQL数据库。
|
||||
|
||||
TC的主要缺点是在数据量达到上亿级别以后,并发写数据性能会大幅度下降,NoSQL: If Only It Was That Easy提到,他们发现在TC里面插入1.6亿条2-20KB数据的时候,写入性能开始急剧下降。看来是当数据量上亿条的时候,TC性能开始大幅度下降,从TC作者自己提供的mixi数据来看,至少上千万条数据量的时候还没有遇到这么明显的写入性能瓶颈。
|
||||
|
||||
这个是Tim Yang做的一个Memcached,Redis和Tokyo Tyrant的简单的性能评测,仅供参考
|
||||
|
||||
3、Flare
|
||||
TC是日本第一大SNS网站mixi开发的,而Flare是日本第二大SNS网站green.jp开发的,有意思吧。Flare简单的说就是给TC添加了scale功能。他替换掉了TT部分,自己另外给TC写了网络服务器,Flare的主要特点就是支持scale能力,他在网络服务端之前添加了一个node server,来管理后端的多个服务器节点,因此可以动态添加数据库服务节点,删除服务器节点,也支持failover。如果你的使用场景必须要让TC可以scale,那么可以考虑flare。
|
||||
|
||||
flare唯一的缺点就是他只支持memcached协议,因此当你使用flare的时候,就不能使用TC的table数据结构了,只能使用TC的key-value数据结构存储。
|
||||
|
||||
二、满足海量存储需求和访问的面向文档的数据库:MongoDB,CouchDB
|
||||
|
||||
面向文档的非关系数据库主要解决的问题不是高性能的并发读写,而是保证海量数据存储的同时,具有良好的查询性能。MongoDB是用C++开发的,而CouchDB则是Erlang开发的:
|
||||
|
||||
1、MongoDB
|
||||
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bjson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
|
||||
|
||||
Mongo主要解决的是海量数据的访问效率问题,根据官方的文档,当数据量达到50GB以上的时候,Mongo的数据库访问速度是MySQL的10倍以上。Mongo的并发读写效率不是特别出色,根据官方提供的性能测试表明,大约每秒可以处理0.5万-1.5次读写请求。对于Mongo的并发读写性能,我(robbin)也打算有空的时候好好测试一下。
|
||||
|
||||
因为Mongo主要是支持海量数据存储的,所以Mongo还自带了一个出色的分布式文件系统GridFS,可以支持海量的数据存储,但我也看到有些评论认为GridFS性能不佳,这一点还是有待亲自做点测试来验证了。
|
||||
|
||||
最后由于Mongo可以支持复杂的数据结构,而且带有强大的数据查询功能,因此非常受到欢迎,很多项目都考虑用MongoDB来替代MySQL来实现不是特别复杂的Web应用,比方说why we migrated from MySQL to MongoDB就是一个真实的从MySQL迁移到MongoDB的案例,由于数据量实在太大,所以迁移到了Mongo上面,数据查询的速度得到了非常显著的提升。
|
||||
|
||||
MongoDB也有一个ruby的项目MongoMapper,是模仿Merb的DataMapper编写的MongoDB的接口,使用起来非常简单,几乎和DataMapper一模一样,功能非常强大易用。
|
||||
|
||||
2、CouchDB
|
||||
CouchDB现在是一个非常有名气的项目,似乎不用多介绍了。但是我却对CouchDB没有什么兴趣,主要是因为CouchDB仅仅提供了基于HTTP REST的接口,因此CouchDB单纯从并发读写性能来说,是非常糟糕的,这让我立刻抛弃了对CouchDB的兴趣。
|
||||
|
||||
三、满足高可扩展性和可用性的面向分布式计算的数据库:Cassandra,Voldemort
|
||||
|
||||
面向scale能力的数据库其实主要解决的问题领域和上述两类数据库还不太一样,它首先必须是一个分布式的数据库系统,由分布在不同节点上面的数据库共同构成一个数据库服务系统,并且根据这种分布式架构来提供online的,具有弹性的可扩展能力,例如可以不停机的添加更多数据节点,删除数据节点等等。因此像Cassandra常常被看成是一个开源版本的Google BigTable的替代品。Cassandra和Voldemort都是用Java开发的:
|
||||
|
||||
1、Cassandra
|
||||
Cassandra项目是Facebook在2008年开源出来的,随后Facebook自己使用Cassandra的另外一个不开源的分支,而开源出来的Cassandra主要被Amazon的Dynamite团队来维护,并且Cassandra被认为是Dynamite2.0版本。目前除了Facebook之外,twitter和digg.com都在使用Cassandra。
|
||||
|
||||
Cassandra的主要特点就是它不是一个数据库,而是由一堆数据库节点共同构成的一个分布式网络服务,对Cassandra的一个写操作,会被复制到其他节点上去,对Cassandra的读操作,也会被路由到某个节点上面去读取。对于一个Cassandra群集来说,扩展性能是比较简单的事情,只管在群集里面添加节点就可以了。我看到有文章说Facebook的Cassandra群集有超过100台服务器构成的数据库群集。
|
||||
|
||||
Cassandra也支持比较丰富的数据结构和功能强大的查询语言,和MongoDB比较类似,查询功能比MongoDB稍弱一些,twitter的平台架构部门领导Evan Weaver写了一篇文章介绍Cassandra:http://blog.evanweaver.com/articles/2009/07/06/up-and-running-with-cassandra/,有非常详细的介绍。
|
||||
|
||||
Cassandra以单个节点来衡量,其节点的并发读写性能不是特别好,有文章说评测下来Cassandra每秒大约不到1万次读写请求,我也看到一些对这个问题进行质疑的评论,但是评价Cassandra单个节点的性能是没有意义的,真实的分布式数据库访问系统必然是n多个节点构成的系统,其并发性能取决于整个系统的节点数量,路由效率,而不仅仅是单节点的并发负载能力。
|
||||
|
||||
2、Voldemort
|
||||
Voldemort是个和Cassandra类似的面向解决scale问题的分布式数据库系统,Cassandra来自于Facebook这个SNS网站,而Voldemort则来自于Linkedin这个SNS网站。说起来SNS网站为我们贡献了n多的NoSQL数据库,例如Cassandar,Voldemort,Tokyo Cabinet,Flare等等。Voldemort的资料不是很多,因此我没有特别仔细去钻研,Voldemort官方给出Voldemort的并发读写性能也很不错,每秒超过了1.5万次读写。
|
||||
|
||||
从Facebook开发Cassandra,Linkedin开发Voldemort,我们也可以大致看出国外大型SNS网站对于分布式数据库,特别是对数据库的scale能力方面的需求是多么殷切。前面我(robbin)提到,web应用的架构当中,web层和app层相对来说都很容易横向扩展,唯有数据库是单点的,极难scale,现在Facebook和Linkedin在非关系型数据库的分布式方面探索了一条很好的方向,这也是为什么现在Cassandra这么热门的主要原因。
|
||||
|
||||
如今,NoSQL数据库是个令人很兴奋的领域,总是不断有新的技术新的产品冒出来,改变我们已经形成的固有的技术观念,我自己(robbin)稍微了解了一些,就感觉自己深深的沉迷进去了,可以说NoSQL数据库领域也是博大精深的,我(robbin)也只能浅尝辄止,我(robbin)写这篇文章既是自己一点点钻研心得,也是抛砖引玉,希望吸引对这个领域有经验的朋友来讨论和交流。
|
||||
|
||||
从我(robbin)个人的兴趣来说,分布式数据库系统不是我能实际用到的技术,因此不打算花时间深入,而其他两个数据领域(高性能NoSQLDB和海量存储NoSQLDB)都是我很感兴趣的,特别是Redis,TT/TC和MongoDB这3个NoSQL数据库,因此我接下来将写三篇文章分别详细介绍这3个数据库。
|
||||
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
||||
118
Zim/NonSQL/关系数据库还是NoSQL数据库.txt
Normal file
@@ -0,0 +1,118 @@
|
||||
Content-Type: text/x-zim-wiki
|
||||
Wiki-Format: zim 0.4
|
||||
Creation-Date: 2011-06-14T21:05:47+08:00
|
||||
|
||||
====== 关系数据库还是NoSQL数据库 ======
|
||||
Created 星期二 14 六月 2011
|
||||
|
||||
在过去,我们只需要学习和使用一种数据库技术,就能做几乎所有的数据库应用开发。因为成熟稳定的关系数据库产品并不是很多,而供你选择的免费版本就更加少了,所以互联网领域基本上都选择了免费的MySQL数据库。在高速发展的WEB2.0时代,我们发现关系数据库在性能、扩展性、数据的快速备份和恢复、满足需求的易用性上并不总是能很好的满足我们的需要,我们越来越趋向于**根据业务场景选择合适的数据库**,以及进行多种数据库的融合运用。几年前的一篇文章《One Size Fits All - An Idea Whose Time Has Come and Gone》就已经阐述了这个观点。
|
||||
|
||||
当我们在讨论是否要使用NoSQL的时候,你还需要理解NoSQL也是分很多种类的,在NoSQL百花齐放的今天,NoSQL的**正确选择**比选择关系数据库还具有挑战性。虽然NoSQL的使用很简单,但是选择却是个麻烦事,这也正是很多人在观望的一个原因。
|
||||
NoSQL的分类
|
||||
|
||||
NoSQL仅仅是一个概念,NoSQL数据库根据数据的存储模型和特点分为很多种类。
|
||||
|
||||
类型 部分代表 特点
|
||||
|
||||
列存储 Hbase
|
||||
Cassandra
|
||||
Hypertable
|
||||
|
||||
顾名思义,是按列存储数据的。最大的特点是方便存储结构化和半结构化数据,方便做数据压缩,对针对某一列或者某几列的查询有非常大的IO优势。
|
||||
文档存储
|
||||
|
||||
MongoDB
|
||||
CouchDB
|
||||
|
||||
|
||||
文档存储一般用类似json的格式存储,存储的内容是文档型的。这样也就有有机会对某些字段建立索引,实现关系数据库的某些功能。
|
||||
|
||||
key-value存储
|
||||
|
||||
Tokyo Cabinet / Tyrant
|
||||
Berkeley DB
|
||||
MemcacheDB
|
||||
Redis
|
||||
|
||||
|
||||
可以通过key快速查询到其value。一般来说,存储不管value的格式,照单全收。(Redis包含了其他功能)
|
||||
|
||||
图存储
|
||||
|
||||
Neo4J
|
||||
FlockDB
|
||||
|
||||
图形关系的最佳存储。使用传统关系数据库来解决的话性能低下,而且设计使用不方便。
|
||||
|
||||
对象存储
|
||||
|
||||
db4o
|
||||
|
||||
Versant
|
||||
|
||||
|
||||
通过类似面向对象语言的语法操作数据库,通过对象的方式存取数据。
|
||||
|
||||
xml数据库
|
||||
|
||||
Berkeley DB XML
|
||||
|
||||
BaseX
|
||||
|
||||
|
||||
高效的存储XML数据,并支持XML的内部查询语法,比如XQuery,Xpath。
|
||||
|
||||
以上NoSQL数据库类型的划分并不是绝对,只是从**存储模型**上来进行的大体划分。它们之间没有绝对的分界,也有交差的情况,比如Tokyo Cabinet / Tyrant的Table类型存储,就可以理解为是文档型存储,Berkeley DB XML数据库是基于Berkeley DB之上开发的。
|
||||
|
||||
===== NoSQL还是关系数据库 =====
|
||||
|
||||
虽然09年出现了比较激进的文章《关系数据库已死》,但是我们心里都清楚,关系数据库其实还活得好好的,你还不能不用关系数据库。但是也说明了一个事实,关系数据库在处理WEB2.0数据的时候,的确已经出现了瓶颈。
|
||||
|
||||
那么我们到底是用NoSQL还是关系数据库呢?我想我们没有必要来进行一个绝对的回答。我们需要根据我们的**应用场景来决定我们到底用什么**。
|
||||
|
||||
如果关系数据库在你的应用场景中,完全能够很好的工作,而你又是非常善于使用和维护关系数据库的,那么我觉得你完全没有必要迁移到NoSQL上面,除非你是个喜欢折腾的人。如果你是在金融,电信等以数据为王的关键领域,目前使用的是Oracle数据库来提供高可靠性的,除非遇到特别大的瓶颈,不然也别贸然尝试NoSQL。
|
||||
|
||||
然而,在**WEB2.0**的网站中,关系数据库大部分都出现了瓶颈。在磁盘IO、数据库可扩展上都花费了开发人员相当多的精力来优化,比如做分表分库(database sharding)、主从复制、异构复制等等,然而,这些工作需要的技术能力越来越高,也越来越具有挑战性。如果你正在经历这些场合,那么我觉得你应该尝试一下NoSQL了。
|
||||
|
||||
===== 选择合适的NoSQL =====
|
||||
|
||||
如此多类型的NoSQL,而每种类型的NoSQL又有很多,到底选择什么类型的NoSQL来作为我们的存储呢?这并不是一个很好回答的问题,影响我们选择的因素有很多,而选择也可能有多种,随着业务场景,需求的变更可能选择又会变化。我们常常需要根据如下情况考虑:
|
||||
|
||||
数据结构特点。包括结构化、半结构化、字段是否可能变更、是否有大文本字段、数据字段是否可能变化。
|
||||
写入特点。包括insert比例、update比例、是否经常更新数据的某一个小字段、原子更新需求。
|
||||
查询特点。包括查询的条件、查询热点的范围。比如用户信息的查询,可能就是随机的,而新闻的查询就是按照时间,越新的越频繁。
|
||||
|
||||
===== NoSQL和关系数据库结合 =====
|
||||
|
||||
其实NoSQL数据库仅仅是关系数据库在某些方面(性能,扩展)的一个弥补,单从功能上讲,NoSQL的几乎所有的功能,在关系数据库上都能够满足,所以**选择NoSQL的原因并不在功能上**。
|
||||
|
||||
所以,我们一般会把NoSQL和关系数据库进行**结合使用**,各取所长,需要使用关系特性的时候我们使用关系数据库,需要使用NoSQL特性的时候我们使用NoSQL数据库,各得其所。
|
||||
|
||||
举个简单的例子吧,比如用户评论的存储,评论大概有主键id、评论的对象aid、评论内容content、用户uid等字段。我们能确定的是评论内容content肯定不会在数据库中用where content=’’查询,评论内容也是一个大文本字段。那么我们可以把 主键id、评论对象aid、用户id存储在数据库,**评论内容存储在NoSQL**,这样数据库就节省了存储content占用的磁盘空间,从而节省大量IO,对content也更容易做Cache。
|
||||
|
||||
//从MySQL中查询出评论主键id列表
|
||||
commentIds=DB.query("SELECT id FROM comments where aid='评论对象id' LIMIT 0,20");
|
||||
//根据主键id列表,从NoSQL取回评论实体数据
|
||||
CommentsList=NoSQL.get(commentIds);
|
||||
|
||||
===== NoSQL代替MySQL =====
|
||||
|
||||
在某些应用场合,比如一些配置的关系键值映射存储、用户名和密码的存储、Session会话存储等等,用NoSQL完全可以替代MySQL存储。不但具有更高的性能,而且开发也更加方便。
|
||||
|
||||
===== NoSQL作为缓存服务器 =====
|
||||
|
||||
MySQL+Memcached的架构中,我们处处都要精心设计我们的缓存,包括过期时间的设计、缓存的实时性设计、缓存内存大小评估、缓存命中率等等。
|
||||
|
||||
NoSQL数据库一般都具有非常高的性能,在大多数场景下面,你不必再考虑**在代码层**为NoSQL构建一层Memcached缓存。NoSQL数据本身在Cache上已经做了相当多的优化工作。
|
||||
|
||||
Memcached这类内存缓存服务器缓存的数据大小受限于内存大小,如果用NoSQL来代替Memcached来缓存数据库的话,就可以不再受限于内存大小。虽然可能有少量的磁盘IO读写,可能比Memcached慢一点,但是完全可以用来缓存数据库的查询操作。
|
||||
|
||||
===== 规避风险 =====
|
||||
|
||||
由于NoSQL是一个比较新的东西,特别是我们选择的NoSQL数据库还不是非常成熟的产品,所以我们可能会遇到未知的风险。为了得到NoSQL的好处,又要考虑规避风险,鱼与熊掌如何兼得?
|
||||
|
||||
现在业内很多公司的做法就是数据的备份。在往NoSQL里面存储数据的时候还会往MySQL里面存储一份。NoSQL数据库本身也需要进行备份(冷备和热备)。或者可以考虑使用两种NoSQL数据库,出现问题后可以进行切换(避免出现digg使用Cassandra的悲剧)。
|
||||
|
||||
===== 总结 =====
|
||||
|
||||
本文只是简单的从MySQL和NoSQL的角度分析如何选择,以及进行融合使用。其实在选择NoSQL的时候,你可能还会碰到关于CAP原则,最终一致性,BASE思想的考虑。因为使用MySQL架构的时候,你也会碰到上面的问题,所以这里没有阐述。
|
||||
101
Zim/NonSQL/视觉中国的NoSQL之路:从MySQL到MongoDB.txt
Normal file
@@ -0,0 +1,101 @@
|
||||
Content-Type: text/x-zim-wiki
|
||||
Wiki-Format: zim 0.4
|
||||
Creation-Date: 2011-06-14T21:59:24+08:00
|
||||
|
||||
====== 视觉中国的NoSQL之路:从MySQL到MongoDB ======
|
||||
Created 星期二 14 六月 2011
|
||||
http://www.programmer.com.cn/4199/
|
||||
|
||||
===== 起因 =====
|
||||
视觉中国网站(www.chinavisual.com)是国内最大的创意人群的专业网站。2009年以前,同很多公司一样,我们的CMS和社区产品都构建于PHP+Nginx+MySQL之上;MySQL使用了Master+Master的部署方案;前端使用自己的PHP框架进行开发;Memcached作为缓存;Nginx进行Web服务和负载均衡;Gearman进行异步任务处理。在传统的基于静态内容(如文章,资讯,帖子)的产品,这个体系运行良好。通过分级的缓存,数据库端实际负载很轻。2009年初,我们进行了新产品的开发。此时,我们遇到了如下一些问题。
|
||||
|
||||
* 用户数据激增:我们的MySQL某个信息表上线1个月的数据就达到千万。我们之前忽略的很多数据,在新形势下需要跟踪记录,这也导致了数据量的激增;
|
||||
* 用户对于信息的实时性要求更高:对信息的响应速度和更新频度就要求更高。简单通过缓存解决的灵丹妙药不复存在;
|
||||
* 对于Scale-out的要求更高:有些创新产品的增长速度是惊人的。因此要求能够无痛的升级扩展,否则一旦停机,那么用户流失的速度也是惊人的;
|
||||
* 大量文件的备份工作:我们面向的是创意人群,产生的内容是以图片为主。需要能够对这些图片及不同尺寸的缩略图进行有效的备份管理。我们之前使用的Linux inotify+rsync的增量备份方案效果不佳;
|
||||
* 需求变化频繁:开发要更加敏捷,开发成本和维护成本要更低,要能够快速地更新进化,新功能要在最短的周期内上线。
|
||||
|
||||
最初,我们试图完全通过优化现有的技术架构来解决以上问题:对数据时效性进一步分级分层缓存,减小缓存粒度;改进缓存更新机制(线上实时和线下异步更新)提高缓存命中率;尝试对业务数据的特点按照水平和垂直进行分表;使用MogileFS进行分布存储;进一步优化Mysql的性能,同时增加MySQL节点等。但很快发现,即便实施了上述方案,也很难完全解决存在的问题:过度依赖Memcached导致数据表面一致性的维护过于复杂,应用程序开发需要很小心,很多时候出现Memcached的失效会瞬间导致后端数据库压力过大;不同类型数据的特点不同,数据量差别也很大;分表的机制和方式在效率平衡上很难取舍;MogileFS对我们而言是脚小鞋大,维护成本远远超过了实际的效益;引入更多的MySQL数据库节点增大了我们的维护量,如何有效监控和管理这些节点又成了新的问题。虽然虚拟化可以解决部分问题,但还是不能令人满意;
|
||||
|
||||
除了MySQL,能否找到一个更为简单、轻便的瑞士军刀呢?我们的目光投向了NoSQL的方案。
|
||||
|
||||
===== 候选方案 =====
|
||||
|
||||
最初,对于NoSQL的候选方案,我依据关注和熟悉程度,并且在甄别和选择合适的方案时特别制定了一些原则:是否节省系统资源,对于CPU等资源是否消耗过大;客户端/API支持,这直接影响应用开发的效率;文档是否齐全,社区是否活跃;部署是否简单;未来扩展能力。按以上几点经过一段测试后,我们候选名单中剩下Redis、MongoDB和Flare。
|
||||
|
||||
Redis对丰富数据类型的操作很吸引人,可以轻松解决一些应用场景,其读写性能也相当高,唯一缺点就是**存储能力和内存挂钩**,这样如果存储大量的数据需要消耗太多的内存(最新的版本已经不存在这个问题)。
|
||||
|
||||
Flare的集群管理能力令人印象深刻,它可以支持节点的动态部署,支持节点的基于权重的负载均衡,支持数据分区。同时允许存储大的数据,其key的长度也不受Memcached的限制。而这些对于客户端是透明的,客户端使用Memcached协议链接到Flare的proxy节点就可以了。由于使用集群,Flare支持fail-over,当某个数据节点宕掉,对于这个节点的访问都会自动被proxy节点forward到对应的后备节点,恢复后还可以自动同步。Flare的缺点是实际应用案例较少,文档较为简单,目前只在Geek使用。
|
||||
|
||||
以上方案都打算作为一个优化方案,我从未想过完全放弃MySQL。然而,用MongoDB做产品的设计原型后,我彻底被征服了,决定全面从MySQL迁移到MongoDB。
|
||||
|
||||
===== 为什么MongoDB可以替代MySQL? =====
|
||||
|
||||
MongoDB是一个**面向文档**的数据库,目前由10gen开发并维护,它的功能丰富,齐全,完全可以替代MySQL。在使用MongoDB做产品原型的过程中,我们总结了MonogDB的一些亮点:
|
||||
|
||||
* 使用JSON风格语法,易于掌握和理解:MongoDB使用JSON的变种BSON作为内部存储的格式和语法。针对MongoDB的操作都使用JSON风格语法,客户端提交或接收的数据都使用JSON形式来展现。相对于SQL来说,更加直观,容易理解和掌握。
|
||||
|
||||
* Schema-less,支持嵌入子文档:MongoDB是一个Schema-free的文档数据库。一个数据库可以有多个Collection,每个Collection是Documents的集合。Collection和Document和传统数据库的Table和Row并不对等。无需事先定义Collection,随时可以创建。
|
||||
|
||||
* Collection中可以包含具有不同schema的文档记录。 这意味着,你上一条记录中的文档有3个属性,而下一条记录的文档可以有10个属性,属性的类型既可以是基本的数据类型(如数字、字符串、日期等),也可以是数组或者散列,甚至还可以是一个子文档(embed document)。这样,可以实现逆规范化(denormalizing)的数据模型,提高查询的速度。
|
||||
|
||||
|
||||
图1 MongoDB是一个Schema-free的文档数据库
|
||||
|
||||
图2是一个例子,作品和评论可以设计为一个collection,评论作为子文档内嵌在art的comments属性中,评论的回复则作为comment子文档的子文档内嵌于replies属性。按照这种设计模式,只需要按照作品id检索一次,即可获得所有相关的信息了。在MongoDB中,不强调一定对数据进行Normalize ,很多场合都建议De-normalize,开发人员可以扔掉传统关系数据库各种范式的限制,不需要把所有的实体都映射为一个Collection,只需定义最顶级的class。MongoDB的文档模型可以让我们很轻松就能将自己的Object映射到collection中实现存储。
|
||||
图2 MongoDB支持嵌入子文档
|
||||
|
||||
图2 MongoDB支持嵌入子文档
|
||||
|
||||
简单易用的查询方式:MongoDB中的查询让人很舒适,没有SQL难记的语法,直接使用JSON,相当的直观。对不同的开发语言,你可以使用它最基本的数组或散列格式进行查询。配合附加的operator,MongoDB支持范围查询,正则表达式查询,对子文档内属性的查询,可以取代原来大多数任务的SQL查询。
|
||||
|
||||
CRUD更加简单,支持in-place update:只要定义一个数组,然后传递给MongoDB的insert/update方法就可自动插入或更新;对于更新模式,MongoDB支持一个upsert选项,即:“如果记录存在那么更新,否则插入”。MongoDB的update方法还支持Modifier,通过Modifier可实现在服务端即时更新,省去客户端和服务端的通讯。这些modifer可以让MongoDB具有和Redis、Memcached等KV类似的功能:较之MySQL,MonoDB更加简单快速。Modifier也是MongoDB可以作为对用户行为跟踪的容器。在实际中使用Modifier来将用户的交互行为快速保存到MongoDB中以便后期进行统计分析和个性化定制。
|
||||
|
||||
所有的属性类型都支持索引,甚至数组:这可以让某些任务实现起来非常的轻松。在MongoDB中,“_id”属性是主键,默认MongoDB会对_id创建一个唯一索引。
|
||||
|
||||
服务端脚本和Map/Reduce:MongoDB允许在服务端执行脚本,可以用Javascript编写某个函数,直接在服务端执行,也可以把函数的定义存储在服务端,下次直接调用即可。MongoDB不支持事务级别的锁定,对于某些需要自定义的“原子性”操作,可以使用Server side脚本来实现,此时整个MongoDB处于锁定状态。Map/Reduce也是MongoDB中比较吸引人的特性。Map/Reduce可以对大数据量的表进行统计、分类、合并的工作,完成原先SQL的GroupBy等聚合函数的功能。并且Mapper和Reducer的定义都是用Javascript来定义服务端脚本。
|
||||
|
||||
性能高效,速度快: MongoDB使用c++/boost编写,在多数场合,其查询速度对比MySQL要快的多,对于CPU占用非常小。部署也很简单,对大多数系统,只需下载后二进制包解压就可以直接运行,几乎是零配置。
|
||||
|
||||
支持多种复制模式: MongoDB支持不同的服务器间进行复制,包括双机互备的容错方案。
|
||||
|
||||
Master-Slave是最常见的。通过Master-Slave可以实现数据的备份。在我们的实践中,我们使用的是Master-Slave模式,Slave只用于后备,实际的读写都是从Master节点执行。
|
||||
|
||||
Replica Pairs/Replica Sets允许2个MongoDB相互监听,实现双机互备的容错。
|
||||
|
||||
MongoDB只能支持有限的双主模式(Master-Master),实际可用性不强,可忽略。
|
||||
|
||||
内置GridFS,支持大容量的存储:这个特点是最吸引我眼球的,也是让我放弃其他NoSQL的一个原因。GridFS具体实现其实很简单,本质仍然是将文件分块后存储到files.file和files.chunk 2个collection中,在各个主流的driver实现中,都封装了对于GridFS的操作。由于GridFS自身也是一个Collection,你可以直接对文件的属性进行定义和管理,通过这些属性就可以快速找到所需要的文件,轻松管理海量的文件,无需费神如何hash才能避免文件系统检索性能问题, 结合下面的Auto-sharding,GridFS的扩展能力是足够我们使用了。在实践中,我们用MongoDB的GridFs存储图片和各种尺寸的缩略图。
|
||||
图3 MongoDB的Auto-sharding结构
|
||||
|
||||
图3 MongoDB的Auto-sharding结构
|
||||
|
||||
内置Sharding,提供基于Range的Auto Sharding机制:一个collection可按照记录的范围,分成若干个段,切分到不同的Shard上。Shards可以和复制结合,配合Replica sets能够实现Sharding+fail-over,不同的Shard之间可以负载均衡。查询是对客户端是透明的。客户端执行查询,统计,MapReduce等操作,这些会被MongoDB自动路由到后端的数据节点。这让我们关注于自己的业务,适当的时候可以无痛的升级。MongoDB的Sharding设计能力最大可支持约20 petabytes,足以支撑一般应用。
|
||||
|
||||
第三方支持丰富: MongoDB社区非常活跃,很多开发框架都迅速提供了对MongDB的支持。不少知名大公司和网站也在生产环境中使用MongoDB,越来越多的创新型企业转而使用MongoDB作为和Django,RoR来搭配的技术方案。
|
||||
|
||||
实施结果
|
||||
|
||||
实施MonoDB的过程是令人愉快的。我们对自己的PHP开发框架进行了修改以适应MongoDB。在PHP中,对MongoDB的查询、更新都是围绕Array进行的,实现代码变得很简洁。由于无需建表,MonoDB运行测试单元所需要的时间大大缩短,对于TDD敏捷开发的效率也提高了。当然,由于MongoDB的文档模型和关系数据库有很大不同,在实践中也有很多的困惑,幸运的是,MongoDB开源社区给了我们很大帮助。最终,我们使用了2周就完成了从MySQL到MongoDB的代码移植比预期的开发时间大大缩短。从我们的测试结果看也是非常惊人,数据量约2千万,数据库300G的情况下,读写2000rps,CPU等系统消耗是相当的低(我们的数据量还偏小,目前陆续有些公司也展示了他们的经典案例:MongoDB存储的数据量已超过 50亿,>1.5TB)。目前,我们将MongoDB和其他服务共同部署在一起,大大节约了资源。
|
||||
|
||||
一些小提示
|
||||
|
||||
切实领会MongoDB的Document模型,从实际出发,扔掉关系数据库的范式思维定义,重新设计类;在服务端运行的JavaScript代码避免使用遍历记录这种耗时的操作,相反要用Map/Reduce来完成这种表数据的处理;属性的类型插入和查询时应该保持一致。若插入时是字符串“1”,则查询时用数字1是不匹配的;优化MongoDB的性能可以从磁盘速度和内存着手;MongoDB对每个Document的限制是最大不超过4MB;在符合上述条件下多启用Embed Document, 避免使用DatabaseReference;内部缓存可以避免N+1次查询问题(MongoDB不支持joins)。
|
||||
|
||||
用Capped Collection解决需要高速写入的场合,如实时日志;大数据量情况下,新建同步时要调高oplogSize的大小,并且自己预先生成数据文件,避免出现客户端超时;Collection+Index合计数量默认不能超过24000;当前版本(<v1.6)删除数据的空间不能被回收,如果你频繁删除数据,那么需要定期执行repairDatabase,释放这些空间。
|
||||
|
||||
结束语
|
||||
|
||||
MongoDB的里程碑是1.6版本,预计今年7月份发布,届时,MongoDB的Sharding将首次具备在生产环境中使用的条件。作为MongoDB的受益者,我们目前也在积极参与MongoDB社区活动,改进Perl/PHP对于MongoDB的技术方案。在1.6版本后也将年内推出基于MongoDB的一些开源项目。
|
||||
|
||||
对于那些刚刚起步,或者正在开发创新型互联网应用的公司来说,MongoDB的快速、灵活、轻量和强大扩展性,正适合我们快速开发产品,快速迭代,适应用户迅速变化和更新的种种需求。
|
||||
|
||||
总而言之,MongoDB是一个最适合替代MySQL的全功能的NoSQL产品,使用MongoDB+Perl/PHP/Django/RoR的组合将很快成为开发Web2.0、3.0的产品的最佳组合,就像当年MySQL替代Oracle/DB2/Informix一样,历史总是惊人的相似,让我们拭目以待吧!
|
||||
|
||||
作者简介:
|
||||
|
||||
潘凡(nightsailer,N.S.), 视觉中国网站技术总监,联合创始人,家有1狗2猫。目前负责网站平台设计和底层产品研发工作。当前关注:Apps平台设计、分布式文件存储、NoSQL、高性能后现代的Perl编程。Twitter:@nightsailer Blog:http://nightsailer.com/
|
||||
|
||||
(本文来自《程序员》杂志10年06期)
|
||||
|
||||
|
||||
BIN
Zim/NonSQL/视觉中国的NoSQL之路:从MySQL到MongoDB/1.gif
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
Zim/NonSQL/视觉中国的NoSQL之路:从MySQL到MongoDB/2.gif
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
Zim/NonSQL/视觉中国的NoSQL之路:从MySQL到MongoDB/3.gif
Normal file
|
After Width: | Height: | Size: 22 KiB |