专栏首页golang+phpMemcache的内存管理和删除机制

Memcache的内存管理和删除机制

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 条评论
登录 后参与评论

相关文章

  • redis源码之set结构

    关于set的命令和常用场景我们暂时先不说了,如果对命令不太熟悉的朋友可以用 help @set命令查看,我们先来看set中的一种现象

    程序员养成日记
  • 一条sql语句究竟是如何执行的

    相信做后端的同学肯定离不开一个话题,就是 mysql,大家也花式的执行过各种各样的 sql 语句,然后得到返回结果,那么一条 sql 语句执行究竟经历了哪些步骤...

    程序员养成日记
  • php数组hashtable的巧妙设计

    一个数组在 PHP 内核里是长什么样的呢?我们可以从 PHP 的源码里看到其结构如下:

    程序员养成日记
  • Linux吃掉了我的内存

    在Windows下资源管理器查看内存使用的情况,如果使用率达到80%以上,再运行大程序就能感觉到系统不流畅了,因为在内存紧缺的情况下使用交换分区,频繁地从磁盘上...

    马哥linux运维
  • Linux内存被吃掉了,它去哪里了?

    在Windows下资源管理器查看内存使用的情况,如果使用率达到80%以上,再运行大程序就能感觉到系统不流畅了,因为在内存紧缺的情况下使用交换分区,频繁地从磁盘上...

    小小科
  • 堕落小白的前台sql注入cms代码审计

    大家好我是一只没有灵魂小白鼠每日每夜都为了拿到那一点src的奖金日夜操劳。有一天我翻了翻日历算了一卦,好家伙今天是个挖洞的好日子。我打开电脑略微思考了一下人生...

    Ms08067安全实验室
  • POJ PKU 2826 An Easy Problem?! 解题报告

    题目链接: http://acm.pku.edu.cn/JudgeOnline/problem?id=2826

    owent
  • 开源日志系统 log4cplus 安装与使用(一)

    log4cplus是一个易于使用的C ++ 日志记录API,log4cplus具有灵活、强大、使用简单、多线程安全的特点。通过将信息划分优先级使其可以面向程序调...

    用户5908113
  • 堆外内存 之 DirectByteBuffer 详解

    tomas家的小拨浪鼓
  • 今咱们来聊聊JVM 堆外内存泄露的BUG是如何查找的前言内存泄露Bug现场查找线索总结

    美的让人心动

扫码关注云+社区

领取腾讯云代金券