Memcache的内存管理机制

本文深入解析Memcached缓存服务的预热理念、内存管理机制、删除机制及分布式集群实现。阐述了SlabAllocator如何优化内存分配,避免碎片化,以及LRU算法在缓存管理中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.Memcached预热理念及集群节点正确重启方法
Memcached预热理念
当需要大面积重启Memcached时,首先要在前端控制网站入口的访问流量,然后,重启Memcached集群并进行数据预热,所有数据都预热完毕之后,在逐步放开前端网站入口的流量。
为了满足Memcached服务数据可以持久化存储的需求,较早期Sina网基于memcached服务开发了一款NoSQL软件,名字MemcacheDB,实现了在缓存的基础上增加了持久存储的特性,不过目前逐步被更
优秀的redis软件取代了

  如何正确开启网站集群服务器?
  如果由于机房断电或者搬迁服务器集群到新机房,那么启动集群服务器时,一定要从网站集群的后端依次往前端开启,特别时开启Memcached缓存服务器后要提前预热
   一般重启memcache的时候,自动指向一个程序  往memcache中写预热数据

2.Memcached内存管理
Malloc内存管理机制
在讲解Memcached内存管理机制前,先了解下malloc
malloc的全称时memory allocation,中文名称动态内存分配,当无法知道内存具体位置的时候,想要绑定真正的内存空间,就需要用到动态分配内存。
早期的Memcached内存管理方式时通过malloc分配的内存,使用完后通过free来收回内存。这种方式容易产生内存碎片并降低操作系统对内存的管理效率。加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢,为了解决上述问题,Slab Allocator内存分配机制就诞生了
Slab内存管理机制
现在的Memcached是利用Slab Allocation机制来分配和管理内存的。
1)提前将大内存分配大小为1MB的若干个slab,然后针对每个slab再进行小对象填充chunk,避免大量重复的初始化和清理,减轻了内存管理器的负担
Slab Allocation内存分配机制原理是按照预先规定的大小,将分配给Memcached服务的内存预先分割成特定长度的内存块(chunk),再把尺寸相同的内存块(chunk)分成组(chunks slab class),这些内存不会释放,可以重复利用。
在这里插入图片描述
2)新增数据对象存储说明
Memcached服务器中保存着slab内空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中。当有数据存入时,Memcached根据接收到的数据大小,选择最适合数据大小的slab分配一个能存下这个数据的最小内存块(chunk)。例如:有100字节的要给数据,就会被分配存入下面112字节的一个内存块中,这样会有12字节被浪费掉,这部分空间不能被使用了,这也是Slab Allocator机制的一个缺点。
在这里插入图片描述
Slab Allocator还可重复使用已分配的内存。即分配到的内存不释放,而是重复利用

Slab Allocation的主要术语
在这里插入图片描述
SLAB内存管理机制特点:
1.1 提前分配大内存slab 1MB,再进行小对象填充chunk
1.2 避免大量重复的初始化和清理,减轻内存管理器负担
1.3 避免频繁malloc/free 内存分配导致的碎片

3 MC内存管理机制小结:
1.1 Mc的早期内存管理机制为malloc(动态内存分配)
1.2 malloc(动态内存分配)产生内存碎片,导致操作系统性能急剧下降
1.3 slab内存分配机制就产生了,可以解决内存碎片的问题
1.4 Memcached服务的内存预先分割成特定长度的内存块,称为Chunk,用于缓存数据的内存空间或内存块,相当于磁盘的block,只不过磁盘的每一个block都是相等的,而chunk只有同一个Slab Class内才时相等的
1.5 Slab Class : 特定大小(1M)的包含多个chunk的集合或组,一个Memcached包含多个Slab Class,每个Slab Class包含多个相同大小的chunk
1.6 Slab机制也有缺点,例如,Chunk的空间会浪费(通过调优因子以及大小接近的数据放入一个MC实例)。

  1. Memcached Slab Allocator内存管理机制缺点
    chunk存储Item浪费空间
    SlabAllocator解决了当初的内存碎片问题,但新的机制也给memcached带来了新的问题。这个问题就是,由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了
    在这里插入图片描述
    避免浪费内存的办法是,预先计算出应用存入的数据大小,或把同一业务类型的数据存入一个Memcached服务器中,确保存入的数据大小相对均匀,这样就可以减少内存的浪费。
    还有一种办法是,在启动时指定"-f"参数,能在某种程度上控制内存组之间的大小差异。在应用中使用Memcached时,通常可以不重新设置这个参数,使用默认值1.25进行部署。如果想优化Memcached对内存的使用,可以考虑重新计算数据预期平均长度,调整这个参数来获得合适的设置值。
    -f chunk size growth factor(default:1.25)
    slab尾部剩余空间
    如classid=40中,两个chunk占用了1009384byte,就有1048576-1009384=39192byte被浪费
    解决办法:规划slab大小=chunk大小*n整数倍

      slab/chunk  = 接近整数
    
  2. 使用Growth Factor对Slab Allocator内存管理机制调优
    在启动memcached时指定Growth Factor因子(通过-f选项).就可以在某种程度上控制每组slab之间的差异。默认值1.25. 但是,在该选项出现之前,这个因子曾经固定为2,称为"powers of 2"策略。让我们用以前的设置,以verbose模式启动memcached试试看:
    memcached -f 2 -vv
    下面是启动后的verbose输出:
    在这里插入图片描述
    v越多输出的信息越多

       memcached  -f   2   -vvvv   -u   root
       基本上通过-n 和 -f来调整chunk大小
       memcached  -f  1.01  -vvv  -u  root   -n   128
       这个基本上就是memcache的优化
       ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190606142923573.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NhbmdxaW9uZ194aWFtZW4=,size_16,color_FFFFFF,t_70)
       6. Memcached删除机制总结
    

    6.1 不主动检测item对象是否过期,而是在get时才会检查item对象是否过期以及是否应该删除
    6.2 当删除item对象时,一般不释放内存空间,而是作标记删除,将指针放入slot回收插槽,下次分配的时候直接使用
    6.3 当内存空间满的时候,才会根据LRU算法把最近最少使用的item对象删除
    6.4 数据存入可以设定过期时间,但是数据过期后不会被立即删除,而是在get时才会检查item对象是否过期应该删除
    6.5 如果不希望系统使用LRU算法清除数据,可以使用-M参数

    总之一句话: 要删除的数据 不立马删除 而是做个标记 插入数据的时候直接替换

