彻底弄清楚memcached

彻底弄清楚memcached

标签(空格分隔): memcache


memcached 是一个高效支持多线程的内存存储系统。接下来会从安装、使用、内存分配一步步来分析memcached。

1. 下载 libevent 并安装

[root@web3 vagrant]# wget http://downloads.sourceforge.net/levent/libevent-2.0.22-stable.tar.gz

[root@web3 vagrant]# tar zxvf libevent-2.0.22-stable.tar.gz
[root@web3 vagrant]# cd libevent-2.0.22-stable
[root@web3 vagrant]# ./configure --prefix=/usr/local/libevent-2.0.22
[root@web3 vagrant]# make
[root@web3 vagrant]# make install

2. 下载memcache 并安装

[root@web3 vagrant]# wget http://memcached.org/files/memcached-1.4.29.tar.gz
[root@web3 vagrant]# tar zxvf memcached-1.4.29.tar.gz
[root@web3 vagrant]# cd memcached-1.4.29
[root@web3 memcached-1.4.29]# ./configure --prefix=/usr/local/memcached-1.4.25 --with-libevent=/usr/local/libevent-2.0.22
[root@web3 memcached-1.4.29]# make
[root@web3 memcached-1.4.29]# make install

3. 拷贝memcached命令到系统bin目录

[root@web3 memcached-1.4.29]# cd /usr/local/memcached-1.4.25/
[root@web3 memcached-1.4.25]# ls
bin  include  share
[root@web3 memcached-1.4.25]# cd bin/
[root@web3 bin]# ls
memcached
[root@web3 bin]# cp memcached /usr/bin/memcached
[root@web3 bin]#
[root@web3 bin]# memcached -h
memcached 1.4.29

4. 启动memcached

[root@web3 bin]# memcached -p 11211 -m 64 -u root -vv

slab class   1: chunk size        96 perslab   10922
slab class   2: chunk size       120 perslab    8738
slab class   3: chunk size       152 perslab    6898
slab class   4: chunk size       192 perslab    5461
slab class   5: chunk size       240 perslab    4369
slab class   6: chunk size       304 perslab    3449
slab class   7: chunk size       384 perslab    2730
slab class   8: chunk size       480 perslab    2184
slab class   9: chunk size       600 perslab    1747
slab class  10: chunk size       752 perslab    1394
slab class  11: chunk size       944 perslab    1110
slab class  12: chunk size      1184 perslab     885
slab class  13: chunk size      1480 perslab     708
slab class  14: chunk size      1856 perslab     564
slab class  15: chunk size      2320 perslab     451
slab class  16: chunk size      2904 perslab     361
slab class  17: chunk size      3632 perslab     288
slab class  18: chunk size      4544 perslab     230
slab class  19: chunk size      5680 perslab     184
slab class  20: chunk size      7104 perslab     147
slab class  21: chunk size      8880 perslab     118
slab class  22: chunk size     11104 perslab      94
slab class  23: chunk size     13880 perslab      75
slab class  24: chunk size     17352 perslab      60
slab class  25: chunk size     21696 perslab      48
slab class  26: chunk size     27120 perslab      38
slab class  27: chunk size     33904 perslab      30
slab class  28: chunk size     42384 perslab      24
slab class  29: chunk size     52984 perslab      19
slab class  30: chunk size     66232 perslab      15
slab class  31: chunk size     82792 perslab      12
slab class  32: chunk size    103496 perslab      10
slab class  33: chunk size    129376 perslab       8
slab class  34: chunk size    161720 perslab       6
slab class  35: chunk size    202152 perslab       5
slab class  36: chunk size    252696 perslab       4
slab class  37: chunk size    315872 perslab       3
slab class  38: chunk size    394840 perslab       2
slab class  39: chunk size    493552 perslab       2
slab class  40: chunk size    616944 perslab       1
slab class  41: chunk size    771184 perslab       1
slab class  42: chunk size   1048576 perslab       1
<26 server listening (auto-negotiate)
<27 server listening (auto-negotiate)
<28 send buffer was 124928, now 268435456
<32 send buffer was 124928, now 268435456
<30 server listening (udp)
<34 server listening (udp)
<31 server listening (udp)
<35 server listening (udp)
<29 server listening (udp)
<33 server listening (udp)
<28 server listening (udp)
<32 server listening (udp)

