暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Memcached内存分配机制及分布式算法分析

bestpaydata 2021-04-18
965

Memcached是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。Memcacheddanga.com的一个项目,最早是为 LiveJournal 服务的,最初为了加速 LiveJournal 访问速度而开发的,后来被很多大型的网站采用。目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力。

Memcached存取的对象都是以key-value的形式存储在服务器端内存中,全内存数据保存,每个被存取的对象都有一个唯一的标志key


                             1

内存分布式算法(Slab Allocator):

memcached的内存分配默认是采用了Slab Allocator的机制分配、管理内,在该机制出现以前,内存的分配是通过对所有记录简单地进行mallocfree来进行的。 但是,这种方式会导致内存碎片,加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢,Slab Allocator就是为解决该问题而诞生的。


                                      
2


                 3

SlabAllocation的名词解释:

Page:分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk
Chunk
实际使用的内存空间大小。
Slab Class
:特定大小的chunk组。

Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题。如图2Slab Allocation原理相当简单,将分配的内存分割成各种尺寸的块(chunk), 并把尺寸相同的块分成组(chunk的集合)。


                 4

 

如图3Memcached根据应用端数据大小选择最合适的slab,应用端需要180 bytes字节的内存,会选择192 bytes slab。如图4Memcached中存储着空闲chunk列表,并根据该列表选择chunk,应用端需要180 bytes 的内存,却选择了192 bytesslab class,这样做的后果是chunk中剩余的12 bytes内存会被浪费掉。对于内存被闲置的处理,如果预先知道客户端发送的数据的使用内存的大小,或者仅缓存大小相同的数据的情况下,只要使用适合数据大小的组的列表,就可以减少浪费。但是想要做到预知客户端发送数据的内存大小比较困难,只能期待以后的版本来解决上述问题了,但是,我们可以根据业务需要来调节slab class的大小,进而减少这种内存闲置造成的内存浪费。

使用GrowthFactor进行内存调优:

Memcached在启动时指定 Growth Factor因子(通过-f选项), 可以控制slab的大小,进而让应用在选择使用slab时,不致更多内存浪费。默认值为1.25 但是,在该选项出现之前,这个因子曾经固定为2,称为“powers of2”策略。让我们用以前的设置,以verbose模式启动Memcached


$ memcached  -f 2  -vv

下面是启动后的verbose输出:

slab class   1: chunk size    128 perslab 8192

slab class  2: chunk size    256 perslab  4096

slab class  3: chunk size    512 perslab  2048

slab class  4: chunk size   1024 perslab  1024

slab class  5: chunk size   2048 perslab   512

slab class  6: chunk size   4096 perslab   256

slab class  7: chunk size   8192 perslab   128

slab class  8: chunk size  16384 perslab    64

slab class  9: chunk size  32768 perslab    32

slab class 10: chunk size  65536 perslab    16

slab class 11: chunk size 131072 perslab     8

slab class 12: chunk size 262144 perslab    4

slab class 13: chunk size 524288 perslab    2

 由上述例子可以看出,从slabclass 1开始,组的内存大小依次增大为原来的2倍。 这样设置导致的问题就是slab之间的差别比较大,有些情况下就会造成内存的浪费。 因此,memcache新版本为尽量减少内存浪费,追加了growth factor这个参数。

来看看现在的默认设置(f=1.25)时的输出:

slab class  1: chunk size     88 perslab 11915

slab class  2: chunk size    112 perslab  9362

slab class  3: chunk size    144 perslab  7281

slab class  4: chunk size    184 perslab  5698

slab class  5: chunk size    232 perslab  4519

slab class  6: chunk size    296 perslab  3542

slab class  7: chunk size    376 perslab  2788

slab class  8: chunk size    472 perslab  2221

slab class  9: chunk size    592 perslab  1771

slab class 10: chunk size    744 perslab  1409

可见,组间差距比因子为2时小得多,更适合缓存几百字节的记录。 从上面的输出结果来看,可能会觉得有些计算误差,这些误差是为了保持字节数的对齐而故意设置的。

Memcached引入产品,或是直接使用默认值进行部署时,最好是重新计算一下数据的预期平均长度,调整growth factor 以获得最恰当的设置。

Memcached数据过期方式:

Memcached数据过期方式为Lazy Expiration Memcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期,这种技术称为lazy expiration。因此,Memcached不会在过期监视上耗费CPU时间。Memcache的默认最大数据过期时间是30天。

     Memcached会优先使用已超时的记录的空间,但即使如此,也会发生追加新记录时空间不足的情况,此时就要使用名为 Least Recently UsedLRU)机制来分配空间。顾名思义,这是删除“最近最少使用”的记录的机制。因此,当Memcached的内存空间不足时(无法从slab class 获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录。

Memcached分布式算法


        图5

选择服务器算法有两种,一种是根据余数来计算分布,另一种是根据散列算法来计算分布。
余数算法:
   
先求得键的整数散列值,再除以服务器台数,根据余数确定存取服务器,这种方法计算简单,高效,但在memcached服务器增加或减少时,几乎所有的缓存都会失效。
散列算法:
     
如图5,先算出memcached服务器的散列值,并将其分布到0232次方的圆上,然后用同样的方法算出存储数据的键的散列值并映射至圆上,最后从数据映射到的位置开始顺时针查找,将数据保存到查找到的第一个服务器上,如果超过232次方,依然找不到服务器,就将数据保存到第一台memcached服务器上。如果添加了一台memcached服务器,只在圆上增加服务器的逆时针方向的第一台服务器上的键会受到影响。



                       


文章转载自bestpaydata,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论