memcached的内存管理机制

来源:互联网 发布:ant java arg 编辑:程序博客网 时间:2024/06/05 05:58

memcached是一个高效的分布式内存cache,默认使用SlabAllocation机制管理内存,其主要思想是按照预先规定的大小,将分配的内存分割成特定长度的块以存储相应长度的key-value数据记录,以完全解决内存碎片问题。
SlabAllocation机制只为存储外部数据而设计,也就是说所有的key-value数据都存储在SlabAllocation系统里,而memcached的其它内存请求则通过普通的malloc/free来申请,因为这些请求的数量和频率决定了它们不会对整个系统的性能造成影响。

Slab和Chunk

这里写图片描述

slab是memcached一次申请内存的最小单位。memcached启动时使用参数-m指定其可用内存,但并不是启动时所有的内存就全部分配出去了,只有在需要时才会去申请,而且每次申请一定是一个slab。Slab的大小固定为1M(1048576 Byte)。

一个slab由若干个大小相等的chunk组成。每个chunk中都保存了一个item结构体、一对key和value。

虽然在同一个slab中chunk的大小相等的,但是在不同的slab中chunk的大小并不一定相等,在memcached中按照chunk的大小不同,可以把slab分为很多种类(class)。

在启动memcached的时候可以通过-vv来查看slab的种类:

$ memcached -vvslab class 1: chunk size 80 perslab 13107slab class 2: chunk size 104 perslab 10082slab class 3: chunk size 136 perslab 7710slab class 4: chunk size 176 perslab 5957slab class 5: chunk size 224 perslab 4681slab class 6: chunk size 280 perslab 3744slab class 7: chunk size 352 perslab 2978slab class 8: chunk size 440 perslab 2383slab class 9: chunk size 552 perslab 1899slab class 10: chunk size 696 perslab 1506slab class 11: chunk size 872 perslab 1202slab class 12: chunk size 1096 perslab 956slab class 13: chunk size 1376 perslab 762slab class 14: chunk size 1720 perslab 609slab class 15: chunk size 2152 perslab 487slab class 16: chunk size 2696 perslab 388slab class 17: chunk size 3376 perslab 310slab class 18: chunk size 4224 perslab 248slab class 19: chunk size 5280 perslab 198slab class 20: chunk size 6600 perslab 158slab class 21: chunk size 8256 perslab 127slab class 22: chunk size 10320 perslab 101slab class 23: chunk size 12904 perslab 81slab class 24: chunk size 16136 perslab 64slab class 25: chunk size 20176 perslab 51slab class 26: chunk size 25224 perslab 41slab class 27: chunk size 31536 perslab 33slab class 28: chunk size 39424 perslab 26slab class 29: chunk size 49280 perslab 21slab class 30: chunk size 61600 perslab 17slab class 31: chunk size 77000 perslab 13slab class 32: chunk size 96256 perslab 10slab class 33: chunk size 120320 perslab 8slab class 34: chunk size 150400 perslab 6slab class 35: chunk size 188000 perslab 5slab class 36: chunk size 235000 perslab 4slab class 37: chunk size 293752 perslab 3slab class 38: chunk size 367192 perslab 2slab class 39: chunk size 458992 perslab 2slab class 40: chunk size 573744 perslab 1slab class 41: chunk size 717184 perslab 1slab class 42: chunk size 1048576 perslab 1

从上图可以看到,默认情况下memcached把slab分为40类(class1~class40),在class 1中,chunk的大小为80字节,由于一个slab的大小是固定的1048576字节(1M),因此在class1中最多可以有13107个chunk:
13107×80 + 16 = 1048576
在class1中,剩余的16字节因为不够一个chunk的大小(80byte),因此会被浪费掉。

每类chunk的大小有一定的计算公式的,假定i代表分类,class i的计算公式如下:

chunk size(class i) :  (default_size+item_size)*factor^(i-1)+ CHUNK_ALIGN_BYTES// default_size: 默认大小为48字节,也就是memcached默认的key+value的大小为48字节,可以通过-n参数来调节其大小。// item_size: item结构体的长度,固定为32字节。default_size大小为48字节,item_size为32,因此class1的chunk大小为48+32=80字节。// factor: chunk变化大小的因素,默认值为1.25,调节f可以影响chunk的步进大小,在启动时可以使用-f来指定;认为factor在1.05~2范围内是合理的。// CHUNK_ALIGN_BYTES: 一个修正值,用来保证chunk的大小是某个值的整数倍(在32位机器上要求chunk的大小是4的整数倍)。

内存申请分配

这里写图片描述

向memcached添加一个item时候,memcached首先会根据item的大小,来选择最合适的slab class。
例如,item的大小为190字节,class 4的chunk大小为176字节不足以分配,class 5的chunk大小为224字节,大于190字节,因此该item将放在class 5中(显然这里会有34字节的浪费是不可避免的)是比较合适的。

计算好所要放入的chunk之后,memcached会去检查该类大小的chunk还有没有空闲的,如果没有,将会申请1M(1个slab)的空间并划分为该种类chunk。
例如,我们第一次向memcached中放入一个190字节的item时,memcached会产生一个slab class 5(也叫一个page),并会用去一个chunk,剩余4680个chunk供下次有适合大小item时使用,当我们用完这所有的4681个chunk之后,下次再有一个在177~224字节之间的item添加进来时,memcached会再次产生一个class 5的slab(这样就存在了2个pages)。

删除策略

memcached删除策略是Lazy Expiration
1. 当存储在内存中的对象过期甚至是flush_all时,它并不会做检查或删除操作,只有在get时查看数据的时间戳,查看数据是否过期。
2. 删除数据时,memcached同样是懒删除机制,只在对应的数据对象上做删除标识并不回收内存,在下次分配时直接覆盖使用。
3. 当memcached内存空间不足,即无法从slab class中获取到新的空间时,memcached使用LRU删除机制从最近未被使用的数据中搜索,将其空间分配给新的数据。

// 操作系统的内存管理,常用 FIFO,LRU 删除LRU: Least Recently Used 最近最少使用FIFO: First In ,First Out 先进先出

参考:
http://blog.csdn.net/think2me/article/details/52091740
http://www.cnblogs.com/codershuai/p/6150002.html

原创粉丝点击