5. memcached 启动时加的常用命令

启动时候,常用的命令:

[root@web3 bin]# memcached -h #可以看所有的命令

由于命令很多,看几个常见的命令:

-p 指定服务TCP端口,默认为11211,默认会监听tcp和udp端口。

比如:memcached -p 11200 表示监听11200端口

-m 分配给memcached用作缓存的内存大小,单位为MB,默认64M

比如:memcached -m 1024 表示分配1g的内存给memcached

-u 是运行Memcache的用户,如果当前为 root 的话,则必须使用此参数指定用户,不然会报错:can’t run as root without the -u switch

比如:memcached -u yangyi 表示用yangyi 这个帐户运行memcached

-l ,小写的字母l, 监听的 IP 地址。本机的话不用设置。

-f chunk size的增长因子(合理范围1.05~2,默认:1.25)。

-t Memcached启动的工作线程数,默认为4,建议不要超过系统 CPU的个数。

-c 最大同时连接数,默认是1024。

-I 大写的字母 i ,改变slab page的容量大小,以调整ITEM容量的最大值,默认为1MB。最大可以支持128M

-vv 输出详细的信息。

-d 启动一个守护进程,后台运行。

-P 指定pid的路径

比如:memcached -P /tmp/memcached.pid

-h 打印版本和帮助信息,然后退出。

6. memcached命令列表

memcached的命令分为以下5个大类。

6.1 存储命令

set/add/replace/append/prepend/cas

存储命令的格式:

     []
 

详细看下面的表格:

参数 说明
command set无论如何都进行存储,add只有数据不存在时进行添加
key 存储的key的名字,长度最多为250个字符,不包含空格和控制字符
flags 是一个16位的无符号的整数(以十进制的方式表示)。该标志将和需要存储的数据一起存储,并在客户端get数据时返回
exptime 过期时间,单位为秒,0为永远,表示用不过期,<30天60*60*24*30为秒数,>30天为unixtime时间戳
bytes byte字节数,不包含\r\n,根据长度截取存/取的字符串,可以是0,即存空串
version 版本号,可选的,可不写,这个字断主要是给cas命令用
datablock 储存的内容value,以\r\n结尾,当然可以包含\r或\n
status STORED/NOT_STORED/EXISTS/NOT_FOUND/ERROR/CLIENT_ERROR/SERVER_ERROR服务端返回的状态标志

用telnet连接一下,来实际操作下。

链接:

telnet 192.168.33.13 11211
Trying 192.168.33.13...
Connected to 192.168.33.13.
Escape character is '^]'.
# 1. set key flag exptime bytes
# flag 是一个16位的无符号的整数标记,这里我们随便设置成一个数字16吧。

set name 16 10 5 #设置name 为 5个字符,过期时间为10秒
12345
STORED #成功

get name #读取name的值
VALUE name 16 5
12345
END

set name 16 10 5
1234

CLIENT_ERROR bad data chunk
ERROR  #字符长度不符合,报错。

get name
END #过期了,没取到值

set name 16 0 5
123456
CLIENT_ERROR bad data chunk
ERROR #字符长度不符合,报错。

set name 16 0 5 #设置为不过期
12345
STORED

get name
VALUE name 16 5
12345
END #正确返回值

set name2 16 2592000 3 #设置为刚好30天过期
123
STORED #成功

get name2
VALUE name2 16 3
123
END # 成功取出数据

set name2 16 2592001 3 #30天多一秒
123
STORED  #成功了

get name2 
END #但是取不到数据了!!!

set name3 16 1476961243 5 #所以如果设置超过30天的过期时间时,就要用时间戳作为过期时间
12345
STORED

get name3
VALUE name3 16 5
12345
END #成功。

