Memcached是一个高效的分布式内存cache,了解memcached的内存管理机制,便于我们理解memcached,让我们可以针对我们数据特点进行调优,让其更好的为我所用。

首先需要我们先了解两个概念:Slab和chunk

Slab和chunk在Memcached的内部结构中是非常两个重要的概念,先上一张图来感性认识下:

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

虽然在同一个Slab中的chunk大小相等,但在不同的Slab中chunk的大小不一定相等。因此在Memcached中按照chunk的大小不同,把Slab分成了很多种类(class)。在启动Memcached的时候可以通过-vv来查看Slab的种类:

从上图可以看到,默认情况下memcached把slab分为40类(class1~class40):

  • 第一列数据(slab class),为slab的编号;
  • 第二列数据是chunk的大小,跟slab class是一一对应的关系,可以通俗的理解为slab就是存放一组相同大小chunk的集合,只不过这个集合是固定的(1M),
  • 第三列数据,表示每种不同slab中的page可以存放的chunk个数,实际上等于1MB/ (chunk size),例如在class 1中,chunk的大小为80字节,因此在class1中最多可以有13107个chunk:

    13107×80 + 16 = 1048576

    很显然,slab的chunk size越大,其中的每个page包含的chunk数量就越少。

在class1中,剩余的16字节因为不够一个chunk的大小(80byte),因此会被浪费掉。每类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结构体的长度,固定为32字节。default_size大小为48字节,item_size为32,因此class1的chunk大小为48+32=80字节;
  • f为factor,是chunk变化大小的因素,默认值为1.25,调节f可以影响chunk的步进大小,在启动时可以使用-f来指定;
  • CHUNK_ALIGN_BYTES是一个修正值,用来保证chunk的大小是某个值的整数倍(在32位机器上要求chunk的大小是4的整数倍)。

从上面的分析可以看到,我们实际可以调节的参数有-f、-n,在memcached的实际运行中,我们还需要观察我们的数据特征,合理的调节f,n的值,使我们的内存得到充分的利用减少浪费。


内存申请分配

Memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存,Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题。

Memcached在重复利用分配的内存时,不会主动删除过期的,而是通过两种策略来实现的:

  • Lazy Expiration:就是Memcached不会去监视服务器上的数据是否过期,而是等待get的时候检查时间戳是否过期,如果过期将不返回值,来减少Memcached在监控数据上所用到的时间。
  • Least Recently Used(LRU):Memcached 不会去释放已经使用的内存空间,但是如果分配的内存空间已经满了,当此处内存空间数据最长时间没有使用,而且使用次数很少,在存储新的数据的同时就会覆盖此处内存块。
    而LRU是针对Slab做的操作,而非全局哦。

下面解释一下memcached的内存预分配过程:

  1. 向memcached添加一个item时候,memcached首先会根据 item的大小,来选择最合适的slab class:例如item的大小为190字节,默认情况下class 4的chunk大小为160字节显然不合适,class 5的chunk大小为200字节,大于190字节,因此该item将放在class 5中(显然这里会有10字节的浪费是不可避免的)。
  2. 计算好所要放入的chunk之后,如果这个item对应的slab未出现过,则申请1个page(注意,这1M空间不论是否达到memcached使用内存都可以申请成功)并加该item存入slab中的chunk。
  3. 如果item对应的slab出现过,则在该slab中优先选择expired(free_chunks)和delete的chunk进行存储,其次将选择未使用过的chunk(free_chunks_end)进行存储。
  4. 如果item对应的slab出现过,但是对应的slab已经存储满了,那么会申请一个新的page,这个page被分为对应大小的chunk,继续存储。例如我们第一次向memcached中放入一个190字节的item 时,memcached会产生一个slab class 5(也叫一个page),并会用去一个chunk,剩余5241个chunk供下次有适合大小item时使用,当我们用完这所有的5242个chunk之后,下次再有一个在160~200字节之间的item添加进来时,memcached会再次产生一个class 5的slab(这样就存在了2个pages)。
  5. 如果item对应的slab出现过,但是对应的slab已经存储满了并且memcache也达到了最大内存使用。将使用lru算法,清除item(可能将未过期的item清除)此时会有eviction++。

Page其实就是分配给Slab的内存空间,默认是1MB,Slab是逻辑概念。

