[关闭]
@phper 2016-09-03T13:20:14.000000Z 字数 16699 阅读 7842

彻底弄清楚memcached

memcache


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

1. 下载 libevent 并安装

  1. [root@web3 vagrant]# wget http://downloads.sourceforge.net/levent/libevent-2.0.22-stable.tar.gz
  2. [root@web3 vagrant]# tar zxvf libevent-2.0.22-stable.tar.gz
  3. [root@web3 vagrant]# cd libevent-2.0.22-stable
  4. [root@web3 vagrant]# ./configure --prefix=/usr/local/libevent-2.0.22
  5. [root@web3 vagrant]# make
  6. [root@web3 vagrant]# make install

2. 下载memcache 并安装

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

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

  1. [root@web3 memcached-1.4.29]# cd /usr/local/memcached-1.4.25/
  2. [root@web3 memcached-1.4.25]# ls
  3. bin include share
  4. [root@web3 memcached-1.4.25]# cd bin/
  5. [root@web3 bin]# ls
  6. memcached
  7. [root@web3 bin]# cp memcached /usr/bin/memcached
  8. [root@web3 bin]#
  9. [root@web3 bin]# memcached -h
  10. memcached 1.4.29

4. 启动memcached

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

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

启动时候,常用的命令:

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

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

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

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

-m <num> 分配给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 <ip> ,小写的字母l, 监听的 IP 地址。本机的话不用设置。

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

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

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

-I <num> 大写的字母 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> <key> <flags> <exptime> <bytes> [<version>]
<datablock> 
<status>

详细看下面的表格:

参数 说明
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连接一下,来实际操作下。

链接:

  1. telnet 192.168.33.13 11211
  2. Trying 192.168.33.13...
  3. Connected to 192.168.33.13.
  4. Escape character is '^]'.
  1. # 1. set key flag exptime bytes
  2. # flag 是一个16位的无符号的整数标记,这里我们随便设置成一个数字16吧。
  3. set name 16 10 5 #设置name 为 5个字符,过期时间为10秒
  4. 12345
  5. STORED #成功
  6. get name #读取name的值
  7. VALUE name 16 5
  8. 12345
  9. END
  10. set name 16 10 5
  11. 1234
  12. CLIENT_ERROR bad data chunk
  13. ERROR #字符长度不符合,报错。
  14. get name
  15. END #过期了,没取到值
  16. set name 16 0 5
  17. 123456
  18. CLIENT_ERROR bad data chunk
  19. ERROR #字符长度不符合,报错。
  20. set name 16 0 5 #设置为不过期
  21. 12345
  22. STORED
  23. get name
  24. VALUE name 16 5
  25. 12345
  26. END #正确返回值
  27. set name2 16 2592000 3 #设置为刚好30天过期
  28. 123
  29. STORED #成功
  30. get name2
  31. VALUE name2 16 3
  32. 123
  33. END # 成功取出数据
  34. set name2 16 2592001 3 #30天多一秒
  35. 123
  36. STORED #成功了
  37. get name2
  38. END #但是取不到数据了!!!
  39. set name3 16 1476961243 5 #所以如果设置超过30天的过期时间时,就要用时间戳作为过期时间
  40. 12345
  41. STORED
  42. get name3
  43. VALUE name3 16 5
  44. 12345
  45. END #成功。
  46. # 2.add只能添加不存在的Key
  47. add name 16 1476961243 5 #使用add命令,会判断这个key是否存在
  48. 12345
  49. NOT_STORED #报错,没有存储成功,因为已经存在了。
  50. add name4 16 0 4
  51. 1234
  52. STORED #添加一个不存在的key就成功了。
  53. get name4
  54. VALUE name4 16 4
  55. 1234 #成功取到
  56. END
  57. # 3. replace 替换一个key的值,必须要已存在的。而且过期时间也会替换掉之前的。
  58. replace name4 17 100 5 #替换 name4的flag,expiretime,bytes
  59. 12345
  60. STORED #成功了。
  61. get name4
  62. VALUE name4 17 5
  63. 12345 #成功取出
  64. END
  65. replace name4 16 3 2 #替换expiretime为3秒
  66. 12
  67. STORED
  68. get name4 #已过期。
  69. END
  70. replace name5 16 0 4 # 替换一个不存在的key name5
  71. 1234
  72. NOT_STORED #报错没有存储成功
  73. # 4. append 在一个key 的 value 后面追加字符。
  74. # 注意:追加不会破坏原先的过期时间。
  75. set name 16 0 4
  76. 1234
  77. STORED
  78. append name 16 3 2 #在后面追加2个字符12,并改变flag和expiretime
  79. 12
  80. STORED 成功了。
  81. get name
  82. VALUE name 16 6
  83. 123412 # 成功取出,而且过期时间不受影响。
  84. END
  85. # 5. prepend 在一个 key 的 value 前面追加字符。
  86. # 注意:追加不会破坏原先的过期时间。
  87. set name 16 0 5
  88. 12345
  89. STORED
  90. prepend name 16 0 2 #在前面追加
  91. 67
  92. STORED #成功
  93. get name
  94. VALUE name 16 7
  95. 6712345 #成功
  96. END
  97. prepend name 16 3 1 #改变过期时间为3秒。
  98. 8
  99. STORED #成功
  100. get name #3秒之后访问,仍让还在。
  101. VALUE name 16 8
  102. 86712345
  103. END
  104. # 6. cas即check and set,只有版本号相匹配时才能存储,否则返回EXISTS。
  105. 版本号的概念 在讲 gets 命令时,一起说。

