`
zhengjunwei2007_163.com
  • 浏览: 126342 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Memcached之内存利用率提升经验分享 转载

    博客分类:
  • JAVA
阅读更多

 

在使用Memcached的时候,大部分人可能很少关注内存利用率,因为Cache毕竟是Cache,那么对于存储数据的可靠性要求就不高,丢了也不心疼,总之能够从DBReload回来即可,话是不错!但是在我们的项目中,却遇到了一个棘手的问题,就是希望数据能够被Memcached 100%Cache起来,那么如何让容量规划做到位呢,加多大内存才是合理的,问题就随之而来了!在我们的测试过程中,想要放入20G的数据(5000万)到开了25GMemcached中,本想是没有问题的,结果才放到45%的容量的时候,数据就发生了“Evict”的现象,后续再继续追加数据,直到全部加完,Memcached的利用率始终维持在50%左右,丢了40%左右的数据,难道说需要开个50GMemcached才能搞定20G的数据存储?这个也是不确定的,资源浪费太严重了,所以我们就开始着手分析原因了,目的就为两点:

① 100%将数据Cache起来

提高Memcached的内存利用率,节省不必要的成本,将利用率稳定在一定合理值,这样便于将来我们预警容量问题,也能做好容量规划

1、 首先:我们需要了解Memcached的内存分配机制:

Memcached采用了Slab Allocation机制,这种机制的好处是预先分配好内存,无需在使用时MallocFree,解决了内存碎片问题,分配好的内存也可以重复使用,所以可以减轻内存管理的负担。

分配过程:先初始化若干个Slab,为每个Slab分配一个Page的内存空间,Page缺省为1MB,每个Page根据Slab规格被划分为若干个相同SizeChunk,每个Chunk里保存一个Item,每个Item同时包含了Item结构体、kV,相同SizeChunk合成一组Slab Class,如图例:

 

我们可以使用Growth Factord对分配策略进行调优,默认值是1.25Growth Factor的值不同,分配的ChunkSize就不同,且不同Slab Class中的Chunk数量也会不同,根据需要调整才是。

n 缺省值F=1.25的情况下,Slab分配情况如下:

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

n F2的情况下,Slab分配情况如下:

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

2、 其次,了解数据存储的原理:

Memcached在收到需要存储的数据后,先计算数据的Size,最大存入1M的数据,然后选择适合的Slab Class中的Chunk(当然Memcached会记录哪些Chunk是空闲的),,如图例:

 

在数据存入选中的Slab Class,可能有以下两种情况:

n 若该Slab Class未满(free_chunks > 0),则成功存入;

n 若该Slab Class满了(free_chunks0),有可能发生以下两种情况:

l 有可用内存,则新增一个Page的内存给该Slab,该Page也是被当前Slab的同样规格进行划分若干Chunk,然后将数据存入新增的Chunk中;

l 无可用内存,有可能发生以下两种情况:

u 启用LRULRUScope只是针对Slab的,而非全局),将新数据替换老数据,老数据丢失

u 禁用LRU(追加Memcached的启动参数-M),发生Out Of Memory错误

由于分配的都是定长Chunk,在内存利用率上也有天然的缺陷,如图例:

 

n 不仅仅存在单个Chunk上浪费现象

n 而且会存在整个Slab Class浪费的现象,因为有时遇到的数据Size根本落不到这个Slab Class上都是可能的

总之,Memcached可谓用心良苦,用空间换取性能,当然应用在使用时需要注意到这点特性,才能用好Memcached

3、 最后,就必须要对自己应用的数据Size分布做个透彻的分析,才能将Memcached物尽其用:

根据经验所得:

n 数据Size的分布尽量集中可以提高Memcached的内存利用率

以我遇到的问题做为例: 我们需要在Memcached里保存User的操作记录,为了贪图查询的方便,我们就Key<UserID> Value<List<操作记录>>,当每位User的操作记录数量从1n都有分布,那么n较大的数据就会选择了Size较大的Chunk进行储存,若出现17193bytes大小的数据,那么只能从以下两个Slab中选择Slab Class 25进行存储:

slab class 24: chunk size 17192 perslab 60

slab class 25: chunk size 21496 perslab 48

如果这样Size的数据非常多的话,那就非常杯具了,浪费的内存成(21496-17193)*m线性增长;因此我们改变了存储策略,使用Key<操作记录ID> = Value<操作记录> Key<UserId> = Value<List<操作记录 ID>>进行存储,这样操作记录的每对K/VSize都在200bytes左右,结果内存利用了提升到90%左右;

n 根据ValueSize分布,适当调整的Growth Factor也是可以提升内存利用率

n 最后,Memcached本身就是解决不可靠数据的存取服务的,做为二级缓存是不错的选择,可以很大程度的提升性能,但是要想存取可靠的数据,就不能选择Memcached,选择一项适合的技术保障可用性才是王道。

VN:F [1.9.6_1107]

please wait...

Rating: 0.0/10 (0 votes cast)

VN:F [1.9.6_1107]

Rating: 0 (from 0 votes)

 

» 转载请注明来源:贰号楼肆层 » 《Memcached之内存利用率提升经验分享》

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics