memcache 内存分配机制详解
1. memcached机制
a. 守护进程机制
-UNIX daemon
b. Socket事件处理机制
-non-blocked:非阻塞
-libevent:异步事件处理
-epoll/kqueue
c. 内存管理机制
-slab:内存分配机制
-LRU:对象清除机制
-Hash机制:快速检索item
d. 多线程处理机制:pthread(POSIX)线程模式
-编译时开启:./configure –enable-threads
-目前还比较粗糙,锁机制locking不够完善
-负载过重时,可以开启(-t线程数为CPU核数)
2. memcached内存管理机制
a. SLAB内存处理机制
-提前分配大内存slab 1MB,再进行小对象填充chunk
-避免大量重复的初始化和清理 减轻内存管理器负担
-避免频繁malloc/free系统碎片
b. 懒惰检测机制
-不检测item对象是否超时
-get时检查item对象是否应该删除
c. 懒惰删除机制
-删除item对象时,不释放内存,作删除标记,指针放入slot回收插槽,下次分配的时候直接使用
3. 名词解释
a. slab class:内存区类别(48byte-1MB)
-slab==page:动态创建的实际内存区
-slab classid:slab class的ID
b. chunk:数据区块,固定大小
-item:实际存储在chunk中的数据项
1. slab内存结构图:二维数组链表
slab是一次申请内存的最小单位
2. slab内存分配实例
3. 实例数据
4. 计算slab占用内存
5. slab参数
进程内存区
slabclass元信息:1.1中是21byte,1.2中是200byte
Hashtable:1.1中位41MB,1.2中位65MB
数据内存区
slab默认大小为1048576byte(1MB),大于1MB数据忽略
chunk初始大小,1.1中是1byte,1.2中是48byte
增长因子factor
1.1中,chunk大小为初始大小*2^n,n为classid,即:
id为0的slab大小1byte,id为1的slab大小2byte,id为2的slab大小4byte...
id为20的slab,每chunk大小为1MB,只有一个chunk
1.2中有一个factor值,默认为1.25
96,120,152...
1. Item数据格式
Item是保存在chunk中的实际数据
2. 新建Item分配内存过程
快速定位slab classid
计算key+value+suffix+32结构体,如90byte
如果>1MB,无法存储丢弃
取最小冗余的slab class
如:有48,96,120,存90会选择96
按顺序寻找可用chunk
slot:检查slab回收空间slot里是否有剩余chunk
delete:delete时标记到slot
exptime:get时检查的过期对象标记到slot
end_page_ptr:检查page中是否有剩余chunk
memory:内存还有剩余则开辟新的slab
LRU:Slab内部扫描Item双向链表50次
1. 调优的最高指示精神
提高内存利用率,减少内存浪费
提高命中率(80%,95%?)
调优方法:
f参数:factor增长因子
n参数:chunk初始值
低CPU消耗(瓶颈在于网络IO)
libevent事件机制
slab内存预分配机制
适合使用大量低CPU的机器搭建集群
32位机器最大2GB,64GB无限制
-m分配内存为数据区,memcached本身也需要占用内存,因此不可将物理内存全部分配
使用连接池维持连接
2. 内存浪费
slab尾部剩余空间
如classid=40中,两个chunk占用了1009384byte,就有1048576-1009384=39192byte被浪费
解决办法:规划slab=chunk*n整数倍
slab中chunk利用率低:申请的slab只存放了一个Item
解决办法:规划slab=chunk
chunk存储Item浪费
如I tem是100,存到128字节chunk,就有28字节浪费
解决办法:规划chunk=Item
3. 使用合适的factor,减少浪费
-f参数:默认为1.25,曾经为2
值越小,slab中chunk size差距越小,内存浪费越小
建议:计算一下数据的预期平均长度,调整factor,以获得最恰当的设置
4. 根据数据分布调整factor
非均匀分布,即数据长度集中在几个区域内
如保存用户Session
更极端的状态是等长数据
如定长键值,定长数据
多见于访问、在线统计或执行锁
计算Item长度
key键长+suffix+value值长+结构大小(32字节)
Can’t dump
无法备份,重启无法恢复
Can’t iterate over keys
无法查询
Not persistent
没有持久化,重启全部丢失
Not redundant
单点故障failover
No Sessions
崩溃没法查找原因
No security
任何机器都可以telnet,需要放在防火墙后
内存问题
LRU是slab局部,没有全局
有空间浪费
日志问题
没有合理的日志
集群问题
集群增加机器成本高
参考推荐:
版权所有: 本文系米扑博客原创、转载、摘录,或修订后发表,最后更新于 2015-01-28 10:10:51
侵权处理: 本个人博客,不盈利,若侵犯了您的作品权,请联系博主删除,莫恶意,索钱财,感谢!
转载注明: memcache 内存分配机制详解 (米扑博客)