6.2 读取命令

get/gets

读取命令的格式为:

get/gets key1 key2 ...keyn

返回值为:

get/gets key1... keyn
VALUE <key1> <flags> <bytes> [<version>]
<value1>
…
VALUE <keyn> <flags> <bytes> [<version>]
<valuen>
END

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

看栗子吧:

  1. #1. get 同时get2个key的值
  2. get name name4
  3. VALUE name 16 1 #返回了key的名字、flag、以及bytes
  4. 2
  5. VALUE name4 16 3
  6. 123
  7. END
  8. 2. gets 会多返回一个version
  9. gets name name4
  10. VALUE name 16 1 31 #version为31
  11. 2
  12. VALUE name4 16 3 32 #version 为32
  13. 123
  14. END
  15. set name4 16 0 3
  16. 456
  17. STORED #改变name4的值
  18. gets name4
  19. VALUE name4 16 3 33 #version 改变了
  20. 456
  21. END

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

cas <key> <flag> <verion> <bytes> <version> 

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

看下栗子:

  1. gets name4
  2. VALUE name4 16 3 33 #version 为33
  3. 456
  4. END
  5. cas name4 16 0 2 30 #我们输入version为30
  6. 12
  7. EXISTS #失败,说已经存在。
  8. cas name4 16 0 2 33 #输入一样的version
  9. 12
  10. STORED #成功
  11. gets name4
  12. VALUE name4 16 2 34 #并且生成新的version
  13. 12
  14. END

6.3 删除命令

delete

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

delete key1

直接上栗子:

  1. delete name4
  2. DELETED #成功
  3. get name4
  4. END
  5. delete name name3
  6. 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. # 1. incr 增加
  2. set name 16 0 2
  3. 12
  4. STORED
  5. incr name 1 #成功,并返回加1的value
  6. 13
  7. # 2. decr 减少
  8. decr name 10 #减去10,返回了3
  9. 3
  10. decr name 10 #继续减10,就直接返回0了
  11. 0
  12. decr name 10 #返回0
  13. 0
  14. #设置为字符串
  15. get name5
  16. VALUE name5 16 3 #字符串
  17. qwe
  18. END
  19. incr name5 1 #报错,说不能增加或者减少非数字型
  20. CLIENT_ERROR cannot increment or decrement non-numeric value

6.5 统计命令

stats/settings/items/sizes/slabs

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

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

运行看一下:

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

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

7. memcached内存管理机制

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

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

格子本

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

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。

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

slab class图

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

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

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

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

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

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注