Memcached数据存储方式
Memcached的内存数据存储方式被称为 Slab Allocator(对象缓存分配)。采取的思想可以理解为化整为零。就是将内存进行多层次的拆分,达到对对象和内存进行最精准的管理。拆分如下:
- 先把内存拆分成很多个slab块。每个slab的大小都可以预先设置。上一篇文章中有对应的参数列表。
- slab的内存空间称为ipage,每个page的大小默认是1M,可以在启动的时候参数l指定page的大小。把每个page的内存拆分成多个大小相等chunk内存块,数据就存储在各个chunk中。
- chunk的大小也是预先设置的。Memcached中有一个增长因子,chunk可以根据这个增长因此增大。
- slab class 这个等于slab的索引ID。 每一个slab对应着一个slab classId。
Memcached内存简图如下:
Memcached数据存储过程
- 在Memcached中每一个需要存储的数据(对象)称为一个Item。每存储一个数据就是为一个Item分配内存的过程。过程如下:
1.快速定位 slab classid, 计算Item的大小,item大小 = key键长 + flag + suffx(16字节) + value值长 + 结构大小(32字节)。也就是说其实item的大小需要增加48个字节就是最终长度。如果item的大小大于定义page大小,则丢弃。否则选择冗余最小的slab保存。 例:item最终大小90字节,slab有60,96,153.选择96存储。
2.查找可用的chunk
(1) slot: 检查slab回收空间slot里面是否有剩余的空间(slot就是slab的回收空间,过期的,删除的对象都会被标记,然后放到回收空间中,等chunk不够时候,从回收空间查找,才会真正删除这些数据)
(2) end_page_etr:检查page中是否有剩余的chunk.
(3) memory:检查内存空间是否有剩余的空间开辟新的slab
(4) LRU(最近最少使用算法)丢弃最近最少使用的chunk来存储新的数据。
Memcached数据存储的缺点
1.每个chunk的大小固定,如果Item的大小小于chunk的大小,造成内存浪费。
2.slab的大小固定,这样如果划分chunk不能刚好分配完,造成内存浪费。
3.有可能某些slab classid没被使用,也就是slab可能在数据过期后,不会在被使用。造成内存浪费。
Memcached数据过期机制
- Lazy Expiration(延迟/懒惰 过期) 当数据已经过期的话,Memcached不会主动去检查数据是否过期,只有当外部来获取该数据的时候,才检查。
- LRU(最近最少使用)当内存没有空间开辟新的slab的时候,就会采用LRU机制,释放最近最少使用的对象空间。Memcached中的LRU机制针对的是slab级的,不是整个内存级别的。
- 懒惰删除:当删除Item时候,Memcached并不会直接删除,而是做一个删除标记,然后放入到slab的回收空间slot中,下次分配就优先使用slot中的空间。