1、item(_stritem)结构体(memcached.h 293行-310行):
item是memcached中存储数据的最小单位,是key-value的抽象,还记录了最近访问时间、消亡时间等重要信息。下面根据源代码一一介绍:
typedef struct _stritem { struct _stritem *next; //下一个item struct _stritem *prev; //上一个item struct _stritem *h_next; //hash表的下一项 rel_time_t time; //最近访问时间 rel_time_t exptime; //消亡时间 int nbytes; //数据大小 unsigned short refcount; //引用计数 uint8_t nsuffix; // **的长度 uint8_t it_flags; /* ITEM_* above */ uint8_t slabs_clsid;// item所存入的slab uint8_t nkey; //key长度 void * end[]; /* 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; |
在memcached中每个item 是存储在其对应大小的slabclass_t 里的,同时又在hash 表中有记录。既可以使用自己的内存分配机制来减少操作系统在处理内存碎片,添加释放等多余的操作,又可以使用hash 表的性质对其进行快速的定位。
2、slab(slabclass_t)结构体(slabs.c 26行-44行):
slabclass_t保存了分级大小的空间槽,以分别适用于不同大小的item存放.取决于两个命令行参数,-f和-n.在应用slabclass_t时,定义的是一个数组,该数组长度取决于增长的指数级别和初始值大小(32+chunk_size),每个空间槽是不允许大于1M的,也就是1048576。slabclass是由(MAX_NUMBER_OF_SLAB_CLASSES)个slabclass_t结构体构成的数组,每个slabclass_t结构体的大小是根据增长因子递增的,增长因子可以由客户端来设定,1.28版本的默认值为2,合理的调优增长因子可以避免空间的浪费
typedef struct { unsigned int size; //items大小 unsigned int perslab; //每个slab有多少个item void **slots; //item链表 unsigned int sl_total; //已有item的数量 unsigned int sl_curr; //第一个空闲链表位置 void *end_page_ptr; //指向下一个空闲item槽的页面结尾地址的指针或者是0 unsigned int end_page_free; //在最后分配页面中,存在的items的数量。 unsigned int slabs; //在这个级别中分配了多少个slab void **slab_list; //slab数组的指针 unsigned int list_size; //slab数组大小 unsigned int killing; /* index+1 of dying slab, or zero if none */ size_t requested; //需要的字节数 } slabclass_t; static slabclass_t slabclass[MAX_NUMBER_OF_SLAB_CLASSES]; |
3、conn结构体(memcached.h 331行-418行):
conn结构是联系上下文的关键对象。对于每个连接的到来,都有一个conn结构与其对应,并且对应到某个连接状态,进入状态转换而完成操作。
conn在程序开始也进行了一次预分配,分配200个连接空间。当200个使用完之后便是按需分配,到达一个分配一个。
conn和item、iovec(内核级别缓冲结构)关联
typedef struct conn conn; struct conn { int sfd; sasl_conn_t *sasl_conn; enum conn_states state; enum bin_substates substate; struct event event; short ev_flags; short which; //刚刚被触发的事件 char *rbuf; //缓存读入的命令 char *rcurr; //语法分析的位置 int rsize; //缓存读入命令的大小 int rbytes; //从rcur开始还有多少信息没有进行语法分析 char *wbuf; char *wcurr; int wsize; int wbytes; enum conn_states write_and_go;//在写操作完成后加入什么状态 void *write_and_free; //在写操作完成后释放该内存 char *ritem; //指向读入item的value int rlbytes; //nread信息数据 /** * 在读取数据之前,item被用来保存一个item结构体, *这个结构体在读入命令行(set/add/replace)后被创建, *数据被读入ITEM_data(item)防止多余拷贝 */ void *item; //保存set/add/replace命令 //总体情况 int sbytes; //总字节数 //nwrite信息数据 struct iovec *iov; int iovsize; //在iov[]数组中分配的元素个数 int iovused; /* number of elements used in iov[] */在iov[]数组中被使用元素的个数 struct msghdr *msglist; int msgsize; //在msglist[]数组中分配的元素个数 int msgused; //在msglist[]数组中被用的元素个数 int msgcurr; //正在传送的元素个数 int msgbytes; //当前msg中的字节数 item **ilist; //需要输出的item链表 int isize; item **icurr; int ileft; char **suffixlist; int suffixsize; char **suffixcurr; int suffixleft; enum protocol protocol; //此次连接的端口 enum network_transport transport; //此次连接的传输工具 //UDP客户端的数据 int request_id; //UDP连接需要一个ID struct sockaddr request_addr; //最近发出请求的地址 socklen_t request_addr_size; unsigned char *hdrbuf; //udp包的头 int hdrsize; //头部空间 bool noreply; //如果没发送应答,将被置为true //当前环境的命令 struct { char *buffer; size_t size; size_t offset; } stats; //二进制协议 //二进制协议的头 protocol_binary_request_header binary_header; uint64_t cas; //所要返回的cas short cmd; //当前所处理的命令 int opaque; int keylen; conn *next; /*/用来创建一个conn结构体链表 LIBEVENT_THREAD *thread; //指向服务的线程 };
|
所有评论(0)