# 2.add只能添加不存在的Key
add name 16 1476961243 5 #使用add命令,会判断这个key是否存在
12345
NOT_STORED  #报错,没有存储成功,因为已经存在了。

add name4 16 0 4
1234
STORED #添加一个不存在的key就成功了。

get name4
VALUE name4 16 4
1234 #成功取到
END


# 3. replace 替换一个key的值,必须要已存在的。而且过期时间也会替换掉之前的。
replace name4 17 100 5 #替换 name4的flag,expiretime,bytes
12345
STORED #成功了。

get name4
VALUE name4 17 5
12345 #成功取出
END

replace name4 16 3 2 #替换expiretime为3秒
12
STORED

get name4 #已过期。
END

replace name5 16 0 4 # 替换一个不存在的key name5
1234
NOT_STORED #报错没有存储成功

# 4. append 在一个key 的 value 后面追加字符。
# 注意:追加不会破坏原先的过期时间。

set name 16 0 4
1234
STORED

append name 16 3 2 #在后面追加2个字符12,并改变flag和expiretime
12
STORED 成功了。

get name
VALUE name 16 6
123412  # 成功取出,而且过期时间不受影响。
END

# 5. prepend 在一个 key 的 value 前面追加字符。
# 注意:追加不会破坏原先的过期时间。

set name 16 0 5
12345
STORED

prepend name 16 0 2 #在前面追加
67
STORED #成功

get name
VALUE name 16 7
6712345 #成功
END

prepend name 16 3 1 #改变过期时间为3秒。
8
STORED #成功

get name #3秒之后访问,仍让还在。
VALUE name 16 8 
86712345
END

# 6. cas即check and set,只有版本号相匹配时才能存储,否则返回EXISTS。

版本号的概念 在讲 gets 命令时,一起说。

6.2 读取命令

get/gets

读取命令的格式为:

get/gets key1 key2 ...keyn

返回值为:

get/gets key1... keyn
VALUE    []

…
VALUE    []

END

gets较get命令,会多返回一个版本号 version, 用于标识名称/值对, 每次set 新的 value后,verison都会变化。

看栗子吧:

#1. get 同时get2个key的值
get name name4
VALUE name 16 1 #返回了key的名字、flag、以及bytes
2
VALUE name4 16 3
123
END

#2. gets 会多返回一个version
gets name name4
VALUE name 16 1 31 #version为31
2
VALUE name4 16 3 32 #version 为32
123
END

set name4 16 0 3
456
STORED #改变name4的值

gets name4
VALUE name4 16 3 33 #version 改变了
456
END

gets命令会多返回一个version值。那么就可以说上面没说完的cas命令了:

cas      

cas(check 和 set),给一个已经存在的key设置新的value,但是它会先检查 version和它gets的version是否一致,如果是一致的,则会生效,否则会报错 EXISTS。

看下栗子:

gets name4
VALUE name4 16 3 33 #version 为33
456
END

cas name4 16 0 2 30 #我们输入version为30
12
EXISTS #失败,说已经存在。

cas name4 16 0 2 33 #输入一样的version
12
STORED #成功

gets name4
VALUE name4 16 2 34 #并且生成新的version
12
END

6.3 删除命令

delete

删除命令最简单了,删除一个key,只能一个一个的删,不能批量

delete key1

直接上栗子:

delete name4
DELETED #成功
get name4
END

delete name name3
CLIENT_ERROR bad command line format.  Usage: delete <key> [noreply] #报错,不能批量删除

6.4 计数命令

incr/decr

计数命令,用来对value为int数字型的key进行加n或者减n操作。

用法为:

incr key number
value + number

decr key number
value - number

直接看栗子:

# 1. incr 增加
set name 16 0 2
12
STORED

incr name 1 #成功,并返回加1的value
13

# 2. decr 减少
decr name 10 #减去10,返回了3
3

decr name 10 #继续减10,就直接返回0了
0

decr name 10 #返回0
0


#设置为字符串
get name5
VALUE name5 16 3 #字符串
qwe
END

