五、Memcached深入分析及内存调优

来源:互联网 发布:电脑蓝牙软件下载 编辑:程序博客网 时间:2024/06/05 18:49
【转载自】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:

[root@iZ25bep053pZ ~]# /usr/local/memcached/bin/memcached -d -u root -p 11211 -vv[root@iZ25bep053pZ ~]# slab class   1: chunk size    104 perslab 10082slab class   2: chunk size    136 perslab  7710slab class   3: chunk size    176 perslab  5957slab class   4: chunk size    224 perslab  4681slab class   5: chunk size    280 perslab  3744slab class   6: chunk size    352 perslab  2978slab class   7: chunk size    440 perslab  2383slab class   8: chunk size    552 perslab  1899slab class   9: chunk size    696 perslab  1506slab class  10: chunk size    872 perslab  1202slab class  11: chunk size   1096 perslab   956slab class  12: chunk size   1376 perslab   762slab class  13: chunk size   1720 perslab   609slab class  14: chunk size   2152 perslab   487slab class  15: chunk size   2696 perslab   388slab class  16: chunk size   3376 perslab   310slab class  17: chunk size   4224 perslab   248slab class  18: chunk size   5280 perslab   198slab class  19: chunk size   6600 perslab   158slab class  20: chunk size   8256 perslab   127slab class  21: chunk size  10320 perslab   101slab class  22: chunk size  12904 perslab    81slab class  23: chunk size  16136 perslab    64slab class  24: chunk size  20176 perslab    51slab class  25: chunk size  25224 perslab    41slab class  26: chunk size  31536 perslab    33slab class  27: chunk size  39424 perslab    26slab class  28: chunk size  49280 perslab    21slab class  29: chunk size  61600 perslab    17slab class  30: chunk size  77000 perslab    13slab class  31: chunk size  96256 perslab    10slab class  32: chunk size 120320 perslab     8slab class  33: chunk size 150400 perslab     6slab class  34: chunk size 188000 perslab     5slab class  35: chunk size 235000 perslab     4slab class  36: chunk size 293752 perslab     3slab class  37: chunk size 367192 perslab     2slab 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大小,bytechunks_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                    使用过期对象空间存储对象次数
0 0
原创粉丝点击