设为首页 - 加入收藏 - 网站地图 欢迎加QQ群 :14364084
当前位置:谭博的博客 > 缓存 > memcache > 正文

Memcached源码阅读笔记

时间:2014-02-25 09:16 来源:未知 标签:Memcached源码阅读笔记 作者:谭博 阅读:

1、第一个slab的chunk size值

       当我试图修改memcached的起始slab大小以便用于存储非常小的缓存对象(往往值是没有意义的,只是用一个1之类的标志来表示key是否存在,这个通常用于判断缓存一种状态而不是数值,例如是否获得过当天的登陆奖励)时发现了这个问题。
        通过启动memcached时添加参数: -n48 (48是要被设置的值,必须是正数) 可以指定第一个slab的chunk大小,但是经过尝试和跟踪代码发现,第一个slab的chunk size不止受此一个参数限制,具体计算第一个chunk size的过程如下:

  1. -n 指定的值被存放到 settings.chunk_size中
  2. 当memcached启动时,会初始化slab(Slabs.c中的slabs_init),第一个slab的chunk size大小首先会被指定为
    unsigned int size = sizeof(item) + settings.chunk_size;
    然后在实际确定前需要转换为8的整数倍
    if (size % CHUNK_ALIGN_BYTES)
        size += CHUNK_ALIGN_BYTES – (size % CHUNK_ALIGN_BYTES);

        通过上面的计算过程可以发现,其实第一个slab的chunk size还受到struct item的大小决定。
        在尝试使用最小值时(即指定-n1时),在我的机器32位机器上生成的第一个slab大小是48,原因是 sizeof(item) 为32,加上1以后33,而33不是8的倍数,所以放大到48;在64位机器上 sizeof(item) 为48,所以最小应该为 56。

2、chunk中不仅仅存放缓存对象的value

         这个不知道是我自己理解的错误还是误听哪的说明,我一直以为chunk中只存放了缓存对象的value,所以在分配slab时只需要根据缓存的value大小来。但是这种情况下无法解释为什么在确定slab的chunk大小时要加上一个item的大小,如果只放1byte的数据却使用的是56byte(64位的服务器)的chunk未免太浪费了,而且不可能没有人发现这种情况,所以有理由怀疑我以前的认识了。
    chunk中不仅保持了缓存对象的value,而且保存了缓存对象的key,expire time, flag等详细信息
         经过查看memcached的源代码发现两个问题:

  1. memcached如何计算需要存放的缓存对象大小,以及如何选择slab
    查找缓存对象应该放到哪个slab时,不仅适用了value的长度,而且使用很多其他信息,具体计算公式如下:
        *nsuffix = (uint8_t) snprintf(suffix, 40, " %d %d\r\n", flags, nbytes – 2);
        return sizeof(item) + nkey + *nsuffix + nbytes;

    上式中item是存储缓存对象的struct,nkey为key的长度加1(用于存放字符串最后的''),nbytes为value的长度加2(存放'\r\n'),suffix为实际打印的字符数,memcached使用返回的大小来选择能够存放得下的最接近的slab。所以在选择slab时,memcached并不是只关心缓存值的大小。
    例如:如果是最短的key(1位),最短的值(1位),则在64机器上需要使用的空间其实是:
         48 + (1 + 1) + 6 + (1 + 2) = 59
    需要找一个大于或者等于59的slab存放。
    当指定-n1时第一个slab的大小为56,这个时候就出现了一个奇怪的现象,memcached的slab 1永远放不进值,因为最小的key和value需要的空间59都大于slab 1的56,必须放到slab 2(size为80),见下图:

    slab 2中只存放了一个对象,而且dump出来显示名称为“t”,值只有1byte,但是却使用了size为80的chunk,而slab 1将永远用不到。这个也可以说明其实在做slab初始化时计算的可能值小于实际需要的最小值。
  2. 到底chunk中存放了些什么
    为什么在选择slab时memcached需要计算那么多的空间进去,导致一个1byte的对象却需要59byte空间存放,从代码中得到的答案如下图:
    在chunk中通过item存放了缓存对象的一些详细信息,包括key的长度,value长度,过期时间,flag等信息,具体可以查看item结构定义,后面紧跟的是key的实际内容、suffix实际打印的内容、value的实际值,所以chunk中存放远比value信息多,有一些值的作用目前还没有搞清楚,但是大部分都是在缓冲对象使用过程中有明显作用的。

 

关注微信公众号

微信扫一扫,打赏我

热评文章
    内容不错,支持一下
    评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)