incr name5 1 #报错,说不能增加或者减少非数字型
CLIENT_ERROR cannot increment or decrement non-numeric value

6.5 统计命令

stats/settings/items/sizes/slabs

统计命令,主要是来维护和统计memcached的一些命令,属于管理命令来。

stats 命令用来统计memcached的运行状态:

运行看一下:

stats
STAT pid 9752  #memcached运行的进程pid
STAT uptime 50034  #memcached的运行时间(秒)
STAT time 1469232745  #当前的UNIX时间戳
STAT version 1.4.29  #memcached的版本号
STAT libevent 2.0.22-stable  #memcached使用的libevent的版本号
STAT pointer_size 64  #操作系统的位数,32或64。我这里是64位
STAT rusage_user 8.855653  #该进程累计的用户时间(秒)
STAT rusage_system 26.481974  #该进程累计的系统时间(秒)
STAT curr_connections 10  #当前连接数
STAT total_connections 12  #服务器运行以来接受的连接总数
STAT connection_structures 12  #Memcached分配的连接结构的数量
STAT reserved_fds 20 #misc fds使用数 
STAT cmd_get 81  #get命令执行的次数
STAT cmd_set 47  #set命令执行的次数
STAT cmd_flush 0   #flush_all命令执行的次数
STAT cmd_touch 0  #执行touch的次数,touch可以刷新过期时间 
STAT get_hits 59  #命中的次数,获取数据成功的次数
STAT get_misses 22   #没有命中的次数,获取数据失败的次数
STAT get_expired 7   #
STAT get_flushed 0
STAT delete_misses 0  #delete未命中次数
STAT delete_hits 1   #delete命中次数
STAT incr_misses 0   #incr命中次数
STAT incr_hits 3    #incr未命中次数
STAT decr_misses 0   #decr未命中次数
STAT decr_hits 3    #decr命中次数
STAT cas_misses 0   #cas未命中次数
STAT cas_hits 3    #cas命中次数
STAT cas_badval 2   #使用擦拭次数 
STAT touch_hits 0    #touch命中次数  
STAT touch_misses 0   #touch未命中次数
STAT auth_cmds 0    #authentication 执行的次数 
STAT auth_errors 0   #authentication 执行失败的次数 
STAT bytes_read 2724   #memcached服务器从网络读取的总的字节数
STAT bytes_written 8610 #memcached服务器发送到网络的总的字节数。
STAT limit_maxbytes 67108864 #memcached服务缓存允许使用的最大字节数。这里为67108864字节,也就是是64M.与我们启动memcached服务设置的大小一致。
STAT accepting_conns 1  #正在接受的连接数
STAT listen_disabled_num 0   #拒绝连接尝试的次数,因为memcached的达到其配置的连接限制("-C"参数)。
STAT time_in_listen_disabled_us 0
STAT threads 4  #当前Memcached服务器使用的线程数。("-t" 参数指定)
STAT conn_yields 0  #memcached 启动至今有多少次打开的连接因为内部请求数达到 -R 参数指定的限值而被动放弃  
STAT hash_power_level 16  #hashpower的level,可以在启动的时候设置($ memcached -o hashpower=20)
STAT hash_bytes 524288  #内存使用总量单位为byte  
STAT hash_is_expanding 0  #是否正在扩大hash表
STAT malloc_fails 0
STAT log_worker_dropped 0
STAT log_worker_written 0
STAT log_watcher_skipped 0
STAT log_watcher_sent 0
STAT bytes 146  #当前memcached服务器上保存数据的字节数
STAT curr_items 2  #当前在memcached服务器上存储的数据项的个数
STAT total_items 38  #在服务器上曾经保存过的数据项的总数
STAT expired_unfetched 0  
STAT evicted_unfetched 0
STAT evictions 0  #因超时而被替换出内存的数据项的个数
STAT reclaimed 2  # memcached 启动至今有多少次在存储数据的时候使用了过期数据的空间  
STAT crawler_reclaimed 0 
STAT crawler_items_checked 0
STAT lrutail_reflocked 0
END

stats 还有几个子命令集合,这些等我们说完memcached的存储和结构后再来看。