Memcached 内存管理详解的更多相关文章

  1. Apache Spark 内存管理详解(转载)

    Spark 作为一个基于内存的分布式计算引擎,其内存管理模块在整个系统中扮演着非常重要的角色.理解 Spark 内存管理的基本原理,有助于更好地开发 Spark 应用程序和进行性能调优.本文旨在梳理出 ...

  2. 动态内存管理详解:malloc/free/new/delete/brk/mmap

    c++ 内存获取和释放 new/delete,new[]/delete[] c 内存获取和释放 malloc/free, calloc/realloc 上述8个函数/操作符是c/c++语言里常用来做动 ...

  3. spark内存管理详解

    Spark 作为一个基于内存的分布式计算引擎,其内存管理模块在整个系统中扮演着非常重要的角色.理解 Spark 内存管理的基本原理,有助于更好地开发 Spark 应用程序和进行性能调优.本文旨在梳理出 ...

  4. MemCache中的内存管理详解

    MC的内存管理机制 1.内存的碎片化 当我们使用C语言或者其他语言进行malloc(申请内存),free(释放内存)等类似的命令操作内存的时候, 在不断的申请和释放的过程中,形成了一些很小的内存片段, ...

  5. 转:C/C++内存管理详解 堆 栈

    http://chenqx.github.io/2014/09/25/Cpp-Memory-Management/ 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了 ...

  6. QF——OC内存管理详解

    堆的内存管理: 我们所说的内存管理,其实就是堆的内存管理.因为栈的内存会自动回收,堆的内存需要我们手动回收. 栈中一般存储的是基本数据类型变量和指向对象的指针(对象的引用),而真实的对象存储在堆中.因 ...

  7. Swift 内存管理详解

    Swift内存管理: Swift 和 OC 用的都是ARC的内存管理机制,它们通过 ARC 可以很好的管理对象的回收,大部分的时候,程序猿无需关心 Swift 对象的回收. 注意: 只有引用类型变量所 ...

  8. IOS内存管理详解

    一.    基本原理 1.        什么是内存管理 移动设备的内存极其有限,每个app所能占用的内存是有限制的 当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空 ...

  9. Apache Spark 内存管理详解

    在spark里面,内存管理有两块组成,一部分是JVM的堆内内存(on-heap memory),这部分内存是通过spark dirver参数executor-memory以及spark.executo ...

随机推荐

  1. 一个简单版的波纹css3动画

    ul{width: 300px;border: red;}ul li{width: 300px;height: 70px;line-height: 70px;background: #fff;text ...

  2. 安装 mrtg

    http://blog.csdn.net/cnbird2008/article/details/2072627

  3. 建立、配置和使用Activity——Activity

    Activity是Android应用中最重要.最常见的应用组件(此处的组件是粗粒度的系统组成部分,并非指界面控件:widget).Android应用的一个重要组成部分就是开发Activity,下 面将 ...

  4. 验证浏览器是否安装已flash插件的js脚本

    function flashChecker() { var hasFlash = 0; //是否安装了flash var flashVersion = 0; //flash版本 if(document ...

  5. because of many connection errors; unblock with 'mysqladmin flush-hosts

    环境:linux,mysql5.5.37 错误:Host is blocked because of many connection errors; unblock with 'mysqladmin ...

  6. 不使用模板导出Excel(C#版本)

    不多说,直接上干货! using System; using System.Collections.Generic; using System.Linq; using System.Web; usin ...

  7. linux系统下find删除目录下除一文件外的所有文件

    /data/目录下有a.txt b.txt c.txt d.txt删除/data/目录下所有文件,保留b.txt两种方法:1.[root@xuegod62 ~]# find /data/ -type ...

  8. win10环境下python3.5安装步骤

    点我去Python官网下载 往下翻几页就能看到各种版本的Python,当前最新的是Python3.6,也没多大区别,我选择的是3.5.2 64位的,点击download 根据自己的电脑配置,我选择的是 ...

  9. [html5] 学习笔记-html5增强的页面元素

    在 HTML5 中,不仅增加了很多表单中的元素,同时也增加和改良了可以应用在整个页面中的元素.重点包含 figure.figcaption.details.summary.mark.progress. ...

  10. Vue.js 系列教程 ①

    原文:intro-to-vue-1-rendering-directives-events 译者:nzbin 如果要我用一句话描述使用 Vue 的经历,我可能会说“它如此合乎常理”或者“它提供给我需要 ...