mongodb 阶段性技术总结

生产环境最佳实践

1.linux 系统:
1】关闭文件系统/分区的atime 选项
Vi /etc/fstab
在对应的分区项后面添加noatime ,nodiratime
LABEL=/1 / ext3 defaults 1 1
LABEL=/data1 /data ext4 defaults,noatime,nodiratime 1 2


2】设置文件句柄4k+,目前该配置已经集成到启动脚本中。
Vi /etc/security/limit.conf
* soft nproc 65536
* hard nproc 65536
* soft nofile 65536
* hard nofile 65536


3】不要使用large vm page (不要使用大内存页选项)
Linux 大内存页参考:http://linuxgazette.net/155/krishnakumar.html
4】用dmesg 查看主机的信息。
2.linux 文件系统的选择:
Mongodb 采用预分配的大文件来存储数据,咱们推荐
1】ext4
2】xfs
3.内核版本:
网络上对2.6.33-31 以及2.6.32 的表现持怀疑度, 而强力推荐2.6.36
4.线程堆栈的尺寸
默认的线程堆栈尺寸为10m ,调整为1m ,已经集成在启动脚本中。

项目过程当中的总结与建议

1.大小写问题
mongodb 是默认区分大小写的,可是这会不会衍生出跟mysql 同样的问题?(mysql 区
分大小写,致使windows 与linux 下的表名,字段名不一致)。
若是无特别用途,建议表名,字段名所有用小写字母。

2.尽量的缩短字段名的长度
mongodb 的schema free 致使了每笔数据都要存储他的key 以及属性,这致使了这些数
据的大量冗余。开发同事也许考虑到,从易读性出发设计的key 基本比较长,基本都是按
照起字面意思去设计的。这致使key 很长。对应的数据存储占用了很大的空间。
必要的时候,能够考虑创建一个key 与实际意义的map 表,尽可能下降key 的长度。
示例定义:
// 基本信息
static final String _ID = "_id";
static final String STATUS_CODE = "sc";
// 缓冲
static final String DATE = "date";
static final String MAX_AGE = "age";
// 内容
static final String CONTENT = "content";
static final String CONTENT_TYPE = "ctype";
static final String CONTENT_LENGTH = "clen";
static final String ZIP = "zip";
3. mongodb 单表最大索引数为64
无索引排序的最大数据量为4M, 超过则报错退出。
建议where 条件尽可能落在索引字段上,排序字段须要创建索引,索引的使用原则与oracle
mysql 一致,尽可能下降索引数量,索引长度。
mongodb 的查询每次只能用到一个索引,对数据的查询不会“并发”执行
例如: db.tab.find({'id'=1,'name'=2}) 若是‘id’,‘name' 列上分别有索引
对查询效率提高意义不大,若是索引为('id','name') 则大幅提高效率。

4.mongodb 添加字段
若是添加字段且带有default 值,须要所有数据都要修改,这也是设计阶段须要考虑的
事情,这个问题的另一种解法是应用代码里作一次判断。

5.测试过程的密码问题
对于用做数据库使用的Mongodb,在代码测试阶段都应加上密码验证,目前上线阶段基
本都会在密码验证方面出现问题(作缓存使用的能够不作密码验证)。

6.数据源链接方式
使用链接池模式,尽可能减小认证带来的性能额外消耗
建议采用标准的uri 链接方式: mongodb://user:passwd@host:port,host:port/db

7.Mongodb日志量
正常状况下不须要开启-v 日志选项。
Mongodb 的-v 日志适合在开发环境的调试线上部署不建议采用这个参数,目前线上
部署的状况,-v 日志一天也会有几个G 的日志量,去掉这个参数,跟数据查询相关的操做
就不会记日志了,数据库的内部的重要操做仍是会写日志的。

8.链接数大小的设置
Mongodb 驱动程序采用的链接池的方式链接到数据库,目前从观察到的状况是应用一
开启便根据变量的设置,创建所有链接,而后提供给程序使用,而且一旦其中某个链接
到数据库的访问失败,则会清空整个链接池到这台数据库的链接,并从新创建链接。
而mongodb 对中断链接的垃圾清理工做则是懒惰的被动清理方式,若是驱动程序端配
置的链接数过大,一旦发生重连,则会致使mongo 端堆积大量的垃圾链接数据,致使
主机资源耗尽。
建议: mongodb 驱动的链接池大小的设置通常应该控制100 如下,通常状况30-50 足
够支撑应用访问。

9.锁的问题
Mongodb 对数据库的访问所有加锁,若是是查询请求则设置共享锁,数据修改请求,
则设置全局排他锁,而且是实例级别的排他锁。而且写锁会阻塞读请求,若是长时间持有
写锁,会阻塞整个实例的读请求。
部署建议:
1】通常状况下,建议不一样的应用不要合用一套示例。
2】若是资源不知足,须要合用,应该具备相同属性的应用合用一套实例。
例如合同mongo 的应用都是读多写少,防止一台写多应用阻塞读请求。

