Memcache的内存模型
几个名词
Item
指实际存放到memcached中的数据对象结构,除key-value数据外,还包括memcached自身对数据对象的描述信息(Item=key+value+16byte后缀长+32byte结构体)Chunk
Chunk才是存放缓存数据的单位,Chunk是一系列固定的内存空间.一个Chunk里面存一个ItemSlab
相同大小的chunk的集合Page
Page为内存分配的最小单位 Memcached的内存分配以page为单位,默认情况下一个page是1M,可以通过-I参数在启动时指定。如果需要申请内存时,memcached会划分出一个新的page并分配给需要的slab区域。page一旦被分配在重启前不会被回收或者重新分配
内存结构
上面途中的slab就当做是Page
每个类型slab的都会有一个LRU链表、一个空闲Item列表
每次读的时候会更新LRU如果已经过期会设置到slots
内存分配
Memcached在启动时通过-m指定最大使用内存,但是这个不会一启动就占用,是随着需要逐步分配给各slab的
如果一个新的缓存数据要被存放,memcached首先选择一个合适的slab,然后查看该slab是否还有空闲的chunk,如果有则直接存放进去;如果没有则要进行申请。slab申请内存时以page为单位,所以在放入第一个数据,无论大小为多少,都会有1M大小的page被分配给该slab
申请到page后:
slab会将这个page的内存按chunk的大小进行切分,这样就变成了一个chunk的数组,在从这个chunk数组中选择一个用于存储数据
这里有几个特点要注意:
1:Memcached分配出去的page不会被回收或者重新分配
2:Memcached申请的内存不会被释放slab
3:空闲的chunk不会借给任何其他slab使用[新版本中Page可以调配给其它的Slab,shell> memcached -o slab_reassign,slab_automove]
如果申请不到page:
触发当前slab的LRU机制
如何查询
整个memcache有个Hashtable,查询时,通过hashtable快速定位
HashTable的主要作用是:用于通过key快速查询缓存数据
- Memcached在启动的时候,会默认初始化一个HashTable,这个table的默认长度为65536
- 我们将这个HashTable中的每一个元素称为桶,每个桶就是一个item结构的单向链表
- Memcached会将key值hash成一个变量名称为hv的uint32_t类型的值
- 通过hv与桶的个数之间的按位与计算,hv & hashmask(hashpower),就可以得到当前的key会落在哪个桶上面
- 然后会将item挂到这个桶的链表上面。链表主要是通过item结构中的h_next实现