记一次MongoDB性能问题,附原理解析
下面文章转载自火丁笔记,原作者描述了一次
同时运行mongostat显示很高的locked值。
…
重复做了很多工作,但始终无法找到问题的症结在哪里,只好求助官方论坛,那里的技术支持都很热心,在我描述了问题后,没过多久就有了回复,建议我检查一下是不是索引不佳所致,为了验证这种可能,我激活了Profiler记录慢操作:
mongo> use <DB>mongo> db.setProfilingLevel(1);
不过结果显示基本都是insert操作(因为我是导入数据为主),本身就不需要索引:
mongo> use <DB>mongo> db.system.profile.find().sort({$natural:-1})…
问题到了这里,似乎已经走投无路了,为了死马当活马医,我又重复了几次迁移旧数据的过程,结果自然是次次都出问题,但幸运的是我发现每当出问题的时候,在top命令的结果中,总有一个名叫irqbalance的进程居高不下,搜索了一下,结果很多介绍
每个核访问分配给自己的内存会比访问分配给其它核的内存要快,有下面几种访问控制策略:
1.缺省(default):总是在本地节点分配(分配在当前进程运行的节点上);2.绑定(bind):强制分配到指定节点上;3.交叉(interleave):在所有节点或者指定的节点上交织分配;4.优先(preferred):在指定节点上分配,失败则在其他节点上分配。上面文章中最后使用numactl –interleave命令就是指定其为交叉共享模式。
irqbalance:这是作者在上面提到的一个占用CPU的进程,这个进程的作用是在多核心CPU的操作系统中,分配系统中断信号的。参见:irqbalance.org
概念说完了,下面是上面问题的简单描述:
我们知道虚拟内存机制是通过一个中断信号来通知虚拟内存系统进行内存swap的,所以这个irqbalance进程忙,是一个危险信号,在这里是由于在进行频繁的内存交换。这种频繁交换现象称为swap insanity,在MySQL中经常提到,也就是在NUMA框架中,采用不合适的策略,导致核心只能从指定内存块节点上分配内存,即使总内存还有富余,也会由于当前节点内存不足时产生大量的swap操作。
对于NUMA,进一步了解可以参考:NUMA与英特尔下一代Xeon处理器 和?MySQL单机多实例方案 两篇文章