Memcache的内存管理和删除机制

2020-09-07 15:36:26 浏览数 (1)

1:内存的碎片化

如果c语言直接向系统malloc,free申请和释放内存时,在不断的申请和释放的过程中,形成了一些很小的内存片段,无法再利用,这种空闲,但无法利用内存的现象,---成为内存的碎片化

2:slab allocator缓解内存碎片化

Slab allocator原理 提前把内存分为多个 slab allocator仓库(每个slab allocator大小1M),各个仓库,切成不同的小块(chunk) 需要存储内容的时候,判断内容的大小,为其选取合理的仓库

image.png

3:系统如何选择合适的chunk?

Memcache根据收到的数据大小,选择最适合数据大小的chunk组(slab class),memcache中保存着slab class内空闲chunk列表,根据该列表选择空的chunk,然后将数据缓存于其中

image.png

如果有 100byte 的内容要存,但 122 大小的仓库中的 chunk 满了

并不会寻找更大的,如 144 的仓库来存储,

而是把 122 仓库的旧数据踢掉! 详见过期与删除机制

4:固定大小的trunk带来的问题

由于在slab allocator分配机制中,分配的trunk的大小是固定的,对于特定的item,很有可能造成内存空间的浪费 比如100字节的数据缓存到122字节的chunk中,剩余的22字节就浪费了

image.png

对于chunk空间浪费的问题,我们无法彻底的解决,只能缓解 开发者可以对网站中需要存储的item的长度进行统计,并制定合理的slab class中的trunk的大小 但是,目前我们无法指定trunk的大小,只能调节slab class中trunk大小的增长速度,即很重要的一个概念,增长因子 grow factor!

5:grow factor调优

Memcache在启动的时候可以通过-f来调节增长因子,并在某种程度上控制slab之间的差异,默认值为1.25,但是,在该选项出现之前,这个值被固定为2,被称为 power of 2策略 我们分别把grow factor调为2和1.5来看看效果

image.png

image.png

对比可知,当f=2的时候,各个slab中的trunk增长的快一些,有些情况下可能就会造成一定的浪费,所以我们应该细心的计算缓存的大小,制定合理的增长因子 注意:在上列图标中我们可以看到,有些增长速度并非是f的值,可能有一定的误差,这些误差是为了数字对应整齐故意设置的

6:Memcache的过期数据惰性删除

  • 当某个值过期后,并没有从内存删除, 因此,stats 统计时, curr_item 有其信息
  • 当某个新值去占用他的位置时,当成空 chunk 来占用.
  • 当 get 值时,判断是否过期,如果过期,返回空,并且清空, curr_item 就减少了. 即--这个过期,只是让用户看不到这个数据而已,并没有在过期的瞬间立即从内存删除. 这个称为 lazy expiration, 惰性失效. 好处--- 节省了 cpu 时间和检测的成本

7: memcached 的 此处用的 lru 删除机制.

如果以 122byte 大小的 chunk 举例, 122 的 chunk 都满了, 又有新的值(长度为 120)要加入, 要 挤掉谁? memcached 此处用的 lru 删除机制. (操作系统的内存管理,常用 fifo,lru 删除) lru: least recently used 最近最少使用 fifo: first in ,first out 原理: 当某个单元被请求时,维护一个计数器,通过计数器来判断最近谁最少被使用. 就把谁 t 出. 注: 即使某个 key 是设置的永久有效期,也一样会被踢出来! 即--永久数据被踢现象

8 memcached 中的一些参数限制

key 的长度: 250 字节, (二进制协议支持 65536 个字节) value 的限制: 1m, 一般都是存储一些文本,如新闻列表等等,这个值足够了. 内存的限制: 32 位下最大设置到 2g. 如果有 30g 数据要缓存,一般也不会单实例装 30g, (不要把鸡蛋装在一个篮子里), 一般建议 开启多个实例(可以在不同的机器,或同台机器上的不同端口)

0 人点赞