http://www.distream.org/?p=10html
NoSQL解决方案比较redis
NoSQL Solution: Evaluation and Comparison: MongoDB vs Redis, Tokyo Cabinet, and Berkeley DBsql
你也许认为这是NoSQL (Not Only SQL)广告宣传的另外一个博客。mongodb
是,这的确是。数据库
可是若是这个时候你仍就为寻找一个可行的NoSQL解决方案而苦恼,读完这篇后你就知道该作什么了。apache
当我之前参与Perfect Market的内容处理平台时,我拼命地尝试寻找一个极端快速(从延时和处理时间上)和可扩展的NoSQL数据库方案,去支持简单地键/值查询。缓存
在开始前我预约义了需求:网络
快速数据插入(Fast data insertion)。有些数据集可能包含上亿的行(KV键值对),虽然每行数据很小,但若是数据插入很慢,那将这个数据集传入数据库将须要花几天时间,这是不可接受的。大数据集上的快速随机读取(Extermely fast random reads on large datesets)。在全部数据集上的一致的读写速度。这个意思是说,读写速度不能由于数据如何保持和index如何组织就在某个数据量上拥有很好的值,读写速度应该在全部的数据量上均衡。有效的数据存储。原始的数据大小和数据被导入数据库中的大小应该相差不大。很好的扩展性。咱们在EC2的内容处理节点可能产生大量的并发线程访问数据节点,这须要数据节点能很好的扩展。同时,不是全部的数据集是只读的,某些数据节点必须在合适的写负载下很好的扩展。容易维护。咱们的内容处理平台利用了本地和EC2资源。在不一样的环境里,同时打包代码,设置数据,和运行不一样类型的节点是不容易的。预期的方案必须很容易维护,以便知足高自动化的内容处理系统。拥有网络接口。只用于库文件的方案是不充足的。稳定。必须的。并发
我开始寻找时毫无偏见,由于我从未严格地使用过NoSQL产品。通过同事的推荐,而且阅读了一堆的博客后,验证的旅程开始于Tokyo Cabinet,而后是 Berkeley DB库, MemcacheDB, Project Voldemort, Redis, MongoDB。oracle
其实还存在不少流行的可选项,好比Cassandra, HBase, CouchDB…还有不少你能列出来的,但咱们没没有必要去尝试,由于咱们选择的那些已经工做得很好。结果出来至关的不错,这个博客共享了我测试的一些细节。
为了解释选择了哪一个以及为何选择这个,我采纳了同事Jay Budzik(CTO)的建议,建立了一张表来比较全部方案在每个需求上的状况。虽然这张表是一个过后的事情,但它展现了基本原理,同时也会对处于决策的人们带来帮助。
请注意这个表不是100%的客观和科学。它结合了测试结果和个人直觉推导。颇有趣,我开始验证时没有偏见,但测试完全部的后,我也许有了一点偏爱(特别是基于个人测试用例)。
另外一个须要注意的是这里的磁盘访问是I/O密集性工做负载里最慢的一个操做。相对于内存访问, 这是毫秒与纳秒的关系。为了处理包含上亿行的数据集合,你最好给你的机器配置足够的内存。若是你的机器只有4G内存而你想处理50GB的数据且指望较好的速度,那你要么摇晃你的机器,要么用个更好的,不然只能扔到下面全部的方案,由于它们都不会工做。
看了这张表,你也许能猜到我选了哪一个方案。不要着急,让我详细说明每个方案。
Tokyo Cabinet (TC)是一个很是好的方案也是我第一个验证的。我如今仍然很喜欢它,虽然这不是我最后选择的。它的质量惊人的高。哈希表数据库对于小数据集(低于2千万行)惊人的快,水平扩展能力也很好。TC的问题是当数据量增长时,读写的性能降低的特别快。
Berkeley DB(BDB)和MemcacheDB (BDB的远程接口)是一个较老的结合物。若是你熟悉BDB,而且不是很是依赖速度和功能集合,好比你愿意等几天去加载大数据集到数据库里而且你接受通常但不优秀的读速度,你仍可使用它。对于咱们,事实是它花了太长的时间来加载初始数据。
Project Voldemort是惟一一个基于Java和云计算的方案。在验证前我有很高的指望,可是结果却有点失望,缘由是:
BDB Java版本让个人数据膨胀得太厉害(大概是1比4,而TC只有1比1.3)。基本上存储效率很是低。对于大数据集,它就是灾难。当数据变得很大的时候,插入速度下降得很快。当大数据集被加载时偶尔因为没法预测的异常而崩溃。
当数据膨胀得太厉害而且偶尔系统崩溃时,数据加载尚未完成。只有四分之一的数据被传播,它读速度还能够但不出色。在这个时候我想我最好放弃它。不然,除了上面列的那些须要优化,JVM可能让我操更多的心让个人头发灰的更多,虽然我已经为Sun工做了五年。
Redis是一个极好的缓存解决方案,咱们也采用了它。Redis将全部的哈希表存在内存里,背后有一个线程按照预设的时间定时将哈希表中的快照存到磁盘上。若是系统重启,它能够从磁盘上加载快照到内存,就像启动时保温的缓存。它要花几分钟来恢复20GB的数据,固然也依赖你的磁盘速度。这是一个很是好的主意,Redis有一个合适的实现。
可是在咱们的用例里,它工做得并很差。后台的保存程序仍妨碍了咱们,特别是当哈希表变得更大时。我担忧它会负面地影响读速度。使用logging style persistence而不是保存整个快照,能够减缓这些数据转存的影响,可是数据大小将会膨胀,若是太频繁,将最终影响恢复时间。单线程模式听起来不是可伸缩的,虽然在个人测试里它水平方向扩展的很好:支持几百个并发读。
另外一个事情干扰个人是Redis的整个数据集必须适合物理内存。这点使得它不容易被管理,象在咱们这样在不一样的产品周期形成的多样化的环境里。Redis最近的版本可能减轻了这方面的问题。
MongoDB是至今我最喜欢的,在我所验证的全部解决方案中,它是胜出者,咱们的产品也正在使用。
MongoDB提供了不一样寻常的插入速度,可能缘由是延迟写入和快速文件扩展(每一个集合结构有多个文件)。只要你拥有足够的内存,上亿的数据行能在几小时内插入,而不是几天。我应该在这提供确切的数据,但数据太具体(与咱们的项目有关)不见得对别人有帮助。但相信我,MongoDB提供了很是快的大数据量插入操做。
MongoDB使用内存映射文件,它通常花纳秒级的时间来解决微小的页面错误,让文件系统缓存的页面映射到MongoDB的内存空间。相比于其它方案,MongoDB不会和页面缓存竞争,由于它使用和只读块相同的内存。在其它方案里,若是你分配给太多的内存给工具自身,那盒子里的页面缓存就变得不多,而且通常来讲想让工具的缓存彻底地预热不是很容易,或者没有一个有效地方法(你绝对不想事先去从数据库里读取每一行)。
对于MongoDB,能够很是容易地作一些简单的技巧让全部的数据加载到页面缓存。一旦在这个状态,MongoDB就很像Redis,在随机读上有较好的性能。
在我另外一个测试中,200并发客户在大数据集(上亿行数据)作持续的随机读取,MongoDB表现了整体上的400,000QPS。测试中,数据在页面缓存里预热(事先加载)。在随后的测试中,MongoDB一样显示了在适度的写负载下拥有很是好的随机读取速度。在相对来讲一个大的负载下,咱们压缩了数据而后将它存入MongoDB,这样就减小了数据大小因此更多的东西能放入内存。
MongoDB提供了一个方便的客户端工具(相似MySQL的),很是好用。它也提供了高级的查询功能,处理大型文档的功能,可是咱们尚未用到这些。MongoDB很是稳定,基本不须要维护,处理你可能要监控数据量增大时的内存使用状况。MongoDB对不一样的语言有很好的客户端API支持,这使得它很容易使用。我不用列举它全部的功能,但我想你会获得你想要的。
虽然MongoDB方案能够知足大多数NoSQL的需求,但它不是惟一的一个。若是你只须要处理小数据量,Tokyo Cabinet最合适。若是你须要处理海量数据(PB千兆兆)并拥有不少机器,并且延时不是个问题,你也不强求极好的响应时间,那么Cassandra和HBase均可以胜任。
最后,若是你仍须要考虑事务处理,那就不要弄NoSQL, 直接用Oracle。
注:这篇文章写得实在是精彩,将nosql的几种数据库比较的很细。因此忍不住转载的。开头的两个连接为原文出处。以及翻译版。