(转) Crittercism: 在MongoDB上实现每天数十亿次请求
MongoDB的扩展能力可以满足你业务需求的增长——这也是为什么它的名字来源于单词humongous(极大的)的原因。当然,这并不是说你在 使用MongoDB的路上并不会碰到一些发展的痛点。Crittercism是一家专门为手机应用程序提供技术支持的初创公司,该公司在过去两年间发展迅 猛,其运营总监Mike Chesnut于最近发表了一篇博文,描述了公司在快速发展的过程中遇到的一些MongoDB陷阱以及从中学到的经验。在今年6月将会举行的MongoDB World大会上,Mike Chesnut将会介绍Crittercism是如何在MongoDB上实现每秒30,000次请求的。
背景
Crittercism提供了世界上首个领先的移动应用 性能管理(mAPM)解决方案。其SDK被嵌入了成千上万的应用中,在全世界有近十亿用户。该公司致力于收集性能数据,例如错误报告、崩溃诊断细节、面包 屑(breadcrumbs,指导航记录)、设备/载体/OS统计和用户行为等。这些数据大部分是非结构化的,并且随着应用程序、版本、设备和使用模式的 不同变化很大。
Crittercism将所有的这些数据存储在MongoDB中以便于收集原始信息供用户以各种方式使用,同时还提供了将数据概括到易消化、可操作 的维度所需的分析功能。在过去的18个月中,Crittercism每天的请求量增长了超过40倍,主要的MongoDB集群现在存储的数据量超过了 20TB。
路由
MongoDB文档显示,最常见的拓扑结构是在每一个客户端系统上包含一个路由器——一个mongos进程。Mike Chesnut表示他们开始的时候就是这样做的,并且在很长的一段时间内这种方式工作的很好。
但是随着生产环境中前端应用程序服务器的数量从十几台增长到几百台,Crittercism发现mongos路由和mongod分片服务器之间建立了几百、有时候甚至是几千个连接,负载非常重。这意味着每当chunk平衡(MongoDB分片集群为了保持数据均匀分布所必须使用的平衡措施)发生的时候传送存储在配置数据库中的chunk位置信息都需要花费相当长的时间。这是因为每一个mongos路由都必须清楚地知道每一个chunk都存在于集群中的哪些位置。
对于这一问题Mike Chesnut表示:
我们发现将mongos路由合并到少数几台主机上能够减轻这个问题。我们产品的基础设施在AWS上,所以我们在每个可用区域内部署了2台mongos服务器。这样每个区域都有冗余,同时还为客户端提供了到mongos路由的最短网络路径。我们也担心请求路径中会增加额外的驿站,但是通过Chef配置所有的客户端让它们仅与自己区域内的mongos路由通信能够最小化这个问题。
这种拓扑结构的变化极大地减少了mongos路由和mongod分片服务器之间的连接的数量(这一点可以通过MMS衡量),并且没有明显地降低应用程序的性能。此外我们还对MongoDB做了一些改进,让它能够更有效地完成mongos更新和内部一致性检查。借助于这些措施以及新的网络拓扑结构,我们现在能够在不引发性能问题的情况下平衡集群中的chunk。
分片替换
Crittercism公司遇到的另一个场景是需要动态地替换mongod服务器从而迁移到更大的分片上。Mike Chesnut表示:
对于这一问题我们再次采用了文档中推荐的最佳部署实践,将MongoDB部署到使用大型RAID 10磁盘阵列并且运行着xfs的服务器实例上。我们使用了有16块磁盘的AWS m2.4xlarge实例。处于性能方面的考虑,我们使用了基本的Linux mdadm,但是这样也牺牲了磁盘配置灵活性。这样做的结果是当我们需要为分片分配更多容量的时候,我们需要执行一个迁移程序,有时候这会花费几天的时间。这意味着我们不仅需要提前做出合适的计划,还需要了解整个流程从而对其进行监控并在出现错误的时候做出响应。
当所有副本的磁盘利用率大致相等的时候我们会开始一个复制集。首先我们会创建一个新的服务器实例,为它分配更多的磁盘,然后使用rs.add()方法将其添加到这个复制集中。
新副本将进入STARTUP2状态并在该状态保持一段时间(在我们的情况下通常是2到3天),在此期间它首先会复制数据,然后会通过操作日志(oplog)复制赶上进度并构建索引。索引的构建通常会停止复制过程(注意,这个行为在MongoDB 2.6中必定会改变),所以严格来说复制延迟时间并不是一直在缩短——在一段时间内它会稳步缩短,然后当一个索引构建发生的时候复制便会暂停,延迟时间会再次延长。一旦索引构建完成,那么复制将会再次恢复。值得注意的是,当索引构建发生的时候,mongostat以及其他任何需要读锁的操作都将被阻塞。
副本最终会进入SECONDARY状态并具备完整的功能。这时候我们可以rs.stepDown()一个旧的副本,关闭它上面运行的mongod进程,然后通过s.remove()方法将它从复制集中移除,让服务器做好退出的准备。
之后复制集中的每一个成员都会重复这个过程,直到这些成员都被使用更大磁盘的新实例替换为止。
虽然这个过程有点耗时,有点乏味,但是却可以让我们以一种优雅的方式增长数据库的足迹,不会对客户造成任何影响。
结论
和使用其他任何技术一样,运营大规模MongoDB也需要一些知识,有些知识你可以从文档中获取,而另一些则来自于经验。通过尝试一些不同的策略, 例如上面提到的那些,你可以发现一些之前并不明显的灵活性。对于Crittercism的运维团队而言,合并mongos路由层无论是在性能方面还是在管 理性方面都是一个巨大的成功,此外开发上面提到的迁移程序让我们能够持续地发展,在满足自己业务需要的同时不会影响我们的服务或者客户。
(转) Crittercism: 在MongoDB上实现每天数十亿次请求的更多相关文章
- C# mongodb [上]
概述 MongoDB是一个高性能,开源,无模式的文档型数据库,使用C++开发.是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是 ...
- Android填坑系列:在小米系列等机型上放开定位权限后的定位请求弹框
背景: 近期因实际项目需要,在特定操作下触发定位请求,取到用户位置及附近位置. 问题: 经初步选型,最终决定接入百度定位,按照百度定位SDK Android文档,接入过程相对顺利.但随后发现,在小米系 ...
- Java中使用HttpPost上传文件以及HttpGet进行API请求(包含HttpPost上传文件)
Java中使用HttpPost上传文件以及HttpGet进行API请求(包含HttpPost上传文件) 一.HttpPost上传文件 public static String getSuffix(fi ...
- django MongoDB上传文件
django上传文件,查询到的资料都是用的django自己的models.Model类,去定义一个FileField类型的存储文件,并且在里面加一句upload_to,如下所示: 但是如果用mon ...
- springboot实现mongodb上传下载
1.上传: private static Logger log = LoggerFactory.getLogger(MongoDbFSUtil.class); private static final ...
- MongoDB上的索引
1. 将索引建在number键上名为nameIndex并且为正序索引({number:-1}为倒序索引) 如: db.list名.ensureIndex({number:1},{name:" ...
- 在 MongoDB 上模拟事务操作来实现支付
我们的产品叫「学海密探」,属于在线教育行业,产品需要有支付功能,然而支付最蛋疼是什么?有人会说是支付宝和微信等支付接口的接入开发!没错,但支付接口的开发算是比较简单的了,我觉得凡是跟钱有关系的操作最重 ...
- MongoDB副本集配置系列十:MongoDB local库详解和数据同步原理
1:local库是MongoDB的系统库,记录着时间戳和索引和复制集等信息 gechongrepl:PRIMARY> use local switched to db local gechong ...
- 百万级高并发mongodb集群性能数十倍提升优化实践
背景 线上某集群峰值TPS超过100万/秒左右(主要为写流量,读流量很低),峰值tps几乎已经到达集群上限,同时平均时延也超过100ms,随着读写流量的进一步增加,时延抖动严重影响业务可用性.该集群采 ...
随机推荐
- Gym 100637F F. The Pool for Lucky Ones 暴力
F. The Pool for Lucky Ones Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10 ...
- MyBatis之七:使用generator工具
可以将mybatis理解成一种半自动化orm框架,通过注解或者配置xml映射文件来手写相关sql语句,不能像我之前介绍orm的文章那样全对象化操作数据库增删改查.其实你会发现,手写配置xml映射文件是 ...
- oracle 基本语句练习(一) where, between ,null, like,转义字符,order by
1 where 筛选关键字; select * from emp where job >'CLERK' 从emp表中列出 job值大于'CLERK'的项 (由于比较的是字符串,所以加单引号 ...
- JS 文本输入框放大镜效果
JS 文本输入框放大镜效果 今天下午研究了下 "文本输入框放大镜效果" 当然KISSY官网也有这种组件 请看kissy demo 其实这种效果 对于很多童鞋来说 应该并不陌生!我今 ...
- Metadata Lock原理7
http://blog.itpub.net/22664653/viewspace-1791744/ 一 简介 通过前面两篇文章的介绍,相信读到这里的各位对MDL 锁已经有了比较深入的了解了,本文将结合 ...
- Helpers\TableBuilder
Helpers\TableBuilder Table builder helper is a class that would help you to create tables in MySQL ( ...
- 如何使用Linux命令dhclient
如何使用Linux命令 dhclient The Internet Systems Consortium DHCP Client, dhclient, provides a means for con ...
- Asp.Net 之 通过调用 WScript.Shell 启动本地 exe 程序时产生“ automation服务器不能创建对象 ”的错误
我们经常需要通过生成 ActiveXObject("WScript.Shell"); 来调用某一exe文件. 设置网页打印的页眉页脚为空: var HKEY_Root,HKEY_P ...
- css笔记08:id选择器之父子选择器
1.父子选择器 (1)01.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...
- C语言有关数组的几点
动态大小数组 先来看一段代码: ; int a[n]; int i; ;i<n;i++) { a[i]=i; printf("%d\n",a[i]); } 我在声明数组a时, ...