7.Memcached的检查过期与删除机制
Memcached懒惰检测对象过期机制
1)不主动检测item对象是否过期,而是在get时才会检查item对象是否过期应该删除!
Mc不会主动检查item对象是否过期,也不会释放已分配给对象的内存空间,除非为添加的数据设定过期时间或内存缓存满了,在数据过期后,客户端不能通过key取出它的值,其存储空间将被重新利用。
Memcached使用的是惰性检测过期策略,自己不会监控存入的key/value对是否过期,而是在获取key值时查看记录的时间戳(sed key flag exptime bytes),检查key/value对空间是否过期。这种策略不会在过期检测上浪费CPU资源。
Memcached惰性删除对象机制
当删除item对象时,一般不释放内存空间,而是作为标记删除,将指针放入slot回收插槽,下次分配的时候直接使用。
Memcached在分配空间时,会优先使用已经过期的key/value对空间,当分配的内存空间占满时,Memcahced就会使用LRU算法来分配空间,删除最近最少使用的key/value对,将其空间分配给新的key/value对。在某些情况下(完整缓存),如果不想使用LRU算法,那么可以通过"-M"参数来启动Memcached,这样,Memcached在内存耗尽时,会返回一个报错信息。
-M return error on memory exhausted(rather than removing items)

  1. Memcached服务在不同企业业务应用场景中的工作流程
    a.当web程序需要访问后端数据库获取数据时会优先访问Memcached内存缓存,如果缓存中有数据就直接获取返回前端服务及用户,如果没有数据(没有命中),在由程序请求后端的数据服务器,获取到对应的数据后,除了返回给前端服务及用户数据外,还会把数据放到Memcached内存中进行缓存,等待下次请求被访问,Memcached内存始终是数据库的挡箭牌,从而大大的减轻数据库的访问能力,提高整个网站架构的响应速度,提升了用户体验。
    b.当程序更新,修改或删除数据库中已有数据时,会同时发送请求通知Memcached已经缓存过的同一个ID内存的旧数据失效,从而保证Memcache中的数据或数据库中的数据一致。
    如果是在高并发场合,除了通知Memcached过期的缓存失效外,还会通知相关机制,使得在用户访问新数据前,通过程序预先把更新过的数据推送到memcached中缓存起来,这样可以减少数据库的访问压力,提升memcached中缓存的命中率
    c.有一款数据库插件可以再写入更新数据库后,自动抛给MC缓存起来,自身不CACHE,类似inotity

9.Memcached服务分布式集群如何实现?
特殊说明:memcached集群和web服务集群式不一样的,所有memcached的数据总和才是数据库的数据,每台memcached都是部分数据
a 程序端实现
程序加载所有mc的列表,通过对key做hash(一致性哈希)。
b 负载均衡器
通过对key做hash(一致性哈希)

说明:一致性哈希算法的目的是不但保证每个对象只请求一个对应的服务器,而且当节点宕机缓存服务器的更新分配比例降到最低

10.Memcached服务特点及原理是什么?
解答:
a. C/S模式架构,C语言2000多行
b. 异步I/O,使用libevent作为事件通知机制
c. 被缓存的数据以key/value键值形式存在的
d. 全部数据存放于内存中,无持久性存储的设计,重启数据丢失
e. 当内存中缓存的数据容量达到启动时设定的内存值,就自动使用LRU算法删除过期的缓存数据。
f. 可以对存储的数据设置过期时间,这样过期后数据自动被清除,服务本身不会监控过期,而是在访问的时候查看key的时间戳判断是否过期
g. memcache会对设定的内存进程分块,再把块分组,然后再提高服务

11.简述Memcache服务内存管理机制原理?
解答:
memcached的内存分配器是如何工作的?为什么不使用malloc/free?为何要使用slabs?
实际上,这是一个编译时选项。默认会使用内部的slab分配器。您确实应该使用内建的slab分配器。最早的时候,memcached只使用malloc/free来管理内存。然而,这种方式反复地malloc/free造成了内存碎片,OS最终花费大量的时间去查找连续的内存块来满足malloc的请求,而不是运行memcached进程
slab分配器就是为了解决这个问题而生的。内存被分配并划分称chunks,一直被重复使用。因为内存被划分称大小不等的slabs,如果item的大小与被选择存放它的slab不是很合适的话,就会浪费一些内存。Steven Grimm正在这方面已经做出了有效的改进。
邮件列表中有一些关于slab的改进(power of n 还是 power of 2)和权衡方案

12.Memcached的删除原理与cache机制?
Memcached主要的cache机制是LRU(最近最少用)算法+超时失效。当您存数据到memcached中,可以指定该数据在缓存中可以呆多久.如果memcached的内存不够用了,过期的slabs会优先被替换,接着就轮到最老的未被使用的slabs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值