设为首页 收藏本站
查看: 760|回复: 0

[经验分享] MongoDB与Tokyo Tyrant性能比较:基础CRU操作(转自:老赵)

[复制链接]
累计签到:21 天
连续签到:1 天
发表于 2015-7-10 08:00:40 | 显示全部楼层 |阅读模式
  (注:因为最近项目需要,将MongoDB和TT Server做了一下对比,准备用MongoDB做一个后端缓存,Leader要求单个Get控制在1ms作用,尼玛坑死爹了,Redis都差不多那个数了)
  以前的项目大都把数据存放在关系型数据库中,关系型数据库的优势在于使用普及,资料丰富,且有大量辅助类库来简化开发。当然它们的问题比较明显的,一是在数据量上升的情况下伸缩性比较差,且进行结构调整的代价比较高。因此现在有个所谓NoSQL的“运动”也逐渐普遍起来了,它便是借助一些非关系型存储方式来开发项目(个人认为其实将它解释为Not Only SQL更为合适)。因此在新项目里,我也想尝试一下使用之前一直只是“听说”的存储方式。
  在和同事的交流过程中,我了解到他们的项目正在尝试使用Tokyo Tyrant(后称TT)进行存储,并且据说效果不错,因此我一开始也打算尝试使用TT进行主要存储,为此也花了一定时间为其编写.NET平台下的驱动程序。不过在驱动程序的开发过程中,我逐渐意识到TT的功能有着严重的限制,似乎并不适合作为接下来项目的主要存储方式。因此,我又将眼光转向了之前关注过的MongoDB上。MongoDB也是NoSQL的代表之一,是一个面向文档的,架构灵活(Schema-less)的存储方式,在仔细阅读相关资料之后,我发现它的功能与TT相比可谓天上地下,非常适合许搭建各类项目(关于这点以后有机会再谈)。
  不过,既然选择NoSQL的原因是性能,那么他们的性能表现究竟如何呢?TT的性能表现在业界非常出名,而MongoDB的使用便相对较少了(当然,官网列举了不少案例,最近著名的开源网站SourceForge也打算使用MongoDB重新设计他们的网站)。为此,我决定亲手比较一下两者的性能表现。
测试环境及数据
  由于缺乏合适的环境,因此我不得不在我的MBP上进行这次性能比较,参数如下:

  • OS:Mac OS X v10.6.2(Snow Leopard)
  • RAM:4GB / 1067MHz / DDR 3
  • CPU:2.53GHz Intel Core 2 Duo
  • 64-bit Kernel and Extensions:Yes
  • TT在64 bit环境下编译,MongoDB使用64 bit版本。
  在测试执行时,我尽量关闭多余的应用程序,避免其它因素造成影响。同样,由于条件限制,我只得把客户端和服务器跑在同一台机器上。测试代码使用Ruby编写,这是由于两者都有官方提供的驱动程序。此外,由于我对于两者的优化都不太熟悉,因此它们都使用了默认的配置。
  关于测试数据,我将存入110万条“新闻”数据,包含以下字段:

  • ID:标识,32位整数,带索引
  • Title:标题,字符串
  • CategoryID:分类ID,32位整数,带索引
  • CreateTime:日期,保存为32位整数,带索引
  • UserID:用户ID,32位整数,带索引
  • Tags:标签集合,字符串数组,带索引
  • Source:来源,字符串
  • SourceUrl:来源URL,字符串
  • Status:状态,32位整数
  为了相对接近真实的环境的数据分布特征(便于以后进行查询操作比较),我设计了这样的测试数据(具体可阅读代码):

  • 2万个分类,分别拥有10个至100条新闻,总共110万条记录。
  • 1万个用户,根据分类id取模得到其归属。
  • 创建时间从2010年1月1日起递增,每条记录增加1秒。
  • 每条记录拥有2到6个Tag,除了其中一个之外,都从一个1.7万个Tag库中获取。
  • 每条记录的字符串字段都不长(20-30字符)
  由于TT只支持字符串的值(但可以建立数字索引,会将字符串当作数字来识别),因此事实上所有的值都会转化为字符串进行保存。此外,由于存在“根据Tag查找新闻”的业务,因此对于Tags字段也建立了索引,其中MongoDB直接支持对字符串数组的索引(索引其中每个元素),而在存入TT时则转化为空格分隔的字符串,并为其建立倒排索引(Token Inverted Index)以便进行全文查找。
  在存储方式上,所有数据将放入MongoDB的同一个集合内,而TT则选用Table Database存储结构。在使用TT时,另一种做法是完全使用键值对来保存一条记录的各个字段,不过这样做会大大限制TT的功能,或是会为系统编写带来额外的复杂度,便不考虑Hash / B+ Tree / Fixed-length等存储方式了。
