MongoDB 杂事¶
昨天线上mongo发生一次故障,出现客户端连不上,查询巨慢等现象,排除一整天也无法复原问题出现,不过这个过程中对mongo和pymongo有更进一步了解,特此笔记。
819连接数
查看日志看到大量如下日志:
使用db.serverStatus().connections查看连接数:
这个错误产生的原因主要是因为linux每个进程1024个文件句柄限制导致的。使用ulimit -n 或 ulimit -a 查看当前系统限制。
使用ulmit -n 65535 只会更改当前session的文件句柄限制,要更改系统的限制需vim /etc/security/limits.conf 添加如下行:
mongo的配置文件也需要修改 vim /etc/mongodb.conf
ps. linux系统做服务器一般都需要做些优化,这里给出一些常用优化项,vim /etc/sysctl.conf:
pymongo连接参数
为了解决连接数过大的问题也算是翻遍了pymongo代码,发现两个选项,能起点作用
auto_start_request: 设为True时,MongoClient为每个线程分配一个socket, 这样比较安全,它能保证你在一个unacknowledged 写之后的读也是对的。而设为False时,多个线程共用socket, 不过如果你还想在单个socket上做序列操作以保证read-your-own-writes consistency, 可以使用 start_request/end_request. 更多详情请看:http://emptysqua.re/blog/requests-in-python-and-mongodb/
use_greenlets: 为True时,使用gevent时,该参数设为True, start_request会保证当前greenlet会使用同一个socket
mongostat
mongostat是个非常好用的监控工具
$mongostat
insert/query/update/delete: 每秒 插入/查询/更新/删除数
getmore: 查询时游标的getmore操作数
command: 每秒执行命令数
flush: 一秒内flush的次数,flush开销很大,如果频繁flush, 可能需要查查原因了
mapped: 所有被mmap的数据量,单位是MB
vsize: 虚拟内存使用量
res: 物理内存使用量
faults: 每秒访问失败数(只有Linux有),数据被交换出物理内存,放到swap。不要超过100,否则就是机器内存太小,造成频繁swap写入。此时要升级内存或者扩展
locked: 写锁所占时间比,该数值过大(>10%)就需要注意了
idx miss: 索引不命中百分比,正常情况下,所有查询都应该通过索引
qr|qw ar|aw: mongo负载高时,命令来不及处理,mongo将命令放入队列。 qr|qw 等待读/写的队列长度 ar|aw 执行读/写操作客户端数量
netIn/netOut: 出入网络带宽
conn: 当前连接数
mongo command
查看/创建/删除 索引
在后台创建索引(线上数据库加索引为了不影响正常应用)
重建索引(collection大小变动巨大或索引占用过多空间时执行)
查看数据库信息
服务器状态
mongodb 当前正在执行的操作
如果你发现一个操作太长,把数据库卡死的话,可以用这个命令杀死他
mongon内存
mongo是出了名的吃内存,空间碎片问题严重,目前也没有什么好办法。
可以用db.repaireDatabase() 整理数据库,非常慢,线上系统就不要用了。
查看系统内存
linux可用内存计算方法是free + buffers + cached, 实际使用内存是 used - buffers - cached
MongoDB使用的是内存映射存储引擎,它会把数据文件映射到内存中,如果是读操作,内存中的数据起到缓存的作用,如果是写操作,内存还可以把随机的写操作转换成顺序的写操作,总之可以大幅度提升性能。MongoDB并不干涉内存管理工作,而是把这些工作留给操作系统的虚拟内存管理器去处理,这样做的好处是简化了MongoDB的工作,但坏处是你没有方法很方便的控制MongoDB占多大内存,幸运的是虚拟内存管理器的存在让我们多数时候并不需要关心这个问题。
更多内存相关可看: http://huoding.com/2011/08/19/107