分布式缓存系统 Memcached(二)——数据存储slab与hashtable
来源:互联网 发布:app源码是什么 编辑:程序博客网 时间:2024/04/27 15:05
缓存数据以item为基本单元,以双链表形式存放在对应级别大小的slabclass结构的chunk中。同时该item还存放在链式hashtable中bucket中,用于提供快速查找的索引。
首先是理解缓存的基本数据单元item结构:
typedef struct _stritem { struct _stritem *next; //在slab中的双链表后向指针 struct _stritem *prev; //在slab中的双向链表的前向指针 struct _stritem *h_next; //指向hash表该bucket中的该item的下一项 /* hash chain next */ rel_time_t time; //最近访问时间戳 /* least recent access */ rel_time_t exptime; //过期时间/* expire time */ int nbytes; //数据大小/* size of data */ unsigned short refcount; //引用计数 uint8_t nsuffix; /* length of flags-and-length string */ uint8_t it_flags; /* ITEM_* above */ uint8_t slabs_clsid; //所在的slab,该slab在slabclass数组中的下标/* which slab class we're in */ uint8_t nkey; //key的长度/* key length, w/terminating null and padding */ /* this odd type prevents type-punning issues when we do * the little shuffle to save space when not using CAS. */ union { uint64_t cas; char end; } data[];//真实数据 /* if it_flags & ITEM_CAS we have 8 bytes CAS */ /* then null-terminated key */ /* then " flags length\r\n" (no terminating null) */ /* then data with terminating \r\n (no terminating null; it's binary!) */} item;
item的结构图如下:
item存放的数据结构slabclass:
//slabclass结构typedef struct { unsigned int size; //该slab的每个chunk的大小 /* sizes of items */ unsigned int perslab; //能存放的size大小的chunk的数量/* how many items per slab */ void *slots; /* 回收来的item链表, 当分配出去的item回收时不时将空间还给slab, 而是直接把该slab从chunk双向链表中删除, 挂到slots链表的尾部,以供循环利用, 且在下次使用时不需要再初始化该item结构, 而是直接更改其各属性值即可list of item ptrs */ unsigned int sl_curr; /* 表示当前slots链表中 有多少个回收而来的空闲 item. total free items in list */ unsigned int slabs; //已分配的当前种类slab的数量/* how many slabs were allocated for this class */ void **slab_list; /* 初始时, memcached 为每个级别的slabclass 分配一个slab,当这个 slab 内存块使用完后,memcached 就分配一个新的 slab,所以 slabclass 可以拥有多个同一级别的slab,这些 slab 就是通过 slab_list 数组来管理的, slab. array of slab pointers */ unsigned int list_size; /* 表示当前 slabclass 有多少个slabsize of prev array */ unsigned int killing; /* index+1 of dying slab, or zero if none */ size_t requested; /* The number of requested bytes */} slabclass_t;static slabclass_t slabclass[MAX_NUMBER_OF_SLAB_CLASSES];//slab数组(其中slab按其chunk从小到大排列)
(注意:同一级别的slabclas可能包括多个该级别的slab,维护在指针数组slab_list中)
在 slabclass 内, 只有最后一个 slab 存在空闲的内存, 其它 slab 的 chunk 都分配出去了。
end_page_ptr:指向最后一个 slab 中的空闲内存块
end_page_free :表示最后一个 slab 中还剩下多少个空闲 chunk. 图中绿色部分的 chunk 表示空闲 chunk。
每个slabclass维护一个双向链表,所有分配出去的item按照最近访问时间依次放到该链表中,该链表也就相当于LRU队列。
所有slabclass的链表头 尾分表保存在*heads、 *tails两个数组中:
static item *heads[LARGEST_ID];//chunk链表头指针数组:slabclass数组中各级别slabclass的chunk链表头 组成的数组static item *tails[LARGEST_ID];//chunk链表尾指针数组:slabclass数组中各级别slabclass的chunk链表尾 组成的数组
item空间分配策略:
** 每次需要为新的item分配空间时,首先根据该item的大小,计算出对应级别的slabclass的id,然后在slabclass数组中找到该slabclass。** 定位到对应slabclass后,首先检查LRU队列的最后一个chunk是否过期,过期则分给用户使用;否则到item回收链表slots中查空闲的chunk;没有回收空闲的chunk则从slab空闲(未分配过得)的chunk中分配;如果没有,则LRU算法在已分配chunk的双向链表中从 尾部向前查找能够释放(最久未访问)的item,依次为新item取得空间。
** 当删除某item时,并不将该chunk空间归还给对应的slab,而是从该slab的已分配chunk链表中删除该chunk ,然后将该chunk挂到回收链表slots的头部,以供循环利用, 并且该chunk中的item也不会释放,直到该chunk被重新利用时直接更新该item的各项属性值。(不用每次都初始化item结构,提高效率!)
链式HsahTable:
同时,slab的chunk链表中的item也被存放到hashTable中。 当需要查找给定key的item时,首先在哈希表中hash到该key对应的item,然后利用hashtable中的item信息得到该item在slabclass中索引位置。
使用了两张hashtable,一个主表,一个“原表”。正常情况下,操作都是在主表中进行的;当正在扩容时,首先在原表中进行操作。
当表中item数量大于表bucket节点数的1.5倍时开始扩容为原来的2倍,采用逐步扩容方式,每次迁移的数量可以设置。 主表与原表是动态切换的,当扩容开始的时候,把主表的类容复制到原表中,让原表替换主表暂时接受操作,而主表容量扩大为原来的两倍,然后逐步从原表中将数据hash到扩容后的主表中,当数据全部迁移完成,所有的操作又回到主表中进行了。
这与Redis中的两张hashtable的操作是一致的。
注:文中图片来自http://blog.csdn.net/lcli2009/article/details/21985793
- 分布式缓存系统 Memcached(二)——数据存储slab与hashtable
- 分布式缓存系统Memcached(六)——slab和item的主要操作
- 分布式缓存系统Memcached(十)——状态机之网络数据读取与解析
- 分布式缓存系统 Memcached(一)——整体架构
- 分布式缓存系统Memcached(五)——内存管理机制
- Memcached分布式内存对象缓存系统(二)
- 分布式缓存系统Memcached简介与实践
- 分布式缓存系统Memcached简介与实践
- 分布式缓存系统Memcached简介与实践
- 分布式缓存系统Memcached简介与实践
- 分布式缓存系统Memcached简介与实践
- 分布式缓存系统Memcached简介与实践
- 分布式缓存系统Memcached简介与实践
- 分布式缓存系统Memcached简介与实践
- 分布式缓存系统Memcached简介与实践
- 分布式缓存系统Memcached简介与实践
- 分布式缓存系统Memcached简介与实践
- 分布式缓存系统Memcached简介与实践
- android 5.0新特性
- C++算法1-4 非递归遍历树的一点研究(习题5.82,5.83)
- 强制使用官方Windows Update
- 一、SOAP简单对象访问协议讲解
- FPGA片外存储器之cyclone v ddr2,ddr3
- 分布式缓存系统 Memcached(二)——数据存储slab与hashtable
- [转载]NS2架构zz
- vs2013注释快捷键
- LZSS算法
- Intel 中国研究院面试经历
- Android自定义Button按钮显示样式(以此点击按钮类型类推)
- 黑马程序员-c语言字符串
- LeetCode Find Minimum in Rotated Sorted Array
- [LeetCode OJ]Gray Code