网上其实有很多文章说明了memcached是如何运作的,特别是底层的内存分配是如何运作的。我参考过很多资料,比较有启发意义的有几个:

  • 首先是官方的英文资料,虽然文章太多、很难看懂,我个人觉得说得也不是太清晰,不够直观(附上官方wiki地址)。还有git上memcached原作者的protocol.txt也值得一读,有时间的话,我会翻译一下。
  • 其次是mixi网站的核心技术人员写的5篇全面剖析,这5篇文章写得很实用,从各方面彻底解剖了memcached,可惜的是这一系列文章对于核心的内存分配逻辑描述还不够详细(个人觉得),而且很多监控方面的guide都是基于mixi站点已经有的一套框架,对于从头开发的人来说只能是用来指明方向的,实际指导意义不大(附上我转载的帖子入口)。
  • 此外还有Mike Perham的一篇博客,写得不错,很详细地举例说明了memcached内部的内存分配逻辑,以及内存浪费现象。
  • 还有梁子的一篇博客,也是一篇很好的博客,从他的角度非常详细地描述了memcached内部的内存分配逻辑。我个人觉得他的文章解释的是最清楚的,虽然在文笔和错别字上实在是。。。。

1. 几个关键概念

Page为内存分配的单位
Memcached的内存分配以page为单位,默认情况下一个page是1M,可以通过-I参数修改,最小1K,最大128M。如果需要申请内存时,memcached会划分出一个新的page并分配给需要的slab区域。page一旦被分配在memcached重启前不会被回收或者重新分配(page ressign已经从1.2.8版移除了)。

Slabs划分数据空间
Memcached并不是将所有大小的数据都放在一起的,而是预先将数据空间划分为一系列大小的slabs,每个slab只负责一定大小范围内的数据存储。每个slab只存储大于其上一个slab的size并小于或者等于自己最大size的数据。例如:slab 3只存储大小介于137 到 224 bytes的数据。如果一个数据大小为230byte的数据进行存储,它将被分配到slab 4中。每个slab负责的空间其实是不等的,memcached默认情况下下一个slab的最大值为前一个的1.25倍,这个可以通过修改-f参数来修改增长比例。

Chunk才是存放缓存数据的单位
Chunk是一系列固定的内存空间,这个大小就是管理它的slab的最大存放大小。例如:slab 1的所有chunk都是104byte,而slab 4的所有chunk都是280byte。chunk是memcached实际存放缓存数据的地方,因为chunk的大小固定为slab能够存放的最大值,所以所有分配给当前slab的数据都可以被chunk存下。如果实际的数据大小小于chunk的大小,空余的空间将会被闲置,这个是为了防止内存碎片而设计的。举例来说,如果chunk size是224byte,而存储的数据只有200byte,剩下的24byte将被闲置。此外,memcached允许配置的最小的chunk空间为48个字节(key+value+flags),通过-n参数可以调节这个数值。

2. 理解这三者之间的关系

要理解memcached是如何分配内存的就要从理解上述三个东西之间的关系开始。
pagememcached在收到内存不够的请求,并进行内存分配的单位。举例来说,slab2的所有空间都用完了,又有大小适合slab2的数据过来了,那么slab2就会向memcached请求新的内存空间,memcached就会划分一个page大小的内存量到slab2。page的默认大小是1M,这个数值可以通过参数-I来修改。
slabmemcached用来划定存储空间的大小概念,每当memcached启动的时候,它会按照-n参数配置的值(如果有的话,否则为默认值)来决定第一个slab的大小,然后根据-f参数的值来决定后续slab大小的增长速率,一个一个地决定后续的slab的大小,直到slab的大小达到设定的page大小(一般是1M)。
chunk是实际用来存储数据的内存空间,它的大小和包含它的slab的大小是一致的。当page大小的内存分配到slab的时候,slab会根据自身的大小将page大小的内存分割成 page / slabsize 个chunk。

memcached启动时候,slab创建以及chunk分配的细节可以参照下面的数据(使用-vv命令查看的详细内存分配过程)。

Source code    
/usr/bin/memcached -u nobody -m 64 -p 11211 -l 127.0.0.1 -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

3. 举个例子来分析

首先,是memcached启动时候的情况:
商人A很有钱,他有100个大小一摸一样的仓库(100M的memcached服务器,每个page大小1M,就是一个仓库)。商人A根据自己的商品尺寸,将自己的仓库分成了42种(42个slab),定义为最小一种的仓库是专门用来存放尺寸为96的货物的(slab1大小为96个字节),然后每种仓库存放的货物大小都是之前一种的1.25倍(增长因子-f为1.25)。商人预先将42个仓库按照预定义的42种货物大小整理、装修了下(memcached启动时候的42个slab预分配、chunk分割)。1号仓库(slab1)中有10922个(1M * 1024 * 1024 / 96)货物存储空间(chunk),后续的仓库类型的装修、空间分配都以此类推。

其次,来看下slab满了的时候的情况:
商人A进了一批尺寸是150的货物,共6899个。货物按大小分配,进入3号仓库( slab3)。因为3号仓库是仓库类型3,其大小只有6898个位置(6898个chunk),6898个货物被安置到仓库类型3(slab3)的3号仓库里去。然后还多出来一个货物没地方放,商人就安排了一个新的仓库装修成仓库类型3(1M的空间分配给slab3,大小为152个字节,含6898个chunk),然后将多余的一个货物放入到新的仓库里。

这个例子看过以后,相信大家都已经很明白前述的三个概念之间的关系以及memcached是如何分配内存空间的了。

4. memcached里的内存浪费

