mongodb 总结
本文内容纲要:
生产环境最佳实践
1.linux系统:
1】关闭文件系统/分区的atime选项
Vi/etc/fstab
在对应的分区项后面添加noatime,nodiratime
LABEL=/1/ext3defaults11
LABEL=/data1/dataext4defaults,noatime,nodiratime12
2】设置文件句柄4k+,目前该配置已经集成到启动脚本中。
Vi/etc/security/limit.conf
*softnproc65536
*hardnproc65536
*softnofile65536
*hardnofile65536
3】不要使用largevmpage(不要使用大内存页选项)
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.ext4文件系统数据损失bug就影响着多个稳定版内核。ext4用户应避免使用Linux
3.4.14、3.4.15、3.5.7、3.6.2和3.6.3。
4.线程堆栈的尺寸
默认的线程堆栈尺寸为10m,调整为1m,已经集成在启动脚本中。
项目过程中的总结与建议
1.大小写问题
mongodb是默认区分大小写的,但是这会不会衍生出跟mysql一样的问题?(mysql区
分大小写,导致windows与linux下的表名,字段名不一致)。
如果无特别用途,建议表名,字段名全部用小写字母。
2.尽可能的缩短字段名的长度
mongodb的schemafree导致了每笔数据都要存储他的key以及属性,这导致了这些数
据的大量冗余。开发同事也许考虑到,从易读性出发设计的key基本比较长,基本都是按
照起字面意思去设计的。这导致key很长。对应的数据存储占用了很大的空间。
必要的时候,可以考虑建立一个key与实际意义的map表,尽量降低key的长度。
示例定义:
//基本信息
staticstring_ID="_id";
staticstringSTATUS_CODE="sc";
//缓冲
staticstringDATE="date";
staticstringMAX_AGE="age";
//内容
staticstringCONTENT="content";
staticstringCONTENT_TYPE="ctype";
staticstringCONTENT_LENGTH="clen";
staticstringZIP="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的支持是单线程的,我们不建议在前台使用该功能,groupby
是通过map/reduce实现的,开发过程中,要慎用。
11.安全问题
1】Mongodb运行在mongodb用户之上,并禁止mongodb用户登录
2】使用Mongodb自带的认证方法(adduser、auth)限制用户访问行为
3】将Mongodb置于内网环境中
4】Mongodb必须暴露在外网环境中的时候,使用IPTABLES等网络层技术进行防护
5】网络层面内容为明文传输,可以考虑存储加密文档,应用端,加解密。
12.性能监控
Mongodb自带有性能数据收集系统
Mongostat实时采集数据库的多项指标,提供httpconsole端口号为应用端口号+1000。
关注的主要性能指标:
1】Faults:显示Mongodb每秒页面故障的数量,这个是mongoDB映射到虚拟地址空间,
而不是物理内存,这个值如果飙高的话,可能意味着机器没有足够的内存来
存储数据和索引。
2】Flushes:每秒做了多少次fsync,显示多少次数据被刷新进了磁盘
3】locked:写锁
4】idxmiss:索引未命中比例
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.】将primarystepDown,不出意外新的primary会起来.
3.】将原primarykill掉.
4.】删掉所有data数据(调用repair很慢,真不如干掉重新来)
5.】再重启动原primary的进程
6.】以此循环完成整个复制组的全部重建。
14.系统备份:
Mongodb目前不支持在线备份,只能离线备份。
我们采用的架构为replSet和Master-slave.
基于我们目前的架构以及数据一致性要求,我们没有安排相关的备份系统。
15.应用代码中Mongodb连接问题
在有些应用在使用Mongodb过程中会存在以下两个小问题:
- 在应用启动过程中,应用存在要求连接池中所有的连接都建立成功才让应用正
常启动,这种做法不可取,因为存在网络问题、Mongodb拒绝连接或Mongodb假死情况,如
果没加外部trycatch做防护,则不断重启也不能正常启动端口。
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】.属性比较多的时候,建立分层的关系能够提高查询效率,否则每个记录都要过一遍
才能找到要的属性
MongoDB结构划分
MongoDB的C#驱动程序教程(译)
http://www.lanceyan.com/category/tech/mongodb
本文内容总结:
原文链接:https://www.cnblogs.com/shanyou/archive/2012/08/22/2650145.html