memcached源码分析-----LRU队列与item结构体

本文深入分析了memcached中LRU队列的插入、删除和更新操作,以及item结构体与哈希表的联系。LRU队列是一个用于管理item的双向链表,用于实现高效的缓存淘汰策略。item结构体包含关键成员如slabs_clsid,用于区分不同种类的item。文章详细讲解了item如何在LRU队列中移动以及与哈希表的交互过程。
摘要由CSDN通过智能技术生成


        转载请注明出处:http://blog.csdn.net/luotuo44/article/details/42869325



LRU队列:

        之前的《slab内存分配》博文已经写到:一个slab class里面的所有slab分配器只分配相同大小的item,不同的slab class分配不同大小的item。item结构体里面有一个slabs_clsid成员,用来指明自己是属于哪个slab class的。这里把slabs_clsid值相同的item称为是同一类item

        slab分配器负责分配一个item,但这个item并非直接被哈希表进行管理。从《哈希表的删除操作》可以得知,对哈希表中的某一个item进行删除只是简单地将这个item从哈希表的冲突链中删除掉,并没有把item内存归还给slab。实际上,slab分配器分配出去的item是由一个LRU队列进行管理的。当一个item从LRU队列中删除就会归还给slab分配器 。


        LRU队列其实是一个双向链表。memcached里面有多条LRU队列,条数等于item的种类数。所以呢,同一类item(slabs_clsid成员变量值相等)将放到同一条LRU队列中。之所以是双向链表,是因为要方便从前后两个方向插入和遍历链表。下面浏览一下item结构体的部分成员。

typedef struct _stritem {
    struct _stritem *next; //next指针,用于LRU链表
    struct _stritem *prev; //prev指针,用于LRU链表
    struct _stritem *h_next;//h_next指针,用于哈希表的冲突链
    rel_time_t      time;   //最后一次访问时间。绝对时间
	  ...
    uint8_t         slabs_clsid;/* which slab class we're in */
} item;

        接下来阅读管理LRU队列的数据结构。其实是超级简单的,就三个全局数组而已,而且是static数组(开心吧)。

//memcached.h文件
#define POWER_LARGEST  200

//items.c文件
#define LARGEST_ID POWER_LARGEST
static item *heads[LARGEST_ID];//指向每一个LRU队列头
static item *tails[LARGEST_ID];//指向每一个LRU队列尾
static unsigned int sizes[LARGEST_ID];//每一个LRU队列有多少个item

        可以看到这三个数组的大小是和slabclass提供的最大slab class个数是一样的。这样也印证了一个LRU队列就对应一类item。heads[i]指向第i类LRU链表的第一个item,tails[i]则指向了第i类LRU链表的最后一个item,sizes[i]则指明第i类LRU链表有多少个item。由LRU队列和heads和tails构成的结构如下图所示:

        



LRU队列的基本操作:


插入操作:

        假设我们有一个item要插入到LRU链表中,那么可以通过调用item_link_q函数把item插入到LRU队列中。下面是具体的实现代码。

//将item插入到LRU队列的头部
static
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值