插入操作性能比较
  具体代码在tt-insert.rb及mdb-insert.rb文件中。两段代码均使用一个连接,使用循环每次插入一条:由于如果每次都建立连接,会在TCP/IP连接的打开关闭上消耗大部分时间,由于实际项目中基本都会使用连接池等机制来复用连接,因此这方面便不多做考虑;再者,由于实际插入时几乎不可能批量操作,因此这里并不使用两者提供的批量插入功能。脚本每插入10万条记录便打印出所耗时间,结果如下:
  
  从结果上看,MongoDB大约有10%的领先,不过总体来说两者的差距不大。值得一提的是,TT在数据量越大的情况下,每插入10万条记录的耗时越长(也从同事的使用过程中确认了这一点)。因此,一开始两者插入速度几乎没有差距,但是慢慢地TT便落后于MongoDB了。目前推测这可能是TT的Table Database存储结构特有的问题,不知道随着数据量的增长TT表现如何,因为对于一个大型系统来说,100多万条记录实际上只是一个很小的数目。
  有同事推测,TT插入性能低是因为建立了Tags字段的倒排索引,于是我也测试了不在Tags字段上建索引的情况。令人惊讶的是,同样去除Tags字段的索引之后,MongoDB的性能提升超过20%,而TT的性能提升却微乎其微。
  值得一提的是,放入相同的记录之后,TT的文件为400多M,但MongoDB则为整整2G。因此推测这是MongoDB进行空间预分配的结果,邮件列表上的这个讨论也证实了这一点。此外,上面每次测试都是从零开始的,经测试如果在插入前为MongoDB预分配文件空间,则性能还会有些许提高。
通过主键获取记录性能比较
  具体代码在tt-get-by-key.rb及mdb-get-by-key.rb文件中。两段代码同样均使用一个连接,使用循环进行100万次Get操作,每次都随机获取一个110万以内的数字,并作为ID进行Get操作。同样,每10万次Get操作后打印出所耗时间,结果如下:
  
  在Get操作方面,MongoDB有大约20%的领先。不过从实际情况分析,这方面的差距也不是太大,因为在项目中根据主键获取记录的操作8成以上都是落在缓存上的,因此在这方面对存储的要求并不高。
通过主键更新记录性能比较
  具体代码在tt-update-by-key.rb及mdb-update-by-key.rb文件中。两段代码各自使用同一个连接,使用循环进行大量的更新操作。每次随机获取一个110万以内的数字,并作为ID更新其CreateTime、Title、Source、SourceUrl、Status五个字段。结果如下:
  
  首先是MongoDB的三次测试结果,每次更新100万条数据。从数据上看,三次查询的性能越来越高,这个现象在重启服务器之后可以重现(三次测试之间并没有重启服务器)。
  
  请注意,TT的三次测试均只更新了10万条记录(因为100万条记录耗时太长)。和MongoDB类似,一开始查询性能较差,但是会慢慢提高,这个现象在重启服务器后也能重现,于是猜测是缓存的结果。即便如此,TT的更新时的最高速度只有大约没秒1500次,而MongoDB却超过了每秒5000次。这是因为TT在功能上有硬伤:它无法像SQL的UPDATE语句那样更新某条记录的部分字段,因此必须全部取出,修改后再整体写入。而MongoDB支持高效的直接修改——这也成为MongoDB放在首页上的“招牌功能”。
  因此,TT对于“更新某个分类下所有新闻的状态”这样的操作会很不适应,而它的这个限制导致我们很难实现如“乐观并发控制”这样的手段。此外,在实际应用中客户端与服务器不会使用本地连接,因此在生产环境中TT和MongoDB在这方面的差距可能会更明显一些。
总结
  到目前为止,我们测试了TT和MongoDB在CRU三种基本操作下的性能,似乎MongoDB全面胜过Tokyo Tyrant。不过需要强调的是,这个测试还很不全面:它没有使用合适的环境,也没有对两者进行适当的优化。此外,两者在并发情况下,或是同时读写下的表现如何也是值得进一步考察的,我也会设计更多的测试用例。因此,这里的数据仅供参考,如果有合适的环境我也会重新进行测试。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-84954-1-1.html 上篇帖子: (转帖)Mongodb 自增id 实现 下篇帖子: 关于MongoDB,你可能不知道的十件事
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表