最近发生了一些事情,由于之前开发和运维对于MONGODB的了解停留在用而已,已经某些外部原因,导致MONGODB 在某些不可抗力的情况下,出现了问题,导致了我不能说的经济损失。
随后公司的非IT 的领导,给出了一句话,没有想到MONGODB 变得如此重要。
呵呵,当然MONGODB当然会越来越重要,这不是偶然,这是必然,读写的速度,JSON的天然混成,以及各种加速查询的方式,事务,天然的读写分离,不重要那才是你的遗憾。
所以这又是一个新的系列,关于MONGODB的优化和调优,下方是一个MONGODB的 内存与磁盘的一个大概的架构。
与传统的数据库一样,你也可以理解为他分为共享的内存,和每个SESSION 自有的内存。MONGODB 本身也有自己的事务多版本控制,这些都是需要耗费内存。
MONGODB的性能与内存的关系可以用三条线来描述
1 FREE MEMORY
2 Response time
3 swap
用语言来描述,如果你的MONGODB所在的服务器上开始使用了SWAP,那将是一个灾难的开始,你的查询时间会以成百倍的程度增加,也就是响应时间,同时此时你的FREE MEMORY 估计也已经捉襟见肘。
图画的比较烂,凑活看哈,所以在FREE MEMORY 到达底线的时候,你的response time 就是要高歌一曲的时候,同时配合着你的 SWAP 缓慢崛起,好一副 性能问题的三重奏。
所以当你看到你的MONGODB 的服务器的 USED SWAP 开始逐步上升,并且你的MONGODB 的相应时间在逐渐的变慢,那么性能问题就已经爆发了。
在使用MONGODB时关于wiredtiger 的cachesize 的设置是一个有意思的是事情,一些人总想找到一个逻辑来控制到底我应该怎么设置 cachesize ,官方提出50% ,当然大多时候这样设置是没有问题的,但也仅仅是没有问题而已,如果你说他是一个非常好的设置的值,我只能呵呵。
cachesize的设置与你本身的物理内存大小有很大的关系,如果你的内存连8G都不到,那么此时你设置 4G 作为CS 其实也是过大的,可能2G 更合适你。
而当你的内存已经都在512G的时候,此时你还咬文嚼字的去说,50%,也未免太保守了。因为原理,MONGODB 的数据库的原理,希望MONGODB 能获得更大的内存,MONGODB的 写 读 SNAPSHOT 等等都离不开内存,所以如果你有 512G 的时候,不妨可以大胆的将60% - 70%的内存都给到 CS。
实际上针对CS 的配置有另外一个想法就是 CHR, cache hit ratio , 其实大多数的数据库也都有这样的一个指标,这个指标实际上可以用一个公式来代表。
在内存中可以找到的数据 /你发起的读取数据的需求 * 100 = cache hit ratio
但是,但是,但是,重要的事情说三遍,即使你有一个好看的 cache hit ratio, 假设他一直在 95% , 这只能证明你的内存够大,读取的数据可能够单一,除此以外什么都证明不了,此时你的MONGODB 运行的没有遇到大的麻烦。
> var cache = db.serverStatus().wiredTiger.cache;
> var missc = cache['pages read into cache']* 100/cache['pages requested from the cache'];
> var hitr = 100 - missc;
> print(hitr)
99.80766247867226
通过这样的方式可以获得你当时的cache hit ratio , 除了这个指标以外,MONGODB 还有一个知名的指标 dirty flush below 5% ,也就是脏页在MONGODB 中的留存不要超过 5% , 根据LRU的原则,MONGODB ,通过4个线程来去逐出这些内存与数据页面不同的数据,超过5% 说明你的服务器的压力过大,脏页的驻留时间过长,所以你就需要注意你的系统压力的情况了。也即使我们俗称的性能问题。
db.serverStatus().wiredTiger["thread-yield"]["page acquire eviction blocked"]
如何获得系统曾经发生过强行的驱逐内存数据到数据磁盘的问题,通过上面的查询就可以获得驱逐次数的情况,这说明系统发生过强行内存刷入到磁盘的情况。