memcache内存使用原理及监控分析 --重在监控分析

  原创:https://i-blog.csdnimg.cn/blog_migrate/5e9565fbdaef924e44b3ad2581106cd5.png

memcache的内存分配默认是采用Slab Allocator的机制分配、管理内存。在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的。 但是,这种方式会导致内存碎片,加重操作系统内存管理器的负担,最坏的情况下, 会导致操作系统比memcached进程本身还慢。Slab Allocator就是为解决该问题而诞生的。

      Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块, 以完全解决内存碎片问题。

    Slab Allocation的原理相当简单。 将分配的内存分割成各种尺寸的块(chunk), 并把尺寸相同的块分成组(chunk的集合)(图1

      memcached-0002-01.png

      

图1 Slab Allocation的构造图而且,slab allocator还有重复使用已分配的内存的目的。 也就是说,分配到的内存不会释放,而是重复利用

   对于slab有几个术语:

  page:分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk.

 chunk:用于记录缓存的内存空间

Slab class:由特定大小的chunk块组成

slab 中的缓存记录原理:

 memcached根据收到的数据的大小,选择最适合数据大小的slab(图2)。 memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk, 然后将数据缓存于其中。

    memcached-0002-02.png

  实际上,Slab Allocator也是有利也有弊。下面介绍一下它的缺点。

  

Slab Allocator解决了当初的内存碎片问题,但新的机制也给memcached带来了新的问题。

这个问题就是,由于分配的是特定长度的内存,因此无法有效利用分配的内存。 例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了(图3)。

 memcached-0002-03.png


对于该问题目前还没有完美的解决方案,但在文档中记载了比较有效的解决方案。就是说,如果预先知道客户端发送的数据的公用大小,或者仅缓存大小相同的数据的情况下, 只要使用适合数据大小的组的列表,就可以减少浪费。

但是很遗憾,现在还不能进行任何调优,只能期待以后的版本了。 但是,我们可以调节slab class的大小的差别。 接下来说明growth factor选项。

memcached在启动时指定 Growth Factor因子(通过-f选项), 就可以在某种程度上控制slab之间的差异。默认值为1.25。 但是,在该选项出现之前,这个因子曾经固定为2,称为“powers of 2”策略。

 $memcached -f 1.25  (-f选项可以用来调整slab增长的因子)

查看slab的使用状态,需要下载memcached-tool脚本:

 perl memcached-tool ip:port

  #  Item_Size   Max_age  1MB_pages Count   Full?
  1      96 B   205654 s       1      44      no
  2     120 B  1337261 s      12     163     yes
  3     152 B   302966 s       3    5474     yes
  4     192 B  1328685 s       5      62     yes
  5     240 B   977587 s       3     158      no
  6     304 B  1304414 s       8    1667     yes
  7     384 B  1337261 s       5      17      no
  8     480 B  1337262 s       2      16      no
  9     600 B  1337261 s       3      19      no
 10     752 B  1337263 s       5       9      no
 11     944 B  1328488 s       4      10      no
 12     1.2 kB 1328486 s       4      16      no
 13     1.4 kB 1326990 s       3       8     yes
 14     1.8 kB 1327343 s       4       5      no
 15     2.3 kB 1326990 s       5       6      no
 16     2.8 kB  364375 s       8     672      no
 17     3.5 kB 1326990 s       4       6      no
 18     4.4 kB 1327343 s       3       2      no
 19     5.5 kB 1327310 s      11       2      no
 20     6.9 kB 1327343 s      10       1     yes
 21     8.7 kB  364430 s       7     413      no
 22    10.8 kB 1320170 s       1       3      no
 23    13.6 kB 1324719 s       2       3      no
 24    16.9 kB 1327341 s       1       1      no
 25    21.2 kB  891471 s       1       1      no
 26    26.5 kB 1312631 s       1       7      no
 27    33.1 kB  286817 s       1       1      no
 28    41.4 kB  954206 s       1       1      no
 29    51.7 kB  959350 s       1       1      no
 30    64.7 kB 1328487 s       1       1      no
 31    80.9 kB 1318688 s       1       2      no
 32   101.1 kB       0 s       1       0      no
 33   126.3 kB  644800 s       1       1      no
 34   157.9 kB  957763 s       1       2      no
 35   197.4 kB 1318686 s       1       1      no
 36   246.8 kB 1312627 s       1       2      no
 37   308.5 kB 1326996 s       1       2     yes
 38   385.6 kB  314722 s       1       1      no



参数说明:

# slab class编号
Item_Size Chunk大小
Max_age LRU内最旧的记录的生存时间
1MB_pages 分配给Slab的页数
Count Slab内的记录数
Full? Slab内是否含有空闲chunk
从这个脚本获得的信息对于调优非常方便,强烈推荐使用。

 有关slab的详细的信息统计可以查看stats slabs命令(先要执行telnet ip port),下面给出slabs的信息:

  Escape character is '^]'.
stats slabs
STAT 1:chunk_size 96
STAT 1:chunks_per_page 10922
STAT 1:total_pages 1
STAT 1:total_chunks 10922
STAT 1:used_chunks 73
STAT 1:free_chunks 3884
STAT 1:free_chunks_end 6965
STAT 1:mem_requested 26863
STAT 1:get_hits 4695884
STAT 1:cmd_set 42248
STAT 1:delete_hits 0
STAT 1:incr_hits 0
STAT 1:decr_hits 0
STAT 1:cas_hits 0
STAT 1:cas_badval 0

给出参数说明:

chunk_size:chunk的大小;

chunks_per_page:1M/chunk_size

total_pages:分配的页数

total chunks:总共的chunk数量

used_chunks:当前正在用的chunk数量

free_chunks:可以用的chunk数量

free_chunks_end :已经分配但是没有使用的chunk数量

mem_requested :实际占用的内存大小

get_hits :命中的次数

从这个slab的块可以看出每个chunk大小是96b,在其高峰时存储了10922个,接近于1m,但目前实际占用内存是26863b=0.02m,而实际分配的内存是1m,其中有6965*96/1024*1024=0.63m是无法使用的。前面说过memcache分配内存后是无法回收的,对于这0.63m已经分配但无法使用的情况是很浪费的(其他节点可能需要的chunk不是96b的,因此是不会分配到96b的slab中的),此时就造成了内存的浪费。对于上面的slab浪费还算是小的,试想如果我们线上的某一个slab分配了1g,但随着热点转移,都存储到其他节点,而原节点失效且也没有其他适合的数据块进行利用的话,那么就会出现1g的内存已经分配,但是无法使用,我们线上就出现过此种情况。

上面是进行查看slab的情况,下面的命令可以进行查看slab里面的item的情况

stats items

STAT items:1:number 41
STAT items:1:age 205654
STAT items:1:evicted 0
STAT items:1:evicted_nonzero 0
STAT items:1:evicted_time 0
STAT items:1:outofmemory 0
STAT items:1:tailrepairs 0
STAT items:1:reclaimed 25646
STAT items:2:number 262
STAT items:2:age 1486437
STAT items:2:evicted 690

前面的编号是代表这对应slab的编号,number代表这当前slab存储的chunk个数(1号slab对应的chunk是96b)

   age:代表在对应的slab中缓存的最长时间,evicted 被去除的个数,evicted_time最后被剔除的缓存对象时间

  reclaimed因为超时而被回收的次数。如果evicted的个数很大,说明需要经常剔除,那么就是节点分配的内存不够,若reclaimed的个数很大,则说明经常会有超时现象,那么缓存的时间应该设置长些。

 我们可以通过图形来进行监控memcache的使用状况,可以在网上下载php编写memcache图形监控工具,然后修改memcache.php的ip和端口配置,放到php服务器上进行运行,即可看到memcached的图形监控。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值