zoukankan      html  css  js  c++  java
  • memcached内存管理机制[未整理]

    memcached默认采用的是Slab Allocator的机制分配管理内存的,在此之前,内存的分配是通过对所有的记录简单地进行malloc和free来进行的,但这种方式容易造成很多内存碎片,加重操作系统内存管理的负担。

    内存碎片化

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

    slab allocator机制

    slab allocator的原理是将分配的内存分隔成各种尺寸的块,并把尺寸相同的块分成组,所分配的这些内存不会释放,而是重复利用.

    针对客户端发送的数据,memcached会根据收到数据的大小,选择最适合数据大小的slab。memcached中保存着slab内空闲块的列表,根据该列表选择块,然后将数据组上于其中

    slab allocator缺点

    该机制来带来了一定的问题,就是由于分配的是特定长度的内存,因此无法有效利用分配的内存,如,将100字节的数据缓存到128字节的块中,而剩余的28字节就浪费了

    使用growth factor进行调优

    memcached启动时可以指定growth factor因子,通过-f选项,就可以在某种程度上控制slab之间的差异,默认为1.25。可由./memcached -f 2 -vv查看内存分配情况

    查看memcached内部状态

    memcached有个stats的命令,它可以获得各种各样的信息,如:

    $telnet localhost 11211
    Trying ::1...
    Connected to localhost.
    Escape character is '^]'.
    stats
    STAT pid 4422
    STAT uptime 85586
    STAT time 1459390330
    STAT version 1.4.25
    STAT libevent 2.0.22-stable
    STAT pointer_size 64
    STAT rusage_user 0.329239
    STAT rusage_system 0.546175
    STAT curr_connections 10
    ....

    通过stats slabsstats items还可以获得关于缓存记录的信息。

    memcached的删除数据机制

    数据不会从memcached中消失,不会释放已分配的内存,记录超时后,客户端就无法再看到该记录,其存储空间是可以再次利用

    lazy expiration

    memcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期,这种技术被称之为lazy expiration,因此memcached不会在过期监视上耗费CPU时间

    LRU

    memcached会优先使用已超时的记录空间,但有时候也会发生空间不足的情况,这时间就会使用LRU机制来分配空间,就是说删除最近最少使用的记录来存放新的记录。

    但可通过./memcached -M命令中的-M参数来禁止使用LRU机制,如果内存用尽时就会返回错误。

    Memcached利用Slab Allocator机制管理内存。

    原理

    预先把内存划分成数个大小1M的slab class仓库;
    再把每个仓库切分成不同尺寸的小块(chunk);
    需要存内容时,判断内容的大小,为其选取合理的仓库。

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

    注意:如果有 100byte 的数据,但122byte大小的仓库中的chunk满了;
    此时会把122byte仓库的旧数据剔除掉,然后存储[Memcachedd的删除机制]。
    固定大小chunk的内存浪费

    Slab Allocator存在的问题
    由于分配的是特定长度的内存,因此无法有效利用分配的内存。
    例如: 将100byte数据存入128byte的chunk,则浪费了28byte。

    因为不能自定义chunk的大小,所以无法彻底解决chunk空间浪费问题。
    问题缓解: 如果预先知道客户端发送的数据的公用的大小,或者仅缓存大小相同的数据的情况下。只要使用适合数据大小的组的列表,就可以减少浪费。

    即: 通过缓存中item长度进行统计,通过参数调整slab class大小的增长速度,即增长因子(growth factor),从而制定合理的chunk大小。

    Slab Allocator术语
    • page – 分配给slab的内存空间,默认是1MB,分配给slab之后跟据slab大小切分成chunk
    • chunk – 用于缓存数据的内存空间
    • slab class – 特定大小的chunk组
    Growth Factor调优

    启动时指定growth factor因子,就可以在某种程度上控制slab之间的差异,默认值为1.25。
    Memcached –f 2 –vv
    (查看growth factor为2时slab中chunk size的差异)
    Memcached引入时,最好重新计算一下数据的预期平均长度,调整growth factor,以获得最恰当的设置。

    数据删除[过期数据惰性删除]

    1、Memcached不会释放已分配的内存,其存储空间可以重复使用。
    2、Lazy Expiration
    Memcached内部不会监视数据是否过期,而是在get时查看数据的时间戳,查看数据是否过期。被称为lazy expiration(惰性过期)。
    3、当Memcached内存空间不足,即无法从slab class中获取到新的空间时,就从最近未被使用的数据中搜索,将其空间分配给新的数据。(如果要禁用LRU,使用-M参数,超出会报错)。
    4、不指定具体值则默认数值为64M。

    lazy expiration好处: 
    节省CPU时间和检测成本

    LRU删除机制

    如果以 128byte的chunk举例, 128byte的chunk都满了, 又有新的值(长度为 120)要加入, 要剔除掉哪个数据?

    操作系统的内存管理,常用 FIFO,LRU 删除

    • LRU: Least Recently Used 最近最少使用
    • FIFO: First In ,First Out 先进先出

    memcached 使用LRU删除机制
    原理: 当某个单元被请求时,维护一个计数器,通过计数器来判断最近谁最少被使用. 就把谁剔除。

    注: 即使某个 key 是设置的永久有效期,也一样会被踢出来!
    --即永久数据被踢现象

    参数限制

    • key 的长度: 250 字节, (二进制协议支持 65536 个字节)
    • value 的限制: 1m, 一般都是存储一些文本,如新闻列表等等,这个值足够了. 内存的限制: 32 位下最大设置到 2g.

    如果有 30G数据要缓存,一般也不会单实例装 30G, (不要把鸡蛋装在一个篮子里),,可以开启多个实例(在不同的机器,或同台机器上的不同端口)

  • 相关阅读:
    iOS开发-Sqlite
    iOS开发-HTTP协议
    iOS开发
    iOS 开发小记 (八)
    iOS
    iOS开发-基础框架
    Java门面模式
    Linux常用命令
    canal使用小结
    MySQL隔离级别的测试
  • 原文地址:https://www.cnblogs.com/wajika/p/6611028.html
Copyright © 2011-2022 走看看