7. memcached内存管理机制

前面基本上把memcache的安装和使用说的差不多了,基本可以正常友好的使用memcached了。现在我们来看下memcached的内存分配和管理机制。

在熟悉memcached的内存管理之前,我们先拿小学生的格子作业本来举例子,把格子本比作memcached的内存分配。每个作业本(memcached的内存空间),它都有很页(slab),每一页里面有很多方格子(trunk),每个格子里面可以写字(item)。

彻底弄清楚memcached_第1张图片

在脑海中有这样一个印象之后,我们开始讲上面提到的几个名词:

7.1 slab、chunk

上面说到的格子本的一页纸,就一个是slab, 是memcached分配的一块内存空间,默认大小为1M。memcached会将内存空间分配成一个一个的slab,还会把一个slab分割成一个一个的格子,也就是一个一个chunk,比如说1M的slab分成两个0.5M的chunk,slab和chunk其实都是代表实质的内存空间,chunk是slab分割后的更小的单元。所以:slab就相当于作业本中的“一页纸”,而chunk则是把这一页纸中的一个个的“格子”。

7.2 item

item是我们要保存的数据,也就是我们需要在“格子”中写入的“字”。

比如,在PHP中我们这样设置一个缓存:

$memcached->set(“name”,”abc”,30);

这行代码代表我们把一个key为name,value为abc的键值对保存在内存中30秒,那么上述中的”name”、 “abc”、“30”这些数据实质都是我们要memcached保存下来的数据, memcached会把这些数据打包成一个item,把打包好的item填充到chunk中,一个item保存在一个chunk。chunk是实质的内存空间,item是要保存的东西,所以关系是:item是往chunk中塞的。

还是拿作业本来比喻,item就是相当于我们要写的“字”,把它写到作业本某一“页(slab)”中的“格子(chunk)”里。

7.3 slabclass

通过上面我们知道,slab(都假设为1M)会割成一个个chunk,而item往chunk中塞。

那么问题来了:

我们要把这个1M的slab割成多少个chunk?就是一页纸,要画多少个格子?

我们往chunk中塞item的时候,item总不可能会与chunk的大小完全匹配吧,chunk太小塞不下或者chunk太大浪费了怎么办?就是我们写字的时候,格子太小,字出界了,或者我们的字很小写在一个大格子里面好浪费。

所以memcached的设计是,我们会准备“几种不同格子的slab”,也就是说根据“slab分割的chunk的大小不一样”来分成“不同的种类的slab”,而 slabclass就是“slab的种类”的意思了。

继续拿作业本来比喻:假设我们现在有很多张A4纸,有些我们画成100个格子,有些我们画成200个格子,有些300,我们把画了相同个格子(也相同大小)的纸钉在一起,成为一本本“作业本”,每本“作业本”的格子大小都是一样的,不同的“作业本”也代表着“画了不同的大小格子的A4纸的集合”,而这个作业本就是slabclass啦!

所以当你要写字(item)的时候,你估一下你的字有多“大”,然后挑一本作业本(slabclass),在某一页(slab)空白的格子(chunk)上写。

每个slabclass在memcached中都表现为一个结构体,里面会有个指针,指向它的那一堆slab。

7.4 trunk大小的分配

slab是一个内存块,它是memcached一次申请内存的最小单位。在启动memcached的时候一般会使用参数-m指定其可用的最大内存,在启动的时候memcached并不会把有的内存就全部分配出去了,只有在需要的时候才会去申请,而且每次申请一定是一个slab。Slab的大小固定为1M(1048576Byte),一个slab由若干个大小相等的chunk组成。每个chunk中都保存了一个item结构体。

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

所以总结下,看下这张图:

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