10.关于map/reduce问题
mongodb 对map/reduce 的支持是单线程的,咱们不建议在前台使用该功能, group by
是经过map/reduce 实现的,开发过程当中,要慎用。

11.安全问题
1】Mongodb 运行在mongodb 用户之上,并禁止mongodb 用户登陆
2】使用Mongodb 自带的认证方法(adduser、auth)限制用户访问行为
3】将Mongodb 置于内网环境中
4】Mongodb 必须暴露在外网环境中的时候,使用IPTABLES 等网络层技术进行防御
5】网络层面内容为明文传输,能够考虑存储加密文档,应用端,加解密。

12.性能监控
Mongodb 自带有性能数据收集系统
Mongostat 实时采集数据库的多项指标,提供http console 端口号为应用端口号+1000。
关注的主要性能指标:
1】Faults:显示Mongodb 每秒页面故障的数量,这个是mongoDB 映射到虚拟地址空间,
而不是物理内存,这个值若是飙高的话,可能意味着机器没有足够的内存来
存储数据和索引。
2】Flushes:每秒作了多少次fsync,显示多少次数据被刷新进了磁盘
3】locked:写锁
4】idx miss:索引未命中比例
5】qr | qw:读写锁的请求队列长度。
6】conn: 当前已经创建的链接数。
其余命令:
Db.stat()
db.serverStatuse()
Db.collection.stats()
13.碎片问题
Mongodb 数据库若是数据修改很频繁,会出现比较严重的空间碎片问题,表如今磁盘
文件扩张与实际数据量不相符,内存不够用,索引命中率低,查询效率下降。
碎片整理,目前咱们采用的版本没有太有效的方法。
能够用db.repaireDatabase() 来整理数据库,这个过程很是的慢
若是是Master-slave 模式则至关于执行一次主从切换,而后重新创建从库。
若是是replSet 架构能够停掉数据库,而后删除数据目录,重新从复制复制组中全同步数据,
这个时候要考虑oplog 的尺寸。
一个大致的步骤:
1.】先调用rs.freeze(1200),将每一个不想让它成为primary 的机器让它在1200 秒内没法成为
primary(这步也能够不作)
2. 】将primary stepDown,不出意外新的primary 会起来.
3. 】将原primary kill 掉.
4. 】删掉全部data 数据(调用repair 很慢,真不如干掉从新来)
5. 】再重启动原primary 的进程
6. 】以此循环完成整个复制组的所有重建。

14.系统备份:
Mongodb 目前不支持在线备份,只能离线备份。
咱们采用的架构为replSet 和Master-slave .
基于咱们目前的架构以及数据一致性要求,咱们没有安排相关的备份系统。

15.应用代码中Mongodb链接问题
在有些应用在使用Mongodb 过程当中会存在如下两个小问题:
1. 在应用启动过程当中,应用存在要求链接池中全部的链接都创建成功才让应用正
常启动,这种作法不可取,由于存在网络问题、Mongodb 拒绝链接或Mongodb 假死状况,如
果没加外部try catch 作防御,则Resin 不断重启也不能正常启动端口。
2.有些应用在使用Mongodb 中链接池配置了safe=true,w=1;这种配置意味着客户端在
插入数据或更新数据的时候,要求mongodb 必须将所更新的数据写入磁盘并返回更新成功
的信息给程序。若是碰上应用程序访问压力大,mongodb 就会反应迟钝,并会发生假死可能,
针对此状况,须要评估数据的一致性需求,作出合适调整。咱们通常建议关闭此选项。

16.补充开发方面的一些问题
1】skip+limit翻页,越日后面越慢,有资料说用数组元素的分页能够解决,目前还没
试过,比较靠谱的作法是,先找出上次的id,翻页的时候不用skip:
last_row_id = ObjectId(‘....’);
db.activity_stream->find({_id:{$lt: last_row_id },
user_id:20 } ).sort( {_id:-1} ).limit(10);


2】.只有真正须要的字段才select出来
3】.更新的某条数据的时候,先查出来再更新会减少锁的时间
4】.只有返回不多结果的查询才用索引,不然会加载太多数据,比没有用索引还慢
5】.属性比较多的时候,创建分层的关系可以提升查询效率,不然每一个记录都要过一遍
才能找到要的属性

17.关于硬件资源的选择:
虚拟机能够很好的隔离资源,并可动态的扩展。
咱们建议mongodb 的部署采用虚拟机的方式,每一个虚拟机部署一个实例,使各节点分
散在不一样的物理机上,根据应用的前期预测,平衡虚拟机的之间的i/o。
相关文章
相关标签/搜索