序
日前国内没有一套比较完整的Nosql数据库资料,有很多先驱整理发表了很多,但不是很系统。不材尝试着将各家的资料整合一下,并书写了一些自己的见解。
本书写了一些目前的Nosql的一些主要技术,算法和思想。同时列举了大量的现有的数据库实例。读完全篇,相信读者会对Nosql数据库了解个大概。
另外我还准备开发一个开源内存数据库galaxydb.本书也是为这个数据库提供一些架构资料。
日前国内没有一套比较完整的Nosql数据库资料,有很多先驱整理发表了很多,但不是很系统。不材尝试着将各家的资料整合一下,并书写了一些自己的见解。
本书写了一些目前的Nosql的一些主要技术,算法和思想。同时列举了大量的现有的数据库实例。读完全篇,相信读者会对Nosql数据库了解个大概。
另外我还准备开发一个开源内存数据库galaxydb.本书也是为这个数据库提供一些架构资料。
@H_548_403@ 存储系统可以理解为一个黑盒子,它为我们提供了可用性和持久性的保证。
@H_548_403@ ProcessA主要实现从存储系统write和read操作
@H_548_403@ ProcessB和C是独立于A,并且B和C也相互独立的,它们同时也实现对存储系统的write和read操作。
下面以上面的场景来描述下不同程度的一致性:
@H_548_403@ 强一致性(即时一致性) 假如A先写入了一个值到存储系统,存储系统保证后续A,B,C的读取操作都将返回最新值
@H_548_403@ 假如A先写入了一个值到存储系统,存储系统不能保证后续A,C的读取操作能读取到最新值。此种情况下有一个“不一致性窗口”的概念,它特指从A写入值,到后续操作A,C读取到最新值这一段时间。
@H_548_403@ 最终一致性是弱一致性的一种特例。假如A首先write了一个值到存储系统,存储系统保证如果在A,C后续读取之前没有其它写操作更新同样的值的话, 最终所有的读取操作都会读取到最A写入的最新值。此种情况下,如果没有失败发生的话,“不一致性窗口”的大小依赖于以下的几个因素:交互延迟,系统的负 载,以及复制技术中replica的个数(这个可以理解为master/salve模式中,salve的个数),最终一致性方面最出名的系统可以说是 DNS系统,当更新一个域名的IP以后,根据配置策略以及缓存控制策略的不同,最终所有的客户都会看到最新的值。
@H_548_403@ 如果Process A通知Process B它已经更新了数据,那么Process B的后续读取操作则读取A写入的最新值,而与A没有因果关系的C则可以最终一致性。
@H_548_403@ 如果Process A写入了最新的值,那么Process A的后续操作都会读取到最新值。但是其它用户可能要过一会才可以看到。
@H_548_403@ 此种一致性要求客户端和存储系统交互的整个会话阶段保证Read-your-writes consistency.Hibernate的session提供的一致性保证就属于此种一致性。
@H_548_403@ 此种一致性要求如果Process A已经读取了对象的某个值,那么后续操作将不会读取到更早的值。
@H_548_403@ 此种一致性保证系统会序列化执行一个Process中的所有写操作。
说起来很有趣,BASE的英文意义是碱,而ACID是酸。真的是水火不容啊。
"Soft state" 可以理解为"无连接"的,而 "Hard state" 是"面向连接"的
最终一致性, 也是是 ACID 的最终目的。@H_548_403@ BASE模型反ACID模型,完全不同ACID模型,牺牲高一致性,获得可用性或可靠性: Basically Available基本可用。支持分区失败(e.g. sharding碎片划分数据库) Soft state软状态 状态可以有一段时间不同步,异步。 Eventually consistent最终一致,最终数据是一致的就可以了,而不是时时一致。
对于数据的随机访问,内存的速度比硬盘高几个数量级(即使是最高端的磁盘存储系统也只是勉强达到1,000次寻道/秒)。其次, 随着数据中心的网络速度提高,访问内存的成本更进一步降低。通过网络访问另一台机器的内存比访问磁盘成本更低。就在我写下这段话的时候,Sun的 Infiniband产品线中有一款具备9个全互联非阻塞端口交换机,每个端口的速度可以达到30Gbit/sec!Voltaire产品的端口甚至更 多;简直不敢想象。(如果你想了解这类超高性能网络的最新进展,请关注Andreas Bechtolsheim在Standford开设的课程。)
各种操作的时间,以2001年夏季,典型配置的 1GHz 个人计算机为标准:
执行单一指令 | 1 纳秒 |
从L1 高速缓存取一个字 | 2 纳秒 |
从内存取一个字 | 10 纳秒 |
从磁盘取连续存放的一个字 | 200 纳秒 |
磁盘寻址并取字 | 8 毫秒 |
以太网 |
2GB/s |
内存是新的硬盘!硬盘速度提高缓慢,内存芯片容量指数上升,in-memory软件架构有望给各类数据密集的应用带来数量级的性能提升。小型机架服务器 (1U、2U)很快就会具备T字节、甚至更大量的内存,这将会改变服务器架构中内存和硬盘之间的平衡。硬盘将成为新的磁带,像磁带一样作为顺序存储介质使 用(硬盘的顺序访问相当快速),而不再是随机存储介质(非常慢)。这里面有着大量的机会,新产品的性能有望提高10倍、100倍。Dare Obsanjo指出 如果不把这句真言当回事,会带来什么样的恶劣后果 —— 也就是Twitter正面临的麻烦。论及Twitter的内容管理,Obsanjo说,“如果一个设计只是简单地反映了问题描述,你去实现它就会落入磁盘 I/O的地狱。不管你用Ruby on Rails、Cobol on Cogs、C++还是手写汇编都一样,读写负载照样会害死你。”换言之,应该把随机操作推给RAM,只给硬盘留下顺序操作。
本质上,在MapReduce的工作方式中,数据流式地读出和写入硬盘,MapReduce是以硬盘的传输速率不断地对这些数据进行排序和合并。 与之相比,访问关系数据库中的数据,其速率则是硬盘的寻道速率(寻道指移动磁头到盘面上的指定位置读取或写入数据的过程)。为什么要强调这一点?请看看寻 道时间和磁盘传输率的发展曲线。寻道时间每年大约提高5%,而数据传输率每年大约提高20%。寻道时间的进步比数据传输率慢——因此采用由数据传输率决定 性能的模型是有利的。MapReduce正是如此。虽然固态硬盘(SSD)能否改变寻道时间/传输率的对比还有待观察, White文章的跟贴 中,很多人都认为 SSD会成为RAM/硬盘之争中的平衡因素 。
提供在内存中的基于对象的数据库能力,支持核心的数据库功能,诸如高级索引和查询、事务语义和锁。IMDG还从应用程序的代码中抽象出了数据的拓扑。通过这样的方式,数据库不会完全消失,只是挪到了“正确的”位置。IMDG相比直接RDBMS访问的优势列举如下:
你是否需要改变对应用和硬件的思维方式,最终取决于你要用它们完成的工作。但似乎公论认为,开发者解决性能和可伸缩性的思路已经到了该变一变的时候。
Amdahl 定律的加速比:S(n) = 使用1个处理器的串行计算时间 / 使用n个处理器的并行计算时间
S(n) = 1/(K+(1-K)/n) = n/(1+(n-1)K)
Gustafson定律的加速比:S(n) = 使用n个处理器的并行计算量 / 使用1个处理器的串行计算量
S(n) = K+(1-K)n
aw2.0公司的Alan Williamson撰写了一篇报道,主要是关于他在Amazon EC2上的体验的,他抱怨说,Amazon是公司唯一使用的云提供商,看起来它在开始时能够适应得很好,但是有一个临界点 :
在开始的日子里Amazon的表现非常棒。实例在几分钟内启动,几乎没有遇到任何问题,即便是他们的 小实例(SMALL INSTANCE) 也很健壮,足以支持适当使用的MysqL数据库。在20个月内,Amazon云系统一切运转良好,不需要任何的关心和抱怨。……
然而,在最后的八个月左右,他们“盔甲”内的漏洞开始呈现出来了。第一个弱点前兆是,新加入的Amazon SMALL实例的性能出现了问题。根据我们的监控,在服务器场中新添加的机器,与原先的那些相比性能有所下降。开始我们认为这是自然出现的怪现象,只是碰 巧发生在“吵闹的邻居”(Noisy Neighbors)旁边。根据随机法则,一次快速的停机和重新启动经常就会让我们回到“安静的邻居”旁边,那样我们可以达到目的。
……
然而,在最后的一两个月中,我们发现,甚至是这些“使用高级cpu的中等实例”也遭受了与小实例相同的命运,其中,新的实例不管处于什么位置,看起来似乎 都表现得一样。经过调查,我们还发现了一个新问题,它已经悄悄渗透到到Amazon的世界中,那就是内部网络延迟。
Gossip协议是一个Gossip思想的P2P实现。现代的分布式系统经常使用这个协议,他往往是唯一的手段。因为底层的结构非常复杂,而且Gossip也很有效。
Gossip协议也被戏称为病毒式传播,因为他的行为生物界的病毒很相似。
数据库以行、列的二维表的形式存储数据,但是却以一维字符串的方式存储,例如以下的一个表:
EmpId | Lastname | Firstname | Salary |
---|---|---|---|
1 | Smith | Joe | 40000 |
2 | Jones | Mary | 50000 |
3 | Johnson | Cathy | 44000 |
这个简单的表包括员工代码(EmpId),姓名字段(Lastname and Firstname)及工资(Salary).
这个表存储在电脑的内存(RAM)和存储(硬盘)中。虽然内存和硬盘在机制上不同,电脑的操作系统是以同样的方式存储的。数据库必须把这个二维表存储在一系列一维的“字节”中,又操作系统写到内存或硬盘中。
行式数据库把一行中的数据值串在一起存储起来,然后再存储下一行的数据,以此类推。
1,Smith,Joe,40000;2,Jones,Mary,50000;3,Johnson,Cathy,44000;列式数据库把一列中的数据值串在一起存储起来,然后再存储下一列的数据,以此类推。
1,3;Smith,Johnson;Joe,Cathy;40000,50000,44000;Memcached处理的原子是每一个(key,value)对(以下简称kv对),key会通过一个hash算法转化成hash-key,便于查找、对比以及做到尽可能的散列。同时,memcached用的是一个二级散列,通过一张大hash表来维护。
Memcached有两个核心组件组成:服务端(ms)和客户端(mc),在一个memcached的查询中,mc先通过计算key的hash值来 确定kv对所处在的ms位置。当ms确定后,客户端就会发送一个查询请求给对应的ms,让它来查找确切的数据。因为这之间没有交互以及多播协议,所以 memcached交互带给网络的影响是最小化的。
默认情况下,ms是用一个内置的叫“块分配器”的组件来分配内存的。舍弃c++标准的malloc/free的内存分配,而采用块分配器的主要目的 是为了避免内存碎片,否则操作系统要花费更多时间来查找这些逻辑上连续的内存块(实际上是断开的)。用了块分配器,ms会轮流的对内存进行大块的分配,并 不断重用。当然由于块的大小各不相同,当数据大小和块大小不太相符的情况下,还是有可能导致内存的浪费。
同时,ms对key和data都有相应的限制,key的长度不能超过250字节,data也不能超过块大小的限制 --- 1MB。
因为mc所使用的hash算法,并不会考虑到每个ms的内存大小。理论上mc会分配概率上等量的kv对给每个ms,这样如果每个ms的内存都不太一样,那 可能会导致内存使用率的降低。所以一种替代的解决方案是,根据每个ms的内存大小,找出他们的最大公约数,然后在每个ms上开n个容量=最大公约数的 instance,这样就等于拥有了多个容量大小一样的子ms,从而提供整体的内存使用率。
当ms的hash表满了之后,新的插入数据会替代老的数据,更新的策略是LRU(最近最少使用),以及每个kv对的有效时限。Kv对存储有效时限是在mc端由app设置并作为参数传给ms的。
同时ms采用是偷懒替代法,ms不会开额外的进程来实时监测过时的kv对并删除,而是当且仅当,新来一个插入的数据,而此时又没有多余的空间放了,才会进行清除动作。
现在memcached最流行的一种使用方式是缓存数据库查询,下面举一个简单例子说明:
App需要得到userid=xxx的用户信息,对应的查询语句类似:
“SELECT * FROM users WHERE userid = xxx”
App先去问cache,有没有“user:userid”(key定义可预先定义约束好)的数据,如果有,返回数据;如果没有,App会从数据库中读取数据,并调用cache的add函数,把数据加入cache中。
当取的数据需要更新,app会调用cache的update函数,来保持数据库与cache的数据同步。
从上面的例子我们也可以发现,一旦数据库的数据发现变化,我们一定要及时更新cache中的数据,来保证app读到的是同步的正确数据。当然我们可 以通过定时器方式记录下cache中数据的失效时间,时间一过就会激发事件对cache进行更新,但这之间总会有时间上的延迟,导致app可能从 cache读到脏数据,这也被称为狗洞问题。(以后我会专门描述研究这个问题)
从设计角度上,memcached是没有数据冗余环节的,它本身就是一个大规模的高性能cache层,加入数据冗余所能带来的只有设计的复杂性和提高系统的开支。
当一个ms上丢失了数据之后,app还是可以从数据库中取得数据。不过更谨慎的做法是在某些ms不能正常工作时,提供额外的ms来支持cache,这样就不会因为app从cache中取不到数据而一下子给数据库带来过大的负载。
同时为了减少某台ms故障所带来的影响,可以使用“热备份”方案,就是用一台新的ms来取代有问题的ms,当然新的ms还是要用原来ms的IP地址,大不了数据重新装载一遍。
另外一种方式,就是提高你ms的节点数,然后mc会实时侦查每个节点的状态,如果发现某个节点长时间没有响应,就会从mc的可用server列表里 删除,并对server节点进行重新hash定位。当然这样也会造成的问题是,原本key存储在B上,变成存储在C上了。所以此方案本身也有其弱点,最好 能和“热备份”方案结合使用,就可以使故障造成的影响最小化。
Memcached客户端有各种语言的版本供大家使用,包括java,c,PHP,.net等等,具体可参见memcached api page [2]。
大家可以根据自己项目的需要,选择合适的客户端来集成。
有了缓存的支持,我们可以在传统的app层和db层之间加入cache层,每个app服务器都可以绑定一个mc,每次数据的读取都可以从ms中取得,如果 没有,再从db层读取。而当数据要进行更新时,除了要发送update的sql给db层,同时也要将更新的数据发给mc,让mc去更新ms中的数据。
Yahoo!的PNUTS是一个分布式的数据存储平台,它是Yahoo!云计算平台重要的一部分。它的上层产品通常也称为Sherpa。按照官方的 描述,”PNUTS,a massively parallel and geographically distributed database system for Yahoo!’s web applications.” PNUTS显然就深谙CAP之道,考虑到大部分web应用对一致性并不要求非常严格,在设计上放弃了对强一致性的追求。代替的是追求更高的 availability,容错,更快速的响应调用请求等。
2006年Greg Linden就说I want a big,virtual database
What I want is a robust,high performance virtual relational database that runs transparently over a cluster,nodes dropping in an out of service at will,read-write replication and data migration all done automatically.
I want to be able to install a database on a server cloud and use it like it was all running on one machine.
详细资料:
http://timyang.net/architecture/yahoo-pnuts/
SQL数据服务 是微软 Azure 网 络服务平台的一部分。该SDS服务也是处于测试阶段,因此也是免费的,但对数据库大小有限制。 sql数据服务其自身实际上是一项处在许多sql服务器之上的应用,这些sql服务器组成了SDS平台底层的数据存储。你不需要访问到它们,虽然底层的数 据库可能是关系式的;SDS是一个键/值型仓储,正如我们迄今所讨论过的其它平台一样。
微软看起来不同于前三个供应商,因为虽然键/值存储对于可扩性���言非常棒,相对于RDBMS,在数据管理上却很困难。微软的方案似乎是入木三分,在实现可扩性和分布机制的同时,随着时间的推移,不断增加特性,在键/值存储和关系数据库平台的鸿沟之间搭起一座桥梁。
在云之外,也有一些可以独立安装的键/值数据库软件产品。大部分都还很年轻,不是alpha版就是beta版,但大都是开源的;通过看看它的代码,比起在非开源供应商那里,你也许更能意识到潜在的问题和限制。
C ouchDB : API: JSON,Protocol: REST,Query Method: MapReduceR of JavaScript Funcs,Replication: Master Master,Written in: Erlang,Concurrency: MVCC,Misc :
Links : 3 CouchDB books »,Couch Lounge » (partitioning / clusering),...
它是Apache社区基于 Erlang/OTP 构建的高性能、分布式容错非关系型数据库系统(NRDBMS)。它充分利用 Erlang 本身所提供的高并发、分布式容错基础平台,并且参考 Lotus Notes 数据库实现,采用简单的文档数据类型(document-oriented)。在其内部,文档数据均以 JSON 格式存储。对外,则通过基于 HTTP 的 REST 协议实现接口,可以用十几种语言进行自由操作。
CouchDB一种半结构化面向文档的���布式,高容错的数据库系统,其提供RESTFul HTTP/JSON接口。其拥有MVCC特性,用户可以通过自定义Map/Reduce函数生成对应的View。
在CouchDB中,数据是以JSON字符的方式存储在文件中。
应用场景 在我们的生活中,有很多document,比如信件,账单,笔记等,他们只是简单的信息,没有关系的需求,我们可能仅仅需要存储这些数据。 这样的情况下,CouchDB应该是很好的选择。当然其他使用关系型数据库的环境,也可以使用CouchDB来解决。
根据CouchDB的特性,在某些偶 尔连接网络的应用中,我们可以用CouchDB暂存数据,随后进行同步。也可以在Cloud环境中,作为分布式的数据存储。CouchDB提供给予 HTTP的API,这样所有的常见语言都可以使用CouchDB。
使用CouchDB,意味着我们不需要在像使用RMDBS一样,在设计应用前首先设计负责数据Table。我们的开发更加快速,灵活。
详细参见:
http://www.javaeye.com/topic/319839
Riak »,
MongoDB : API: BSON,Protocol: lots of langs,Query Method: dynamic object-based language,Replication: Master Slave,Written in: C++,Concurrency: Update in Place . Misc: ... Links : Talk »,
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一模一样,功能非常强大易用。
Terrastore : API: Java & http,Protocol: http,Language: Java,Querying: Range queries,Predicates,Replication: Partitioned with consistent hashing,Consistency: Per-record strict consistency,Misc: Based on Terracotta
ThruDB : (please help provide more facts!) Uses Apache Thrift to integrate multiple backend databases as BerkeleyDB,Disk,MysqL,S3.
Amazon SimpleDB : Misc : not open source,Book »
SimpleDB 是一个亚马逊网络服务平台的一个面向属性的键/值数据库。SimpleDB仍处于公众测试阶段;当前,用户能在线注册其“免费”版 --免费的意思是说直到超出使用限制为止。
SimpleDB有几方面的限制。首先,一次查询最多只能执行5秒钟。其次,除了字符串类型,别无其它数据类型。一切都以字符串形式被存储、获取和 比较,因此除非你把所有日期都转为ISO8601,否则日期比较将不起作用。第三,任何字符串长度都不能超过1024字节,这限制了你在一个属性中能存储 的文本的大小(比如说产品描述等)。不过,由于该模式动态灵活,你可以通过追加“产品描述1”、“产品描述2”等来绕过这类限制。一个项目最多可以有 256个属性。由于处在测试阶段,SimpleDB的域不能大于10GB,整个库容量则不能超过1TB。
SimpleDB的一项关键特性是它使用一种最终一致性模型 。 这个一致性模型对并发性很有好处,但意味着在你改变了项目属性之后,那些改变有可能不能立即反映到随后的读操作上。尽管这种情况实际发生的几率很低,你也 得有所考虑。比如说,在你的演出订票系统里,你不会想把最后一张音乐会门票卖给5个人,因为在售出时你的数据是不一致的。
Chordless : API: Java & simple RPC to vals,Protocol: internal,Query Method: M/R inside value objects,Scaling: every node is master for its slice of namespace,Concurrency: serializable transaction isolation,Links :
Redis :(please help provide more facts!) API: Tons of languages,Written in: C,Concurrency: in memory and saves asynchronous disk after a defined time. Append only mode available. Different kinds of fsync policies. Replication: Master / Slave,
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。
@L_758_301@ : (please help provide more facts!) Written in: Erlang,Replication: Strong consistency over replicas,Concurrency: non blocking Paxos .
Tokyo Cabinet / Tyrant : Links : nice talk »,slides »,Misc: Kyoto Cabinet »
它是日本最大的SNS社交网站mixi.jp 开发的 Tokyo Cabinet key-value数据库网络接口。它拥有Memcached兼容协议,也可以通过HTTP协议进行数据交换。对任何原有Memcached客户端来讲, 可以将Tokyo Tyrant看成是一个Memcached,但是,它的数据是可以持久存储的。Tokyo Tyrant 具有故障转移、日志文件体积小、大数据量下表现出色等优势,详见:http://blog.s135.com/post/362.htm
Tokyo Cabinet 2009年1月18日发布的新版本(Version 1.4.0)已经实现 Table Database,将key-value数据库又扩展了一步,有了MysqL等关系型数据库的表和字段的概念,相信不久的将来,Tokyo Tyrant 也将支持这一功能。值得期待。
GT.M : API: M,C,Python,Perl,Protocol: native,inprocess C,Misc: Wrappers: M/DB for SimpleDB compatible HTTP »,MDB:X for XML »,PIP for mapping to tables for sql »,Features: Small footprint (17MB),Terabyte Scalability,Unicode support,Database encryption,Secure,ACID transactions (single node),eventual consistency (replication),License: AGPL v3 on x86 GNU/Linux,Links : Slides »,
Scalien : API / Protocol: http (text,html,JSON),C++,Python,Concurrency: Paxos .
Berkley DB : API: Many languages,Replication: Master / Slave,License: Sleepycat,BerkleyDB Java Edition : API: Java,License: Sleepycat
MemcacheDB : API: Memcache protocol (get,set,add,replace,etc.),Data Model: Blob,Misc: Is Memcached writing to BerkleyDB.
它是新浪互动社区事业部为在Memcached基础上,增加Berkeley DB存储层而开发一款支持高并发的分布式持久存储系统,对任何原有Memcached客户端来讲,它仍旧是个Memcached,但是,它的数据是可以持久存储的。
LightCloud : (based on Tokyo Tyrant)
HamsterDB : (embedded solution) ACID Compliance,Lock Free Architecture (transactions fail on conflict rather than block),Transaction logging & fail recovery (redo logs),In Memory support – can be used as a non-persisted cache,B+ Trees – supported [Source: Tony Bain » ]
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数据结构存储。
Amazon Dynamo : Misc : not open source (see KAI below)
可以根据应用类型优化(可用性,容错性,高效性配置)
BeansDB 是一个主要针对大数据量、高可用性的分布式KeyValue存储系统,采用HashTree和简化的版本号来快速同步保证最终一致性(弱),一个简化版的Dynamo。
它采用类似memcached的去中心化结构,在客户端实现数据路由。目前只提供了Python版本的客户端,其它语言的客户端可以由memcached的客户端稍加改造得到。
Google Group: http://groups.google.com/group/beandb/
# memstorm -s localhost:7900 -n 1000
Num of Records : 10000
Non - Blocking IO : 0
TCP No - Delay : 0
Successful [ SET ] : 10000
Failed [ SET ] : 0
Total Time [ SET ] : 0.45493s
Average Time [ SET ] : 0.00005s
Successful [ GET ] : 10000
Failed [ GET ] : 0
Total Time [ GET ] : 0.28609s
Average Time [ GET ] : 0.00003s
实际部署情况下的性能(客户端测量):
􀂄 服务器 请求数 评价时间( ms ) 中位数( ms ) 99 % ( ms ) 99.9 %( ms )
􀂄 get A : 7900 n = 151398 , avg = 8.89 , med = 5.94 , 99 %= 115.5 , 99.9 %= 310.2
􀂄 get B : 7900 n = 100054 , avg = 6.84 , med = 0.40 , 99 %= 138.5 , 99.9 %= 483.0
􀂄 get C : 7900 n = 151250 , avg = 7.42 , med = 5.34 , 99 %= 55.2 , 99.9 %= 156.7
􀂄 get D : 7900 n = 150677 , avg = 7.63 , med = 5.09 , 99 %= 97.7 , 99.9 %= 284.7
􀂄 get E : 7900 n = 3822 , avg = 3.07 , med = 0.18 , 99 %= 44.3 , 99.9 %= 170.0
􀂄 get F : 7900 n = 249973 , avg = 8.29 , med = 6.36 , 99 %= 46.8 , 99.9 %= 241.5
􀂄 set A : 7900 n = 10177 , avg = 18.53 , med = 12.78 , 99 %= 189.3 , 99.9 %= 513.6
􀂄 set B : 7900 n = 10431 , avg = 12.85 , med = 1.19 , 99 %= 206.1 , 99.9 %= 796.8
􀂄 set C : 7900 n = 10556 , avg = 17.29 , med = 12.97 , 99 %= 132.2 , 99.9 %= 322.9
􀂄 set D : 7900 n = 10164 , avg = 7.34 , med = 0.64 , 99 %= 98.8 , 99.9 %= 344.4
􀂄 set E : 7900 n = 10552 , avg = 7.18 , med = 2.33 , 99 %= 73.6 , 99.9 %= 204.8
􀂄 set F : 7900 n = 10337 , avg = 17.79 , med = 15.31 , 99 %= 109.0 , 99.9 %= 369.5
BeansDB设计实现(非常难得的中文资料)
PPT
人人网研发中的数据库
详见:
http://ugc.renren.com/2010/01/21/ugc-nuclear-guide-use/
http://ugc.renren.com/2010/01/28/ugc-nuclear-guide-theory/
1. 万事皆异步
我们在编码的过程中走了一些弯路,同步的操作在高并发的情况下带来的性能下降是非常恐怖的,于是乎,Nuclear系统中任何的高并发操作都消除了Block。no waiting,no delay。
2. 根据系统负载控制后台线程的资源占用
Nuclear系统中有不少的后台线程默默无闻的做着各种辛苦的工作,但是它们同样会占用系统资源,我们的解决方案是根据系统负载动态调整线程的运行和停止,并达到平衡。
Voldemort : (can you help)
Voldemort是个和Cassandra类似的面向解决scale问题的分 布式数据库系统,Cassandra来自于Facebook这个 SNS网站,而Voldemort则来自于Linkedin这个SNS网站。说起来SNS网站为我们贡献了n多的Nosql数据库,例如 Cassandar,Voldemort,Tokyo Cabinet,Flare等等。Voldemort的资料不是很多,因此我没有特别仔细去钻研,Voldemort官方给出Voldemort的并发读 写性能也很不错,每秒超过了1.5万次读写。
其实现在很多公司可能都面临着这个抽象架构图中的类似问题。以 Hadoop 作为后端的计算集群,计算得出来的数据如果要反向推到前面去,用什么方式存储更为恰当? 再放到 DB 里面的话,构建索引是麻烦事;放到 Memcached 之类的 Key-Value 分布式系统中,毕竟只是在内存里,数据又容易丢。Voldemort 算是一个不错的改良方案。
值得借鉴的几点:
详细:
http://www.dbanotes.net/arch/voldemort_key-value.html
http://project-voldemort.com/blog/2009/06/building-a-1-tb-data-cycle-at-linkedin-with-hadoop-and-project-voldemort/
Dynomite : (can you help)
KAI : Open Source Amazon Dnamo implementation,Misc: slides,
全新的Ruby MapReduce实现
2004年,Google提出用于分布式数据处理的MapReduce设计模式,同时还提供了第一个C++的实现。现在,一个名为Skynet的Ruby实现已经由Adam Pisoni发布。
Skynet是可适配、可容错的、可自我更新的,而且完全
是分布式的系统,不存在单一的失败节点。
Skynet和Google在设计上有两点重要的区别:
Skynet无法向工作者(Worker)发送原生代码(Raw code),
Skynet利用结对恢复系统,不同的工作者会互相监控以防失败:
如果有一个工作者由于某种原因离开或者放弃了,就会有另一个工作者发现并接管它的任务。Skynet 也没有所谓的“主”管理进程,只有工作者,它们在任何时间都可以充当任何任务的主管理进程。
Skynet的使用和设置都很容易,这也正是MapReduce这个概念的真正优势。Skynet还扩展了ActiveRecord,加入了MapReduce的特性,比如distributed_find。
你要为Starfish编写一些小程序,它们的代码是你将要构建其中的。如果我没有弄错的话,你无法在同一台机器上运行多种类型的MapReduce作业。Skynet是一个更全面的MR系统,可以运行多种类型的多个作业,比如,各种不同的代码。
Skynet也允许失败。工作者会互相关照。如果一个工作者失败了,无法及时完成任务,另一个工作者将会接起这个任务并尝试完成它。Skynet也支持map_data流,也就是说,即使某个数据集非常庞大,甚至无法放在一个数据结构中,Skynet也可以处理。
什 么是map_data流?大多数时候,在你准备启动一个map_reduce作业时,必须提供一个数据的队列,这些数据已经被分离并将被并行处理。如果队 列过大,以至于无法适应于内存怎么办?在这种情况下,你就要不能再用队列,而应该使用枚举(Enumerable)。Skynet知道去对象的调 用:next或者:each方法,然后开始为“每一个(each)”分离出map_task来。通过这样的方式,不会有人再试图同时创建大量的数据结构。
还 有很多特性值得一提,不过最想提醒大家的是,Skynet能够与你现有的应用非常完美地集成到一起,其中自然包括Rails应用。Skynet甚 至还提供了一个ActiveRecord的扩展,你可以在模型中以分布式的形式执行一些任务。在Geni中,我们使用这项功能来运行特别复杂的移植,它通 常涉及到在数百万的模型上执行Ruby代码。
> Model.distributed_find(:all,:conditions => "id > 20").each(:somemethod)在你运行Skynet的时候,它将在每个模型上执行:somemethod,不过是以分布式的方式(这和你 拥有多少个工作者相关)。它在向模型分发任务前不必进行初始化,甚至不必提前获取所有的id。因此它可以操作无限大的数据集。 用户的反馈如何?
Drizzle 可 被认为是键/值存储要解决的问题的反向方案。Drizzle诞生于MysqL(6.0)关系数据库的拆分。在过去几个月里,它的开发者已经移走了大量非核 心的功能(包括视图、触发器、已编译语句、存储过程、查询缓冲、ACL以及一些数据类型),其目标是要建立一个更精简、更快的数据库系统。Drizzle 仍能存放关系数据;正如MysqL/Sun的Brian Aker所说那样:“没理由泼洗澡水时连孩子也倒掉”。它的目标就是,针对运行于16核(或以上)系统上的以网络和云为基础的应用,建立一个半关系型数据 库平台。
当你需要查询或更新一个值的一部分时,Key/value模型是最简单有效实现。
面向文本数据库是Key/value的下一步,允许内嵌和Key关联的值. 支持查询这些值数据,这比简单的每次返回整个blob类型数据要有效得多。
Neo4J是唯一的存储对象和关系作为数学图论中的节点和边. 对于这些类型数据的查询,他们能够比其他竞争者快1000s
Scalaris是唯一提供跨越多个key的分布式事务。
内存数据库是非常快的,(Redis在单个机器上可以完成每秒100,000以上操作)但是数据集超过内存RAM大小就不行. 而且 Durability (服务器当机恢复数据)也是一个问题
Memtables和SSTables缓冲 buffer是在内存中写(“memtable”), 写之前先追加一个用于durability的日志中.
但有足够多写入以后,这个memtable将被排序然后一次性作为“sstable.”写入磁盘中,这就提供了近似内存性能,因为没有磁盘的查询 seeks开销,同时又避免了纯内存操作的durability问题.(个人点评 其实Java中的Terracotta早就实现这两者结合)
B-Trees提供健壮的索引,但是性能很差,一般和其他缓存结合起来。
最近看到的另外一个介绍Twitter技术的视频[Slides ] [Video (GFWed)],这是Twitter的John Adams在Velocity 2009 的一个演讲,主要介绍了Twitter在系统运维方面一些经验。 本文大部分整理的观点都在Twitter(@xmpp )上发过,这里全部整理出来并补充完整。
Twitter没有自己的硬件,都是由NTTA来提供,同时NTTA负责硬件相关的网络、带宽、负载均衡等业务,Twitter operations team只关注核心的业务,包括Performance,Availability,Capacity Planning容量规划,配置管理 等,这个可能跟国内一般的互联网公司有所区别。
Twitter的监控后台几乎都是图表(critical metrics),类似驾驶室的转速表,时速表,让操作者可以迅速的了解系统当前的运作状态。联想到我们做的类似监控后台,数据很多,但往往还需要浏览者 做二次分析判断,像这样满屏都是图表的方法做得还不够,可以学习下这方面经验。 据John介绍可以从图表上看到系统的瓶颈-系统最弱的环节(web,mq,cache,db?)
根据图表可以科学的制定系统容量规划,而不是事后救火。
每个系统都需要一个自动配置管理系统,越早越好,这条一整理发到Twitter上去之后引起很多回应。
配置界面可以enable/disable 高计算消耗或高I/O的功能,也相当于优雅降级,系统压力过大时取消一些非核心但消耗资源大的功能。
Twitter做了一个”Seppaku” patch,就是将Daemon在完成了n个requests之后主动kill掉,以保持健康的low memory状态,这种做法据了解国内也有不少公司是这样做。
Twitter将cpu由AMD换成Xeon之后,获得30%性能提升,将cpu由双核/4核换成8核之后,减少了40%的cpu,不过John也说,这种升级不适合自己购买硬件的公司。
Twitter有上百个模块,如果没有一个好的制度,容易引起代码修改冲突,并把问题带给最终用户。所以Twitter有一强制的source code review制度,如果提交的代码的svn comment没有”reviewed by xxx”,则pre-commit脚本会让提交失败,review过的代码提交后会通过自动配置管理系统应用到上百台服务器上。 有@xiaomics同学在Twitter上马上就问,时间成本能否接受?如果有紧急功能怎么办?个人认为紧急修改时有两人在场,一人修改一人 review也不是什么难事。
从部署图表可以看到每个发布版本的cpu及latency变化,如果某个新版本latency图表有明显的向上跳跃,则说明该发布版本存在问题。另外在监控首页列出各个模块最后deploy版本的时间,可以清楚的看到代码库的现状。
Campfire来协同工作,campfire有点像群,但是更适合协同工作。对于Campfire就不做更多介绍,可参考Campfire 官方说明。
作者认为,金字塔概念最能说明每一层的大小,它也表达了每 个层是依赖前层的消息传递。在概念上,硬件是基础和广泛层。SaaS层是顶峰,也是最轻层。这种观点是来自于将购买SaaS的的最终用户角度。对于一个非 常大的企业内部,PaaS平台层将是顶峰。使用内部开发的软件的内部各部门将实现他们的顶峰SaaS。还要注意:大小和层位置并不一定等同于重要性。硬件 层可能是最重要的,因为它是所有超过一定点的商品。
硬件层The Hardware Layer
必须考虑容错和冗余,大部分人认为没有容错硬件廉价商品。冗余和容错处理在软件层内,硬件预计要失败的,当然故障多电源容错服务器,RAID磁盘阵列也是必要的。
虚拟层The Virtualization Layer
基于操作系统OS的虚拟化层,虚拟资源能够在线即时增加拓展,允许供应商提供基础设施作为服务(SaaS),VMware,Citrix公司,Sun都提供虚拟化产品。
The IaaS Layer
提 供和控制的基于虚拟层的计算方式,终端用户能够精确控制每个虚拟机没分钟每小时耗费多少钱。比如提供一个共同的接口,如门户网站暴露的API,允许最终用 户创建和配置虚拟机模板的需求。最终用户还可以控制何时打开或破坏虚拟机,以及如何在虚拟机互相联网。在这个领域的主要竞争者例子是亚马逊网络服务的 EC2,S3和数据库服务。
The PaaS Layer
这一层的目的是尽量减少部署云的复杂性和麻烦,最终用户 利用和开发的这层的API和编程语言。两个很好的例子是谷歌的App Engine 和Force.com平台,在App Engine中,谷歌公开云存储,平台和数据库,以及使用Python和Java编程语言的API。开发人员能够编写应用程序并部署到这一层中,后端可伸缩性 架构设计完全交给谷歌负责,最终用户完全不必担心管理基础设施。Force.com平台类似,但采用了自定义的编程语言名为Apex。如果你是一个大型企业寻求内部开发应用的部署,这层是你的顶峰。
The SaaS Layer
如 果您是中小型企业(SME)和大企业不希望开发自己的应用程序时,SaaS的层是你的顶峰(是你将直接面对的)。您只是进行有兴趣地采购如电子邮件或客户 关系管理服务,这些功能服务已经被供应商开发成功,并部署到云环境中了,您只需验证的应用是否符合你的使用需要,帐单可以基于包月租费等各种形式,,作为 最终用户的您不会产生开发和维护拓展应用程序软件的任何成本。越来越多的企业订阅Salesforce.com和Sugar CRM的SaaS产品。
大部分的人都坚持在单一的设备上部署我们的应用,因为这样部署的费用会比较低,但是我们要清楚任何的硬件设备都会有失败的风险的,这种单点失败会严重的影 响用户体验甚至是拖垮你的应用,因此除非你的应用能容忍失败带来的损失,否则得话应该尽量的避免单点风险,比如做冗余,热备等。
同步调用在任何软件系统中都是不可避免的,但是我们软件工程师必须明白同步调用给软件系统带来的问题。如果我们将应用程序串接起来,那么系统的可用性就会 低于任何一个单一组件的可用性。比如组件A同步调用了组件B,组件A的可用性为99.9%,组件B的可用性为99.9%,那么组件A同步调用组件B的可用 性就是99.9% * 99.9%=99.8%。同步调用使得系统的可用性受到了所有串接组件可用性的影响,因此我们在系统设计的时候应该清楚哪些地方应该同步调用,在不需要同 步调用的时候尽量的进行异步的调用(而我这里所说的异步是一种基于应用的异步,是一种设计上的异步,因为J2EE目前的底层系统出了JMS是异步API以 外,其它的API都是同步调用的,所以我们也就不能依赖于底层J2EE平台给我们提供异步性,我们必须从应用和设计的角度引入异步性)
虽然对应用的每个版本进行回滚能力测试是非常耗时和昂贵的,但是我们应该清楚任何的业务操作都有可能失败,那么我们必须为这种失败作好准备,需要对系统的 用户负责,这就要求系统一定要具有回滚的能力,当失败的时候能进行及时的回滚。(说到回滚大家可能第一时间想到的是事务的回滚,其实这里的回滚应该是一种 更宽泛意义的回滚,比如我们记录每一次的失败的业务操作,这样在出现错误的时候就不是依靠于事务这种技术的手段,而是通过系统本身的回滚能力来进行回滚失 败业务操作)。
日志记录对于一个成熟稳定的系统是非常重要的,如果我们不进行日志记录,那么我就很难统计系统的行为。
随着系统规模的慢慢变大,我们就需要打破单一数据的限制,需要对其进行切分。
系统在规模小的时候,也许感觉不出无切分的应用带来的问题,但是在目前互联网高速发展的时代,谁能保证一个小应用在一夜或者是几夜以后还是小应用呢?说不 定哪天,我们就发现应用在突如其来的访问量打击的支离破碎。因此我们就需要让我们的系统和我们一样具有生命力,要想让系统具有应付大负载的能力,这就要求 我们的应用具有很好的伸缩性,这也就要求应用需要被良好的切分,只有进行了切分,我们才能对单一的部门进行伸缩,如果应用是一块死板的话,我们是没有办法 进行伸缩的。就好比火车一样,如果火车设计之初就把他们设计为一体的,那么我们还怎么对火车的车厢进行裁剪?因此一个没有切分的应用是一个没有伸缩性和没 有可用性的应用。
如果我们的应用系统的伸缩性依赖于第三方的厂商,比如依赖于数据库集群,那么我们就为系统的伸缩性埋下了一个定时炸弹。因为只有我们自己最清楚我们自己的应用,我们应该从应用和设计的角度出发去伸缩我们的应用,而不是依赖于第三方厂商的特性。
联机分析处理 (OLAP) 的概念最早是由关系数据库之父E.F.Codd于1993年提出的,他同时提出了关于OLAP的12条准则。OLAP的提出引起了很大的反响,OLAP作为一类产品同联机事务处理 (OLTP) 明显区分开来。
目前报表工具最大的难点不在于报表的样式(如斜线等),样式虽较繁琐但并非本质困难。最根本的难点在于业务 部门知道报表代表的真正含义,却不知道报表的数据统计模型模型;而IT部门通过理解业务部门的描述,在数据库端进行设置数据统计模型,却对报表本身所代表 的价值很难理解。
说起来有点深奥,其实并不复杂,OLAP最基本的概念只有三个:多维观察、数据钻取、CUBE运算。
关于CUBE运算:OLAP分析所需的原始数据量是非常庞大的。一个分析模型,往往会涉及数百万、数千万条数据,甚至更多;而分析模型中包含多个维数据,这些维又可以由浏览者作任意的提取组合。这样的结果就是大量的实时运算导致时间的延滞。
我们可以设想,一个1000万条记录的分析模型,如果一次提取4个维度进行组合分析,那么实际的运算次数将 达到4的1000次方的数量。这样的运算量将导致数十分钟乃至更长的等待时间。如果用户对维组合次序进行调整,或增加、或减少某些维度的话,又将是一个重 新的计算过程。
从上面的分析中,我们可以得出结论,如果不能解决OLAP运算效率问题的话,OLAP将是一个毫无实用价值的概念。那么,一个成熟产品是如何解决这个问题的呢?这涉及到OLAP中一个非常重要的技术——数据CUBE预运算。
一个OLAP模型中,度量数据和维数据我们应该事先确定,一旦两者确定下来,我们可以对数据进行预先的处理。在正式发布之前,将数据根据维进行最大
限度的聚类运算,运算中会考虑到各种维组合情况,运算结果将生成一个数据CUBE,并保存在服务器 上。
这样,当最终用户在调阅这个分析模型的时候,就可以直接使用这个CUBE,在此基础上根据用户的维选择和维组合进行复运算,从而达到实时响应的效果。
几个星期之前,我写了一篇文章描述了常被称作 NOsql 的一类新型数据库的背后驱动。几个星期之前,我在Qcon上发表了一个演讲,其中,我介绍了一个可伸缩(scalable)的 twitter 应用的构建模式,在我们的讨论中,一个显而易见的问题就是数据库的可扩展性问题。要解答这个问题,我试图寻找隐藏在各种 NOsql 之后的共有模式,并展示他们是如何解决数据库可扩展性问题的。在本文中,我将尽力勾勒出这些共有的原则。
与我们先前通过昂贵硬件之类的手段尽力去避免失效的手段不同,NOsql实现都建立在硬盘、机器和网络都会失效这些假设之上。我们需要认定,我们不 能彻底阻止这些时效,相反,我们需要让我们的系统能够在即使非常极端的条件下也能应付这些失效。Amazon S3 就是这种设计的一个好例子。你可以在我最近的文章 Why Existing Databases (RAC) are So Breakable! 中找到进一步描述。哪里,我介绍了一些来自 Jason McHugh 的讲演的面向失效的架构设计的内容(Jason 是在 Amazon 做 S3 相关工作的高级工程师)。
通过对数据进行分区,我们最小化了失效带来的影响,也将读写操作的负载分布到了不同的机器上。如果一个节点失效了,只有该节点上存储的数据受到影响,而不是全部数据。
大部分 NOsql 实现都基于数据副本的热备份来保证连续的高可用性。一些实现提供了 API,可以控制副本的复制,也就是说,当你存储一个对象的时候,你可以在对象级指定你希望保存的副本数。在 GigaSpaces,我们还可以立即复制一个新的副本到其他节点,甚至在必要时启动一台新机器。这让我们不比在每个节点上保存太多的数据副本,从而降低 总存储量以节约成本。
你还可以控制副本复制是同步还是异步的,或者两者兼有。这决定了你的集群的一致性、可用性与性能三者。对于同步复制,可以牺牲性能保障一致性和可用 性(写操作之后的任意读操作都可以保证得到相同版本的数据,即使是发生失效也会如此)。而最为常见的 GigaSpaces 的配置是同步副本到被分界点,异步存储到后端存储。
要掌控不断增长的数据,大部分 NOsql 实现提供了不停机或完全重新分区的扩展集群的方法。一个已知的处理这个问题的算法称为一致哈希。有很多种不同算法可以实现一致哈希。
一个算法会在节点加入或失效时通知某一分区的邻居。仅有这些节点受到这一变化的影响,而不是整个集群。有一个协议用于掌控需要在原有集群和新节点之间重新分布的数据的变换区间。
另一个(简单很多)的算法使用逻辑分区。在逻辑分区中,分区的数量是固定的,但分区在机器上的分布式动态的。于是,例如有两台机器和1000个逻辑 分区,那么每500个逻辑分区会放在一台机器上。当我们加入了第三台机器的时候,就成了每 333 个分区放在一台机器上了。因为逻辑分区是轻量级的(基于内存中的哈希表),分布这些逻辑分区非常容易。
第二种方法的优势在于它是可预测并且一致的,而使用一致哈希方法,分区之间的重新分布可能并不平稳,当一个新节点加入网络时可能会消耗更长时间。一个用户在这时寻找正在转移的数据会得到一个异常。逻辑分区方法的缺点是可伸缩性受限于逻辑分区的数量。
更进一步的关于这一问题的讨论,建议阅读 Ricky Ho 的文章 NOSQL Patterns 。
在这个方面,不同的实现有相当本质的区别。不同实现的一个共性在于哈希表中的 key/value 匹配。一些市县提供了更高级的查询支持,比如面向文档的方法,其中数据以 blob 的方式存储,关联一个键值对属性列表。这种模型是一种无预定义结构的(schema-less)存储,给一个文档增加或删除属性非常容易,无需考虑文档结 构的演进。而 GigaSpaces 支持很多 sql 操作。如果 SQL查询没有指出特定的简直,那么这个查询就会被并行地 map 到所有的节点去,由客户端完成结果的汇聚。所有这些都是发生在幕后的,用户代码无需关注这些。
Map/Reduce 是一个经常被用来进行复杂分析的模型,经常会和 Hadoop 联系在一起。 map/reduce 常常被看作是并行汇聚查询的一个模式。大部分 NOsql 实现并不提供 map/reduce 的内建支持,需要一个外部的框架来处理这些查询。对于 GigaSpaces 来说,我们在 sql 查询中隐含了对 map/reduce 的支持,同时也显式地提供了一个称为 executors 的 API 来支持 map/reduce。在质疑模型中,你可以将代码发送到数据所在地地方,并在该节点上直接运行复杂的查询。
这方面的更多细节,建议阅读 Ricky Ho 的文章 Query Processing for NOSQL DB 。
NOsql 实现分为基于文件的方法和内存中的方法。有些实现提供了混合模型,将内存和磁盘结合使用。两类方法的最主要区别在于每 GB 成本和读写性能。
最近,斯坦福的一项称为“The Case for RAMCloud”的调查,对磁盘和内存两种方法给出了一些性能和成本方面的有趣的比较。总体上说,成本也是性能的一个函数。对于较低性能的实现,磁盘方 案的成本远低于基于内存的方法,而对于高性能需求的场合,内存方案则更加廉价。
内存云的显而易见的缺点就是单位容量的高成本和高能耗。对于这些指标,内存云会比纯粹的磁盘系统差50到100 倍,比使用闪存的系统差5-10倍(典型配置情况和指标参见参考文献[1])。内存云同时还比基于磁盘和闪存的系统需要更多的机房面积。这样,如果一个应 用需要存储大量的廉价数据,不需要高速访问,那么,内存云将不是最佳选择。
然而,对于高吞吐量需求的应用,内存云将更有竞争力。当 使用每次操作的成本和能量作为衡量因素的时候,内存云的效率是传统硬盘系统的 100 到 1000 倍,是闪存系统的 5-10 倍。因此,对于高吞吐量需求的系统来说,内存云不仅提供了高性能,也提供了高能源效率。同时,如果使用 DRAM 芯片提供的低功耗模式,也可以降低内存云的功耗,特别是在系统空闲的时候。 此外,内存云还有一些缺点,一些内存云无法支持需要将数据在 多个数据中心之间进行数据复制。对于这些环境,更新的时延将主要取决于数据中心间数据传输的时间消耗,这就丧失了内存云的时延方面的优势。此外,跨数据中 心的数据复制会让内存云数据一致性更能难保证。不过,内存云仍然可以在夸数据中心的情况下提供低时延的读访问。
近来我见到的最多的问题就是 “NOsql 是不是就是炒作?” 或 “NOsql 会不会取代现在的数据库?”
我的回答是——NOsql 并非始于今日。很多 NOsql 实现都已经存在了十多年了,有很多成功案例。我相信有很多原因让它们在如今比以往更受欢迎了。首先是由于社会化网络和云计算的发展,一些原先只有很高端的 组织才会面临的问题,如今已经成为普遍问题了。其次,已有的方法已经被发现无法跟随需求一起扩展了。并且,成本的压力让很多组织需要去寻找更高性价比的方 案,并且研究证实基于普通廉价硬件的分布式存储解决方案甚至比现在的高端数据库更加可靠。(进一步阅读 )所有这些导致了对这类“可伸缩性优先数据库”的需求。这里,我引用 AWS团队的接触工程师、VP, James Hamilton 在他的文章 One Size Does Not Fit Al l 中的一段话:
“伸缩性优先应用是那些必须具备无限可伸缩性的应用,能够不受限制的扩展比更丰富的功能更加重要。这些应用包括很多需要高 可伸缩性的网站,如 Facebook,MySpace,Gmail,Yahoo 以及 Amazon.com。有些站点实际上使用了关系型数据库,而大部分实际上并未使用。这些服务的共性在于可扩展性比功能公众要,他们无法泡在一个单一的 RDBMS 上。”
总结一下——我认为,现有的 sql 数据库可能不会很快淡出历史舞台,但同时它们也不能解决世上的所有问题。NOsql 这个名词现在也变成了 Not Only sql,这个变化表达了我的观点。
本书不求利,只图学术之便。感谢诸位大牛写了那么多的资料,如果您不愿意被引用,学生会重写相应的章节。
引用网志多篇,由于涵盖太广难以一一校队,特此致歉。
感谢Jdon,dbanotes,infoq和Timyang.您们分享和撰写了那么多有用的资料。
V0.1版本在2010.2.21发布,提供了本书的主题框架
v0.2版本在2010.2.24发布,因为一些外界原因,提前发布。完善各个示例,勘误,翻译部分内容。
v0.3版本将在3月份或之后发布
http://www.jdon.com/jivejdon/thread/37999 http://queue.acm.org/detail.cfm?id=1413264 http://www.dbanotes.net/arch/five-minute_rule.html http://www.infoq.com/cn/news/2009/09/Do-Not-Delete-Data http://www.infoq.com/cn/news/2010/02/ec2-oversubscribed http://timyang.net/architecture/consistent-hashing-practice http://en.wikipedia.org/wiki/Gossip_protocol http://horicky.blogspot.com/2009/11/nosql-patterns.html http://snarfed.org/space/transactions_across_datacenters_io.html http://research.microsoft.com/en-us/um/people/lamport/pubs/lamport-paxos.pdf http://en.wikipedia.org/wiki/Distributed_hash_table http://hi.baidu.com/knuthocean/blog/item/cca1e711221dcfcca6ef3f1d.html http://zh.wikipedia.org/wiki/MapReduce http://labs.google.com/papers/mapreduce.html http://nosql-database.org/ http://www.rackspacecloud.com/blog/2009/11/09/nosql-ecosystem/ http://www.infoq.com/cn/news/2008/02/ruby-mapreduce-skynet http://s3.amazonaws.com/AllThingsDistributed/sosp/amazon-dynamo-sosp2007.pdf http://labs.google.com/papers/bigtable.html http://www.allthingsdistributed.com/2008/12/eventually_consistent.html http://www.rackspacecloud.com/blog/2009/11/09/nosql-ecosystem/ http://timyang.net/tech/twitter-operations/ http://blog.s135.com/read.PHP?394 http://www.programmer.com.cn/1760/