memcache 认知

memcached会预先分配内存,memcached分配内存方式称之为allocator,

首先,这里有3个概念:1slab  2page  3chunk

一般来说一个memcahced进程会预先将自己划分为若干个slab,每个slab下又有若干个page,每个page下又有多个chunk,slab得数量是有限得,几个,十几个,或者几十个,这个跟进程配置得内存有关。而每个slab下得page默认情况是1m,也就是说如果一个slab占用100m得内存得话,那么默认情况下这个slab所拥有得page得个数就是100,而chunk就是我们得数据存放得最终地方。

statsslabs

-----------------------------

STAT2:chunk_size104

STAT2:chunks_per_page10082

STAT2:total_pages1

STAT2:total_chunks10082

STAT2:used_chunks12

STAT2:free_chunks74

STAT2:free_chunks_end9996

STAT2:mem_requested996

STAT2:get_hits0

STAT2:cmd_set31761

STAT2:delete_hits17

STAT2:incr_hits991

STAT2:decr_hits0

STAT2:cas_hits0

STAT2:cas_badval0

STAT2:touch_hits0

STAT5:chunk_size224

STAT5:chunks_per_page4681

STAT5:total_pages1

STAT5:total_chunks4681

STAT5:used_chunks29

STAT5:free_chunks13

STAT5:free_chunks_end4639

STAT5:mem_requested6496

STAT5:get_hits2954

STAT5:cmd_set297

STAT5:delete_hits10

STAT5:incr_hits0

STAT5:decr_hits0

STAT5:cas_hits0

STAT5:cas_badval0

STAT5:touch_hits0

.....

.....

STATactive_slabs28

STATtotal_malloced63283664

-----------------------------

chunk_size表示数据存放块得大小,

chunks_per_page表示一个内存页page中拥有得chunk得数量,

total_pages表示每个slab下page得个数。

total_chunks表示这个slab下chunk得总数(=total_pages*chunks_per_page),

used_chunks表示该slab下已经使用得chunk得数量,

free_chunks表示该slab下还可以使用得chunks数量。

从上面得示例slab1一共有1m得内存空间,而且现在已经被用完了,slab2也有1m得内存空间,也被用完了,slab3得情况依然如此。而且从这3个slab中chunk得size可以看出来,第一个chunk为104b,第二个是224,基本上后一个是前一个得1.25倍,但是这个增长情况我们是可以控制得,我们可以通过在启动时得进程参数f来修改这个值,比如说f1.1表示这个增长因子为1.1,那么第一个slab中得chunk为80b得话,第二个slab中得chunk应该是80*1.1左右。

memcached中新的value过来存放的地址是该value的大小决定的,value总是会被选择存放到chunk与其最接近的一个slab中,比如上面的例子,如果我的value是80b,那么我这所有的value总是会被存放到1号slab中,而1号slab中的free_chunks已经是0了,怎么办呢,如果你在启动memcached的时候没有追加-M(禁止LRU,这种情况下内存不够时会outofmemory),那么memcached会把这个slab中最近最少被使用的chunk中的数据清掉,然后放上最新的数据。这就解释了为什么我的内存还有40%的时候LRU就执行了,因为我的其他slab中的chunk_size都远大于我的value,所以我的value根本不会放到那几个slab中,而只会放到和我的value最接近的chunk所在的slab中(而这些slab早就满了,郁闷了)。这就导致了我的数据被不停的覆盖,后者覆盖前者。

memcachedserver不能停啊,不要紧还有另外一个方法,就是memcached-tool,执行move命令,如:move31,代表把3号slab中的一个内存页移动到1号slab中,有人问了,这有什么用呢,比如说我的20号slab的利用率非常低,但是page却又很多,比如200,那么就是200m,而2好slab经常发生LRU,明显page不够,我就可以move202,把20号slab的一个内存页移动到2号slab上,这样就能更加有效的利用内存了

相关推荐