2018.6.19
今天来看memecached的缓存设置,前面学习的是memcached的网络模型,现在来讲一下memcached的缓存模型。今天来学习关于缓存模型的哈希表的结构。
从这一章开始我们慢慢讲解Memcached是如何存储数据的。
讲解本章前,我们先看一个Memcached存储数据的item的基本结构。
数据结构
1. //item的具体结构
2. typedef struct _stritem {
3. //记录下一个item的地址,主要用于LRU链和freelist链
4. struct _stritem *next;
5. //记录上一个item的地址,主要用于LRU链和freelist链
6. struct _stritem *prev;
7. //记录HashTable的下一个Item的地址
8. struct _stritem *h_next;
9. //最近访问的时间,只有set/add/replace等操作才会更新这个字段
10. //当执行flush命令的时候,需要用这个时间和执行flush命令的时间相比较,来判断是否失效
11. rel_time_t time; /* least recent access */
12. //缓存的过期时间。设置为0的时候,则永久有效。
13. //如果Memcached不能分配新的item的时候,设置为0的item也有可能被LRU淘汰
14. rel_time_t exptime; /* expire time */
15. //value数据大小
16. int nbytes; /* size of data */
17. //引用的次数。通过这个引用的次数,可以判断item是否被其它的线程在操作中。
18. //也可以通过refcount来判断当前的item是否可以被删除,只有refcount -1 = 0的时候才能被删除
19. unsigned short refcount;
20. uint8_t nsuffix; /* length of flags-and-length string */
21. uint8_t it_flags; /* ITEM_* above */
22. //slabs_class的ID。
23. uint8_t slabs_clsid;/* which slab class we're in */
24. uint8_t nkey; /* key length, w/terminating null and padding */
25. /* this odd type prevents type-punning issues when we do
26. * the little shuffle to save space when not using CAS. */
27. //数据存储结构
28. union {
29. uint64_t cas;
30. char end;
31. } data[];
32. /* if it_flags & ITEM_CAS we have 8 bytes CAS */
33. /* then null-terminated key */
34. /* then " flags length\r\n" (no terminating null) */
35. /* then data with terminating \r\n (no terminating null; it's binary!) */
36. } item;
说明:
- Memcached上存储的每一个元素都会有一个Item的结构。
- Item结构主要记录与HashTable之间的关系,以及存储数据的slabs_class(后面几章节会讲解)的关系以及key的信息,存储的数据和长度等基本信息。
- Item块会被分配在slabclass上,slabclass会在下下章节中详细讲解。
- HashTable的主要作用是:用于通过key快速查询缓存数据。
Memcached的HashTable源码分析
HashTable结构图
说明:
- Memcached在启动的时候,会默认初始化一个HashTable,这个table的默认长度为65536
- 我们将这个HashTable中的每一个元素称为桶,每个桶就是一个item结构的单向链表
- Memcached会将key值hash成一个变量名称为hv的uint32_t类型的值。
- 通过hv与桶的个数之间的按位与计算,hv & hashmask(hashpower),就可以得到当前的key会落在哪个桶上面。
- 然后会将item挂到这个桶的链表上面。链表主要是通过item结构中的h_next实现。
从上面的图来看,和之前的缓存结构也是类似的,通过哈希桶的方式来达到快速查找。即可以通过key快速的查询缓存的数据。
memcached查找的流图:
思考与分析:
这里我们可以学习到的是,memcached利用的哈希桶的缓存技术,这种设计到缓存的,为了快速的查找,避免全局的遍历,一般都会设置哈希桶来实现,哈希桶可以达到快速查找的目的。