[root@web3 bin]# memcached -p 11211 -m 64 -u root -vv
slab class   1: chunk size        96 perslab   10922
slab class   2: chunk size       120 perslab    8738
slab class   3: chunk size       152 perslab    6898
slab class   4: chunk size       192 perslab    5461
slab class   5: chunk size       240 perslab    4369
slab class   6: chunk size       304 perslab    3449
slab class   7: chunk size       384 perslab    2730
slab class   8: chunk size       480 perslab    2184
slab class   9: chunk size       600 perslab    1747
slab class  10: chunk size       752 perslab    1394
slab class  11: chunk size       944 perslab    1110
slab class  12: chunk size      1184 perslab     885
slab class  13: chunk size      1480 perslab     708
slab class  14: chunk size      1856 perslab     564
slab class  15: chunk size      2320 perslab     451
slab class  16: chunk size      2904 perslab     361
slab class  17: chunk size      3632 perslab     288
slab class  18: chunk size      4544 perslab     230
slab class  19: chunk size      5680 perslab     184
slab class  20: chunk size      7104 perslab     147
slab class  21: chunk size      8880 perslab     118
slab class  22: chunk size     11104 perslab      94
slab class  23: chunk size     13880 perslab      75
slab class  24: chunk size     17352 perslab      60
slab class  25: chunk size     21696 perslab      48
slab class  26: chunk size     27120 perslab      38
slab class  27: chunk size     33904 perslab      30
slab class  28: chunk size     42384 perslab      24
slab class  29: chunk size     52984 perslab      19
slab class  30: chunk size     66232 perslab      15
slab class  31: chunk size     82792 perslab      12
slab class  32: chunk size    103496 perslab      10
slab class  33: chunk size    129376 perslab       8
slab class  34: chunk size    161720 perslab       6
slab class  35: chunk size    202152 perslab       5
slab class  36: chunk size    252696 perslab       4
slab class  37: chunk size    315872 perslab       3
slab class  38: chunk size    394840 perslab       2
slab class  39: chunk size    493552 perslab       2
slab class  40: chunk size    616944 perslab       1
slab class  41: chunk size    771184 perslab       1
slab class  42: chunk size   1048576 perslab       1
<26 server listening (auto-negotiate)
<27 server listening (auto-negotiate)
<28 send buffer was 124928, now 268435456
<32 send buffer was 124928, now 268435456
<30 server listening (udp)
<34 server listening (udp)
<31 server listening (udp)
<35 server listening (udp)
<29 server listening (udp)
<33 server listening (udp)
<28 server listening (udp)
<32 server listening (udp)

memcached把slab分为40类(class1~class40),在class 1中,chunk的大小为96字节,由于一个slab的大小是固定的1048576字节(1M),因此在class1中最多可以有perslab = 10922个chunk:

10922×80 + 64 = 1048576

在class1中,剩余的64字节因为不够一个chunk的大小(96byte),因此会被浪费掉。

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

chunk size(class i) = (default_size+item_size)*f^(i-1) + CHUNK_ALIGN_BYTES

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

所以,我们可以根据自己的业务需求,通过-f-n参数,来合理划分trunk的大小。

我们,来修改下-f-n来重新启动下memcached:

