https://www.cnblogs.com/xrq730/p/4948707.html
MemCache是什么
理解memcached的内存存储机制
Slab Allocator内存分配机制Memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存。0. 之前内存分配的弊端在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的。但是,这种方式会导致内存碎片,加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢。Slab Allocator就是为解决该问题而诞生的。Slab Allocator的基本原理是按照预先规定的大小,将分配的内存以page为单位,默认情况下一个page是1M,可以通过-I参数在启动时指定,分割成各种尺寸的块(chunk), 并把尺寸相同的块分成组(chunk的集合),如果需要申请内存时,memcached会划分出一个新的page并分配给需要的slab区域。page一旦被分配在重启前不会被回收或者重新分配,以解决内存碎片问题。
Page
分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk。Chunk用于缓存记录的内存空间。 是memcached实际存放缓存数据的地方,这个大小就是管理它的slab的最大存放大 小。每个slab中的chunk大小是一样的,如上图所示slab1的chunk大小是88字节,slab2是112字节。由于分配的是特定长度的内存,因此无法有效利用分配的内存。Slab Class slab是linux操作系统的一种内存分配机制相同大小的chunk组成的组。Memcached并不是将所有大小的数据都放在一起的,而是预先将数据空间划分为一系列slabs,每个slab只负责一定范围内的数据存储。memcached根据收到的数据的大小,选择最适合数据大小的slab。memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中。如图所示,每个slab只存储大于其上一个slab的size并小于或者等于自己最大size的数据。例如:100字节大小的字符串会被存到slab2(88-112)中,每个slab负责的空间是不等的,memcached默认情况下下一个slab的最大值为前一个的1.25倍,这个可以通过修改-f参数来修改增长比例。 slab的内存分配具体过程如下:Memcached在启动时通过-m参数指定最大使用内存,但是这个不会一启动就占用完,而是逐步分配给各slab的。 如果一个新的数据要被存放:首先选择一个合适的slab,然后查看该slab是否还有空闲的chunk,如果有则直接存放进去;如果没有则要进行申请,slab申请内存时以page为单位,无论大小为多少,都会有1M大小的page被分配给该slab(该page不会被回收或者重新分配,永远都属于该slab)。申请到page后,slab会将这个page的内存按chunk的大小进行切分,这样就变成了一个chunk的数组,再从这个chunk数组中选择一个用于存储数据。若没有空闲的page的时候,则会对该slab进行LRU,而不是对整个memcache进行LRU。
1、slab class:在memcached中,对元素的管理是以slab为单元进行管理的。每个slab class对应一个或多个空间大小相同的chunk。
2、chunk:存放元素的最小单元。用户数据item(key、value等)最终会保存在chunk中。memcached会根据元素大小将其放到合适的slab class中。每一个slab class中的chunk空间大小是一样的,所以元素存放进来后,chunk可能会有部分空间剩余。 3、page:大小固定为1MB。当slab class空间不足时,就会申请page,并将page按chunk的大小进行切割。 MemCache是一个自由、源码开放、高性能、分布式的分布式内存对象缓存系统,用于动态Web应用以减轻数据库的负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高了网站访问的速度。MemCaChe与Redis相比在使用简单的key-value存储时memcached的内存利用率更高;而Redis在使用哈希结构来做key-value存储时,采用组合式压缩,内存利用率高于Memcache缓存:将要调用的对象存在内存中,使用时可以快速调用,不必再去创建新的重复的实例。可以减少系统开销,提高系统效率。MemCache被称为"分布式缓存",但是不具备分布式的功能,因此只能在客户端通过像一致性哈希这样的分布式算法来实现MemCache分布式缓存。MemCache实现原理
MemCache的数据存放在内存中,存放在内存中个人认为意味着几点:1、访问数据的速度比传统的关系型数据库要快,因为Oracle、MySQL这些传统的关系型数据库为了保持数据的持久性,数据存放在硬盘中,IO操作速度慢2、MemCache的数据存放在内存中同时意味着只要MemCache重启了,数据就会消失3、既然MemCache的数据存放在内存中,那么会受到机器位数的限制,32位机器最多只能使用2GB的内存空间,64位机器没有上限MemCache的原理,MemCache最重要的莫不是内存分配的内容了,MemCache采用的内存分配方式是固定空间分配,还是自己画一张图说明:这张图片里面涉及了slab_class、slab、page、chunk四个概念,
Slab Class 相同大小的chunk组成的组。Slab 是linux操作系统的一种内存分配机制Page分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk。Chunk用于缓存记录的内存空间。 它们之间的关系是:1、MemCache将内存空间分为一组slab2、每个slab下又有若干个page,每个page默认是1M,如果一个slab占用100M内存的话,那么这个slab下应该有100个page3、每个page里面包含一组chunk,chunk是真正存放数据的地方,同一个slab里面的chunk的大小是固定的4、有相同大小chunk的slab被组织在一起,称为slab_classMemCache内存分配的方式称为allocator,slab的数量是有限的,几个、十几个或者几十个,这个和启动参数的配置相关。MemCache中的value过来存放的地方是由value的大小决定的,value总是会被存放到与chunk大小最接近的一个slab中,比如slab[1]的chunk大小为80字节、slab[2]的chunk大小为100字节、slab[3]的chunk大小为128字节(相邻slab内的chunk基本以1.25为比例进行增长,MemCache启动时可以用-f指定这个比例),那么过来一个88字节的value,这个value将被放到2号slab中。放slab的时候,首先slab要申请内存,申请内存是以page为单位的,所以在放入第一个数据的时候,无论大小为多少,都会有1M大小的page被分配给该slab。申请到page后,slab会将这个page的内存按chunk的大小进行切分,这样就变成了一个chunk数组,最后从这个chunk数组中选择一个用于存储数据。如果这个slab中没有chunk可以分配了怎么办,如果MemCache启动没有追加-M(禁止LRU,这种情况下内存不够会报Out Of Memory错误),那么MemCache会把这个slab中最近最少使用的chunk中的数据清理掉,然后放上最新的数据。针对MemCache的内存分配及回收算法,总结三点:1、MemCache的内存分配chunk里面会有内存浪费,88字节的value分配在128字节(紧接着大的用)的chunk中,就损失了30字节,但是这也避免了管理内存碎片的问题2、MemCache的LRU算法不是针对全局的,是针对slab的3、应该可以理解为什么MemCache存放的value大小是限制的,因为一个新数据过来,slab会先以page为单位申请一块内存,申请的内存最多就只有1M,所以value大小自然不能大于1M了再总结MemCache的特性和限制上面已经对于MemCache做了一个比较详细的解读,这里再次总结MemCache的限制和特性:1、MemCache中可以保存的item数据量是没有限制的,只要内存足够2、MemCache单进程在32位机中最大使用内存为2G,这个之前的文章提了多次了,64位机则没有限制3、Key最大为250个字节,超过该长度无法存储4、单个item最大数据是1MB,超过1MB的数据不予存储5、MemCache服务端是不安全的,比如已知某个MemCache节点,可以直接telnet过去,并通过flush_all让已经存在的键值对立即失效6、不能够遍历MemCache中所有的item,因为这个操作的速度相对缓慢且会阻塞其他的操作7、MemCache的高性能源自于两阶段哈希结构:第一阶段在客户端,通过Hash算法根据Key值算出一个节点;第二阶段在服务端,通过一个内部的Hash算法,查找真正的item并返回给客户端。从实现的角度看,MemCache是一个非阻塞的、基于事件的服务器程序8、MemCache设置添加某一个Key值的时候,传入expiry为0表示这个Key值永久有效,这个Key值也会在30天之后失效,
posted on 2019-06-01 14:39 阅读( ...) 评论( ...)