五、Memcached深入分析及内存调优
2017-03-03 12:01
204 查看
【转载自】http://hi.baidu.com/mouhainy/blog/item/a3b2bf3377fa02fd1b4cfffc.html
到这里memcached的初步使用我们已经没问题了,但是了解一些它内部的机制还是十分必要的,这直接涉及到你能否把memcached给真正“用好”。
Memcached的守护进程机制使用的是Unix下的daemon,Socket则使用了非阻塞(non-blocked)高性能的NIO,事件处理上大家都已经知道了,是基于libevent,支持异步的事件处理。
最主要的是要知道它的内存管理机制,使用如下命令启动memcached:
# /usr/local/memcached/bin/memcached -d -u root -p 11211 -vv
这里我们分配了默认的内存64M的内存给memcached,那么memcached又是怎么样来分配内存的呢?先看下图:
Memcached在分配内存时是以Page为单位的,默认情况下一个Page是1M,内部是一个个chunk,当chunk的大小等于Page大小时也就是Memcached所能存储的最大数据大小了,可以在启动时通过-l来指定它。
Memcached并不是将所有大小的数据都存放在一起的,而是将内存空间划分为一个个的slab,每个slab只负责一定范围内的数据。上图中,slab1只负责96bytes的数据,slab2负责120bytes的数据。
在存储数据时,如果这个item对应的slab还没有创建则申请一个page的内存,将这个page按照所在slab中chunk的大小进行分割,然后将item存入。
如果已经创建存在了,判断对应的slab是否用完,没用完直接存储。
如果对应的slab已经用完了,看内存是否用完,没用完会申请一个新的page进行分割存储,用完了则直接进行LRU。
那么我们怎么样来查看各个slab的状况及里面的chunk大小呢?
在前面的启动参数中我们发现有-v –vv -vvv三个选项,一般我们用的最多的是-vv:
我们看到,一共有38个slab,第一个slab中chunk大小为104bytes,第二个为136bytes,第三个为176bytes,每个slab中chunk的大小都不一样,这个chunk就是memcached具体存储数据的地方。
Memcached通过指定的成长因子(-f指定,默认1.25倍)来决定每个slab中chunk增长的范围,第一个slab的大小可以通过-n来设定。
当数据进来时Memcached会选择一个大于等于最接近的slab来进行存储。例如当item大小为100时将存储到chunk为104bytes的slab1,item大小为110时则会存储到chunk大小为136的slab2.
这样分配的好处是速度快,避免大量重复的初始化和清理操作,有效的避免了内存碎片的问题,但内存利用率上会有所浪费。典型的拿空间换效率,如图所示:
另外Memcached是懒检测机制,当存储在内存中的对象过期甚至是flush_all时,它并不会做检查或删除操作,只有在get时才检查数据对象是否应该删除。
删除数据时,Memcached同样是懒删除机制,只在对应的数据对象上做删除标识并不回收内存,在下次分配时直接覆盖使用。
了解了Memcached的内存分配机制,如何进行调优是不是自然而然的就明白了?
应该尽量的根据实际情况来设定slab的chunk的初始大小和增长因子,尽量减少内存的浪费。在某些情况下数据的长度都会集中在一个区域,如session。甚至会有定长的情况,如数据统计等。
还有一个重要调优的地方就是提高缓存命中率了,这个没有固定的方法,还得具体场景做具体业务分析,需要注意的就是,Memcached中LRU的操作是基于slab而非全局,分析时最好考虑这一点,这也就是有时候内存还没用完但数据却被回收了的原因。
现在我们再回过头去看Memcached的stats命令,是不是就很有用了?这里贴上常用的一些参数说明。
stats统计项:
stats slabs区块统计:
被浪费内存数=(total_chunks * chunk_size) - mem_requested,如果太大,则需要调整factor
stats items数据项统计:
到这里memcached的初步使用我们已经没问题了,但是了解一些它内部的机制还是十分必要的,这直接涉及到你能否把memcached给真正“用好”。
Memcached的守护进程机制使用的是Unix下的daemon,Socket则使用了非阻塞(non-blocked)高性能的NIO,事件处理上大家都已经知道了,是基于libevent,支持异步的事件处理。
最主要的是要知道它的内存管理机制,使用如下命令启动memcached:
# /usr/local/memcached/bin/memcached -d -u root -p 11211 -vv
这里我们分配了默认的内存64M的内存给memcached,那么memcached又是怎么样来分配内存的呢?先看下图:
Memcached在分配内存时是以Page为单位的,默认情况下一个Page是1M,内部是一个个chunk,当chunk的大小等于Page大小时也就是Memcached所能存储的最大数据大小了,可以在启动时通过-l来指定它。
Memcached并不是将所有大小的数据都存放在一起的,而是将内存空间划分为一个个的slab,每个slab只负责一定范围内的数据。上图中,slab1只负责96bytes的数据,slab2负责120bytes的数据。
在存储数据时,如果这个item对应的slab还没有创建则申请一个page的内存,将这个page按照所在slab中chunk的大小进行分割,然后将item存入。
如果已经创建存在了,判断对应的slab是否用完,没用完直接存储。
如果对应的slab已经用完了,看内存是否用完,没用完会申请一个新的page进行分割存储,用完了则直接进行LRU。
那么我们怎么样来查看各个slab的状况及里面的chunk大小呢?
在前面的启动参数中我们发现有-v –vv -vvv三个选项,一般我们用的最多的是-vv:
[root@iZ25bep053pZ ~]# /usr/local/memcached/bin/memcached -d -u root -p 11211 -vv [root@iZ25bep053pZ ~]# slab class 1: chunk size 104 perslab 10082 slab class 2: chunk size 136 perslab 7710 slab class 3: chunk size 176 perslab 5957 slab class 4: chunk size 224 perslab 4681 slab class 5: chunk size 280 perslab 3744 slab class 6: chunk size 352 perslab 2978 slab class 7: chunk size 440 perslab 2383 slab class 8: chunk size 552 perslab 1899 slab class 9: chunk size 696 perslab 1506 slab class 10: chunk size 872 perslab 1202 slab class 11: chunk size 1096 perslab 956 slab class 12: chunk size 1376 perslab 762 slab class 13: chunk size 1720 perslab 609 slab class 14: chunk size 2152 perslab 487 slab class 15: chunk size 2696 perslab 388 slab class 16: chunk size 3376 perslab 310 slab class 17: chunk size 4224 perslab 248 slab class 18: chunk size 5280 perslab 198 slab class 19: chunk size 6600 perslab 158 slab class 20: chunk size 8256 perslab 127 slab class 21: chunk size 10320 perslab 101 slab class 22: chunk size 12904 perslab 81 slab class 23: chunk size 16136 perslab 64 slab class 24: chunk size 20176 perslab 51 slab class 25: chunk size 25224 perslab 41 slab class 26: chunk size 31536 perslab 33 slab class 27: chunk size 39424 perslab 26 slab class 28: chunk size 49280 perslab 21 slab class 29: chunk size 61600 perslab 17 slab class 30: chunk size 77000 perslab 13 slab class 31: chunk size 96256 perslab 10 slab class 32: chunk size 120320 perslab 8 slab class 33: chunk size 150400 perslab 6 slab class 34: chunk size 188000 perslab 5 slab class 35: chunk size 235000 perslab 4 slab class 36: chunk size 293752 perslab 3 slab class 37: chunk size 367192 perslab 2 slab class 38: chunk size 458992 perslab 2 <6 server listening (replication) replication: listen <7 server listening <8 server listening <9 send buffer was 212992, now 268435456 <9 server listening (udp) <10 send buffer was 212992, now 268435456 <10 server listening (udp)
我们看到,一共有38个slab,第一个slab中chunk大小为104bytes,第二个为136bytes,第三个为176bytes,每个slab中chunk的大小都不一样,这个chunk就是memcached具体存储数据的地方。
Memcached通过指定的成长因子(-f指定,默认1.25倍)来决定每个slab中chunk增长的范围,第一个slab的大小可以通过-n来设定。
当数据进来时Memcached会选择一个大于等于最接近的slab来进行存储。例如当item大小为100时将存储到chunk为104bytes的slab1,item大小为110时则会存储到chunk大小为136的slab2.
这样分配的好处是速度快,避免大量重复的初始化和清理操作,有效的避免了内存碎片的问题,但内存利用率上会有所浪费。典型的拿空间换效率,如图所示:
另外Memcached是懒检测机制,当存储在内存中的对象过期甚至是flush_all时,它并不会做检查或删除操作,只有在get时才检查数据对象是否应该删除。
删除数据时,Memcached同样是懒删除机制,只在对应的数据对象上做删除标识并不回收内存,在下次分配时直接覆盖使用。
了解了Memcached的内存分配机制,如何进行调优是不是自然而然的就明白了?
应该尽量的根据实际情况来设定slab的chunk的初始大小和增长因子,尽量减少内存的浪费。在某些情况下数据的长度都会集中在一个区域,如session。甚至会有定长的情况,如数据统计等。
还有一个重要调优的地方就是提高缓存命中率了,这个没有固定的方法,还得具体场景做具体业务分析,需要注意的就是,Memcached中LRU的操作是基于slab而非全局,分析时最好考虑这一点,这也就是有时候内存还没用完但数据却被回收了的原因。
现在我们再回过头去看Memcached的stats命令,是不是就很有用了?这里贴上常用的一些参数说明。
stats统计项:
STAT pid 22438 memcache服务器的进程ID STAT uptime 2642 服务器已经运行的秒数 STAT time 1488435021 服务器当前的unix时间戳 STAT version 1.2.8 memcache版本 STAT pointer_size 64 当前操作系统的指针大小(32位系统一般是32bit,64就是64位操作系统) STAT rusage_user 0.033049 进程的累计用户时间 STAT rusage_system 0.066099 进程的累计系统时间 STAT curr_items 0 当前存储的数据总数 STAT total_items 0 启动以来存储的数据总数 STAT bytes 0 当前存储占用的字节数 STAT curr_connections 5 当前打开着的连接数 STAT total_connections 8 从服务器启动以后曾经打开过的连接数 STAT connection_structures 6 服务器分配的连接构造数 STAT cmd_flush 0 flush命令请求次数 STAT cmd_get 0 get命令(获取)总请求次数 STAT cmd_set 0 set命令(保存)总请求次数 STAT get_hits 0 总命中次数 STAT get_misses 0 总未命中次数 STAT evictions 0 为获取空闲内存而删除的items数(分配给memcache的空间用满后需要删除旧的items来得到空间分配给新的items) STAT bytes_read 30 总读取字节数(请求字节数) STAT bytes_written 1240 总发送字节数(结果字节数) STAT limit_maxbytes 67108864 分配给memcache的内存大小(字节) STAT threads 2 当前线程数 STAT accepting_conns 1 服务器是否达到过最大连接 STAT listen_disabled_num 0 失效的监听数 STAT replication MASTER STAT repcached_version 2.2 STAT repcached_qi_free 8192 END
stats slabs区块统计:
chunk_size chunk大小,byte chunks_per_page 每个page的chunk数量 total_pages page数量 total_chunks chunk数量*page数量 get_hits get命中数 cmd_set set数 delete_hits delete命中数 incr_hits incr命中数 decr_hits decr命中数 cas_hits cas命中数 cas_badval cas数据类型错误数 used_chunks 已被分配的chunk数 free_chunks 剩余chunk数 free_chunks_end 分完page浪费chunk数 mem_requested 请求存储的字节数 active_slabs slab数量 total_malloced 总内存数量
被浪费内存数=(total_chunks * chunk_size) - mem_requested,如果太大,则需要调整factor
stats items数据项统计:
number 该slab中对象数,不包含过期对象 age LRU队列中最老对象的过期时间 evicted LRU释放对象数 evicted_nonzero 设置了非0时间的LRU释放对象数 evicted_time 最后一次LRU秒数,监控频率 outofmemory 不能存储对象次数,使用-M会报错 tailrepairs 修复slabs次数 reclaimed 使用过期对象空间存储对象次数
相关文章推荐
- Memcached深入分析及内存调优
- Memcached 深入分析及内存调优
- .NET Framework 自动内存管理机制深入剖析 (C#分析篇)
- .NET Framework 自动内存管理机制深入剖析 (C#分析篇)
- (转)UCGUI的动态内存分配的原理深入分析
- memcached server LRU 深入分析[转载]
- UCGUI的动态内存分配的原理深入分析
- .NET Framework 自动内存管理机制深入剖析 (C#分析篇)[转]
- memcached server LRU 深入分析
- 深入分析Memcached的线程接入模型---中
- 深入分析Memcached的线程接入模型---上
- linuxr下sar调优工具的深入分析
- .NET Framework 自动内存管理机制深入剖析 (C#分析篇)
- JavaME 程序性能调优内存分析工具 Memory Monitor 的使用
- Memcached 1.2 内存模型分析(zz)
- 深入分析Memcached的线程接入模型---下
- .NET Framework 自动内存管理机制深入剖析 (C#分析篇) 读了三遍回味无穷
- 自动内存管理机制深入剖析-C#分析篇
- 深入分析Memcached的线程接入模型---中
- memcached server LRU 深入分析