MongoDB应用实践分享

1 为什么选择MongoDB

  • 我们做的是互联网产品,要小步快跑,需要快速迭代发布,产品需求变更频繁,且无事务性的强要求,传统的关系型数据库并不适合我们。

  • 纵观当下流行的NoSql数据库,发现MongoDB这个数据模型自由、支持数据容灾、支持容量水平扩展、文档丰富详尽、中文社区活跃的文档型数据库非常适合我们,于是我们就采用了MongoDB作为我们产品主要的持久化层。

2 我们怎么使用

2.1 放任式管理
起初数据量小,MongoDB并无专人维护,创建索引也比较随意,数据库也并未出现什么问题。
2.2 专人维护
随着用户的增多,产品功能越来越丰富,数据量快速增长,并发读写增高,数据库问题越来越严重,还曾出过系统“雪崩”,大部分业务请求超时,系统大部分功能不可用。就像“出来混的迟早都要还一样”说的一样,前期偷懒欠的“技术债”迟早要还的,我们后续安排了专人维护数据库,并安排评审数据库相关的设计。
2.3 不同数据的存储规划
我们线上部署模式,从原来单一的分片集群(5分片)模式,扩展到副本集模式和单例模式。我们把统计运营数据剥离出来存储在云服务厂商的MongoDB副本集中,使用MongoDB单实例存储部分业务的消息日志用于排查问题。

3 在问题中成长

3.1 遇到过的问题
早期由于团队对MongoDB不够熟悉,对研发人员无太多约束,出现过创建的索引过多进而导致MongoDB占用内存过多,也出现过没命中索引的查询导致扫描全表或者没命中合理的索引导致扫描过多的文档使MongoDB服务器cpu被跑满,也出现过一个携带排序要求的查询占用的内存超过了MongoDB 32M的限制而查询失败。

由于某些业务特点我们在一天中某个时间点有写的峰值,导致MongoDB的服务器上IO和cpu都特别的高,由于我们业务中也有很多统计需求,导致MongoDB服务器执行了一些过多复杂的查询,使得cpu持续标高且业务层没缓存查询结果。

3.2 如何解决
- 在做需求分析时确认主要的读写模型,最好是和产品经理确认好后期可能发生的比较重大的变更,在设计上做好对变更的支持
- 对数据库表和索引的设计做评审,减少不必要的索引的创建,优化索引,减少内存占用,提升写的性能
- 不要把大量复杂的业务逻辑放在数据库中做,需要有一个平衡点,该缓存的数据缓存,该业务自己统计排序的业务自己统计排序
- 对于写高峰使用消息队列来削峰,写请求先写消息队列,然后再由专门的同步程序把数据慢慢写入到MongoDB数据库中
- 使用Redis构建了一个自研的分布式缓存系统,用于缓存统计结果和部分热点数据,减少对MongoDB数据库持久化层的冲击
- 组织团队人员定期分享MongoDB的相关知识点,提升团队整体使用MongoDB的能力

3.3 建议
- 那种一对多的关系尽量不要在数组字段上建立索引,可以单独创建一个表用多条记录来表示1多N的关系再在这个表上创建非数组索引,MongoDB内部数组索引也是创建出多个单独的索引
- 分片集群部署时不要过早的创建分片建,在业务稳定之后再创建分片建
- 给balance设置窗口期避开业务高峰
- 构建副本集时根据业务数据量调大oplog,oplog的大小决定了你数据库维护抢修的时限

4 数据安全保障

4.1 容灾方面
我们核心的数据存储在分片集群中,在每个分片复制集中我们采用3副本结构,为了容灾需求把其中一个副本部署在一个单独的数据中心
4.2 数据备份方面
我们使用ops做分片集群的全量备份和增量备份,这个备份是放在另外的一个数据中心
4.3 恢复演练
我们定期的使用ops备份的数据恢复到测试环境中,做恢复演练,保证备份数据的可用性。

5 数据库业务监控

5.1 服务器监控
使用云服务器厂商提供的监控告警机制(邮件、短信等),对cpu,内存,磁盘,带宽等进行监控,有专人负责。
5.2 读写监控
使用ops对核心数据分片集群做读写监控,可以看到不同时间段的读写情况。
5.3 服务健康监控
使用ops对整个分片集群中各个mongod实例的“健康状况”进行监控,而不用登录每个服务器使用mongo接入各个复制集的主节点去看这个复制集的“健康状况”
5.4 业务级别和语句级别的监控
正常一个系统是有多个环节组成了,当数据库读写压力巨大时,你无法精准定位到达是那个地方出了问题?那么该怎么办?如何做到业务和语句级的监控呢?
这个是我要分享的一个核心,因为ops提供的监控是有限的,其粒度是很粗的并不能细致到具体业务或者具体的某个查询(商业版的不知道有没有支持),那么我们怎么做到业务级别甚至是语句级别的监控呢?
5.4.1 业务级别的监控
我们这边的思路是在所有的数据库读写函数中添加一个统计的钩子,对所有的数据库读写进行统计,定期监视这个统计结果,从统计结果中分析系统可能存在的bug,或者不合理的读写。
5.4.2 语句基本的监控
语句级别如何监控呢,改MongoDB源代码?答案是否定的。我们利用MongoDB默认会把操作超过100ms以上的语句输出到日志文件中的特性,开发专门的监控程序用于分析MongoDB日志中所有的慢操作语句,对这些语句进行归类整理汇总,最终以报表的形势展现出来,那些语句有问题需要优化一目了然。

6.写在最后
这些就是我们在MongoDB实践上的经验,希望能对大家有所帮助。

本文作者:码龙喵

MongoDB应用实践分享》有1个想法

发表评论