[root@web3 ~]# memcached -u root -m 64 -p 11211 -n 80 -vv
slab class   1: chunk size       128 perslab    8192
slab class   2: chunk size       160 perslab    6553
slab class   3: chunk size       200 perslab    5242
slab class   4: chunk size       256 perslab    4096
slab class   5: chunk size       320 perslab    3276
slab class   6: chunk size       400 perslab    2621
slab class   7: chunk size       504 perslab    2080
slab class   8: chunk size       632 perslab    1659
slab class   9: chunk size       792 perslab    1323
slab class  10: chunk size       992 perslab    1057
slab class  11: chunk size      1240 perslab     845
slab class  12: chunk size      1552 perslab     675
slab class  13: chunk size      1944 perslab     539
slab class  14: chunk size      2432 perslab     431
slab class  15: chunk size      3040 perslab     344
slab class  16: chunk size      3800 perslab     275
slab class  17: chunk size      4752 perslab     220
slab class  18: chunk size      5944 perslab     176
slab class  19: chunk size      7432 perslab     141
slab class  20: chunk size      9296 perslab     112
slab class  21: chunk size     11624 perslab      90
slab class  22: chunk size     14536 perslab      72
slab class  23: chunk size     18176 perslab      57
slab class  24: chunk size     22720 perslab      46
slab class  25: chunk size     28400 perslab      36
slab class  26: chunk size     35504 perslab      29
slab class  27: chunk size     44384 perslab      23
slab class  28: chunk size     55480 perslab      18
slab class  29: chunk size     69352 perslab      15
slab class  30: chunk size     86696 perslab      12
slab class  31: chunk size    108376 perslab       9
slab class  32: chunk size    135472 perslab       7
slab class  33: chunk size    169344 perslab       6
slab class  34: chunk size    211680 perslab       4
slab class  35: chunk size    264600 perslab       3
slab class  36: chunk size    330752 perslab       3
slab class  37: chunk size    413440 perslab       2
slab class  38: chunk size    516800 perslab       2
slab class  39: chunk size    646000 perslab       1
slab class  40: chunk size    807504 perslab       1
slab class  41: chunk size   1048576 perslab       1
<26 server listening (auto-negotiate)
<27 server listening (auto-negotiate)
<28 send buffer was 124928, now 268435456
<32 send buffer was 124928, now 268435456
<30 server listening (udp)
<34 server listening (udp)
<31 server listening (udp)
<35 server listening (udp)
<29 server listening (udp)
<33 server listening (udp)
<28 server listening (udp)
<32 server listening (udp)

可以看见class1的chunk大小为:80+48字节,根据具体的业务预估缓存数据的最小值以便设置memcache的chunk初始值,避免内存浪费。

memcache默认的slab大小是1M,所以不能存入大小超过1M的数据,但一旦需要存入大数据时可以使用-I参数来设置slab的值,但是不推荐将slab值设置为超过1M。

7.5 内存分配申请

向memcached添加一个item时候,memcached首先会根据item的大小,来选择最合适的slabclass。例如item的大小为190字节。

slab class   3: chunk size       152 perslab    6898
slab class   4: chunk size       192 perslab    5461

默认情况下slb class 4的chunk大小为192字节,因此是可以放到在class4中(显然这里会有2字节的浪费是不可避免的),计算好所要放入的chunk之后,memcached会去检查该类大小的chunk还有没有空闲的,如果没有,将会申请1M(1个slab)的slab class4 空间并划分为该种类chunk。

例如我们第一次向memcached中放入一个190字节的item时,memcached会使用slab class4,并会用去一个chunk,剩余5460个chunk供下次有适合大小item时使用,当我们用完这所有的5460个chunk之后,下次再有一个在152~192字节之间的item添加进来时,memcached会再申请空间生成一个class4的slab(这样就存在了2个slab class4)。

7.6 删除策略

memcached是懒检测机制,当存储在内存中的对象过期甚至是flush_all时,它并不会做检查或删除操作,只有在get时才检查数据对象是否应该删除。删除数据时,Memcached同样是懒删除机制,只在对应的数据对象上做删除标识并不回收内存,在下次分配时直接覆盖使用。

所以,当memcached过期或者删除的时候,它所占用的内存并不会释放,除非重新启动。

参考:

http://www.bo56.com/%E6%B3%A8%E6%84%8Fphp-memcached%E6%89%A9%E5%B1%95%E9%BB%98%E8%AE%A4%E9%85%8D%E7%BD%AE%E4%B8%8B%E6%97%A0%E6%B3%95%E8%87%AA%E5%8A%A8failover/

http://www.cnblogs.com/moqiang02/p/4061151.html

http://blog.csdn.net/clh604/article/details/39401249

http://blog.wpjam.com/m/php-memcached-persistent-mode/

http://blog.csdn.net/wangsg2014/article/details/17451273

http://www.dexcoder.com/selfly/article/2248

http://www.dexcoder.com/selfly/article/2388

http://blog.csdn.net/lgh1117/article/details/11742023

http://ccvita.com/306.html

http://calixwu.com/2014/11/memcached-yuanmafenxi-neicunguanli.html

你可能感兴趣的:(memcached)