读过上文之后大家应该很明白memcached的内存分配方式了。memcached这样分配内存的好处是不会存在内存碎片,但是坏处也很明显,就是内存的浪费。就拿前面的商人例子来说,如果遇到一种极端的情况,所有的货物进来的都是121个字节的大小,那么按逻辑他们都会被分到slab3里面去,也就是分到大小是152的slab里,也就是说每塞进一个对象,就会有31个字节的内存空间被浪费掉了。

5. memcached的数据回收机制

memcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期。 这种技术被称为lazy(惰性)expiration。因此,memcached不会在过期监视上耗费CPU时间。如果某一个item在memcached里过期了,这个东西并不会被删除,而是客户端无法再看见该记录(invisible,透明), 其存储空间即可重复使用。一般情况下memcached会优先使用已超时的记录的空间,但即使如此,也会发生追加新记录时空间不足的情况, 此时就要使用名为 Least Recently Used(LRU)机制来分配空间。 顾名思义,这是删除“最近最少使用”的记录的机制。 因此,当memcached的内存空间不足时(无法从slab class 获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录。

以上,主要是memcached的内存分配利用的一些经验。当然,memcached的配置、调优、监控在这篇文章里是没有涉及的,以后有机会的话会补上。

转载于:https://www.cnblogs.com/tingfengainiaini/p/5606640.html

memcache运行机制(转)相关推荐

  1. 傻傻分不清的javascript运行机制

    学习到javascript的运行机制时,有几个概念经常出现在各种文章中且容易混淆.Execution Context(执行环境或执行上下文),Context Stack (执行栈),Variable ...

  2. 从hello world 说程序运行机制

    http://www.cnblogs.com/yanlingyin/archive/2012/03/05/2379199.html 开篇 学习任何一门编程语言,都会从hello world 开始.对于 ...

  3. js 多个定时器_从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理(二)

    作者:撒网要见鱼   https://segmentfault.com/a/1190000012925872 本文接上篇 <从浏览器多进程到JS单线程,JS运行机制最全面的一次梳理(一)> ...

  4. session对象运行机制

    当你看到 "会话" 这个词的时候,你会怎么理解呢?是交流.对话的意思吗?那毫无疑问绝对是的啦,只不过那是传统意义上的,或者说是日常生活中的意思,在计算机科学领域,它的意思就要引申一 ...

  5. http和https的区别 与 SSL/TLS协议运行机制的概述

    http和https的区别 与 SSL/TLS协议运行机制的概述 参考1 1 http 是不使用的SSL/TSL的通信通道 窃听风险:第三方获取通信内容 篡改风险:修改通信内容 冒充风险:冒充他人身份 ...

  6. 第3课:SparkStreaming 透彻理解三板斧之三:解密SparkStreaming运行机制和架构进阶之Job和容错...

    本期内容: 解密Spark Streaming Job架构和运行机制 解密Spark Streaming容错架构和运行机制 理解SparkStreaming的Job的整个架构和运行机制对于精通Spar ...

  7. 浅谈SQL Server内部运行机制

    原文:浅谈SQL Server内部运行机制 对于已经很熟悉T-SQL的读者,或者对于较专业的DBA来说,逻辑的增删改查,或者较复杂的SQL语句,都是非常简单的,不存在任何挑战,不值得一提,那么,SQL ...

  8. 《Java疯狂讲义》(第3版)学习笔记 2 - Java语言的运行机制

    内容 1.高级语言的运行机制 2.Java 语言的运行机制 1.高级语言的运行机制 高级语言主要分为编译型语言和解释型语言两类. 编译型语言是指使用专门的编译器.针对特定平台(操作系统)将高级语言源代 ...

  9. WebForm页面生命周期及asp.net运行机制

    转载至:https://www.cnblogs.com/liangxiaofeng/p/5620033.html 1.先上几张原理图着重理解: 现在针对第四副图原理进行解析: 流程: 1.浏览器发送请 ...

最新文章

  1. 客快物流大数据项目(十五):DockeFile常用命令
  2. mysql error1045 yes_MySQLERROR1045(28000)错误的解决办法_MySQL
  3. 毕业设计出现的一个严重错误----文件不能相互引用
  4. 贵阳中职计算机学什么区别,贵阳中职计算机专业
  5. linux服务器无法登录,linux服务器账号密码正确无法登录-Go语言中文社区
  6. 程序人生:程序员做外包“前途“,“技术“,“经验“如何决策
  7. Start with - Connect by - level
  8. sed 去掉最后一行_shell sed命令匹配替换删除最后第一行字符正则表
  9. 南京工程学院《DSP技术及应用》期末试卷
  10. R语言笔记--par()函数详解
  11. 研报复现系列(六)【国泰君安】基于CCK模型的股票市场羊群效应研究
  12. pythonnumpy矩阵详解_基于Python Numpy的数组array和矩阵matrix详解_python
  13. 完美时空客服自助平台SQL注射漏洞
  14. Oracle安装与配置(Linux)
  15. python执行pip install 命令的时候报错 Filexxxx,line 1 pip install 的问题
  16. dgi数据治理_银行数据治理方法浅析
  17. 爱情有多美(曾贤志)
  18. 自由职业者de哪些时间
  19. HTML表格(合并单元格、边框、行高、间距等样式)
  20. 音频识别主要使用了什么技术?

热门文章

  1. 如何读取jar包外的properties文件和log4j.properties
  2. 网络学习(二十七)Windows XP 加入 Windows Server 2003 Active Directory
  3. linux下的dns设置详解
  4. paper structure for innovation management
  5. 在显示器上面看到Lo的时候应该怎么想呢?一种可能的解释
  6. U3D 动态创建Prefab的多个实例
  7. virtualbox安装centos 6之增强工具
  8. Java中ListE对象赋值问题(引用传递和值传递)
  9. Powershell统计一周内创建的账户和邮箱
  10. Bash中的whereis