文章链接:http://www.hcoding.com/?p=121
个人站点:JC&hcoding.com
memcached是什么呢?memcached是一个优秀的、高性能的内存缓存工具。
memcached具有以下的特点:
- 协议简单:memcached的服务器客户端通信并不使用复杂的MXL等格式,而是使用简单的基于文本的协议。
- 基于libevent的事件处理:libevent是个程序库,他将Linux 的epoll、BSD类操作系统的kqueue等时间处理功能封装成统一的接口。memcached使用这个libevent库,因此能在Linux、BSD、Solaris等操作系统上发挥其高性能。(libevent是什么)
- 内置内存存储方式:为了提高性能,memcached中保存的数据都存储在memcached内置的内存存储空间中。由于数据仅存在于内存中,因此重启memcached,重启操作系统会导致全部数据消失。另外,内容容量达到指定的值之后memcached回自动删除不适用的缓存。
- Memcached不互通信的分布式:memcached尽管是“分布式”缓存服务器,但服务器端并没有分布式功能。各个memcached不会互相通信以共享信息。他的分布式主要是通过客户端实现的。
本文主要讲解memcached的连接模型,memcached由一条主线程(连接线程)监听连接,然后把成功的连接交给子线程(工作线程)处理读写操作。N条【启动memcached通过-t命令指定】子线程(工作线程)负责读写数据,一条子线程(工作线程)维护着多个连接。一个conn结构体对象对应着一个连接,主线程(连接线程)成功连接后,会把连接的内容赋值到一个conn结构体对象,并把这个conn结构体对象传递给一条子线程(工作线程)处理。
conn结构体:
1 typedef struct conn conn; 2 struct conn { 3 int sfd; 4 sasl_conn_t *sasl_conn; 5 6 // 连接状态 7 enum conn_states state; 8 enum bin_substates substate; 9 struct event event; 10 short ev_flags; 11 12 // 刚刚出发的事件 13 short which; /** which events were just triggered */ 14 15 // read buffer 16 char *rbuf; /** buffer to read commands into */ 17 18 // 已经解析了一部分的命令, 指向已经解析结束的地方 19 char *rcurr; /** but if we parsed some already, this is where we stopped */ 20 21 // rbuf 已分配的大小 22 int rsize; /** total allocated size of rbuf */ 23 24 // 尚未解析的命令大小 25 int rbytes; /** how much data, starting from rcur, do we have unparsed */ 26 27 // buffer to write 28 char *wbuf; 29 30 // 指向已经返回的地方 31 char *wcurr; 32 33 // 写大小 34 int wsize; 35 36 // 尚未写的数据大小 37 int wbytes; 38 39 /** which state to go into after finishing current write */ 40 // 当写回结束后需要即刻转变的状态 41 enum conn_states write_and_go; 42 43 void *write_and_free; /** free this memory after finishing writing */ 44 45 char *ritem; /** when we read in an item's value, it goes here */ 46 int rlbytes; 47 48 /* data for the nread state */ 49 50 /** 51 * item is used to hold an item structure created after reading the command 52 * line of set/add/replace commands, but before we finished reading the actual 53 * data. The data is read into ITEM_data(item) to avoid extra copying. 54 */ 55 56 // 指向当下需要完成的任务 57 void *item; /* for commands set/add/replace */ 58 59 /* data for the swallow state */ 60 int sbytes; /* how many bytes to swallow */ 61 62 /* data for the mwrite state */ 63 struct iovec *iov; 64 int iovsize; /* number of elements allocated in iov[] */ 65 int iovused; /* number of elements used in iov[] */ 66 67 // msghdr 链表, 一个连接可能有多个 msghdr 68 // 如果是 UDP, 需要为每一个 msghdr 填写一个 UDP 头部 69 struct msghdr *msglist; 70 int msgsize; /* number of elements allocated in msglist[] */ 71 int msgused; /* number of elements used in msglist[] */ 72 int msgcurr; /* element in msglist[] being transmitted now */ 73 int msgbytes; /* number of bytes in current msg */ 74 75 item **ilist; /* list of items to write out */ 76 int isize; 77 item **icurr; 78 79 // 记录任务数量 80 int ileft; 81 82 char **suffixlist; 83 int suffixsize; 84 char **suffixcurr; 85 int suffixleft; 86 87 enum protocol protocol; /* which protocol this connection speaks */ 88 enum network_transport transport; /* what transport is used by this connection */ 89 90 /* data for UDP clients */ 91 int request_id; /* Incoming UDP request ID, if this is a UDP "connection" */ 92 struct sockaddr request_addr; /* Who sent the most recent request */ 93 socklen_t request_addr_size; 94 95 unsigned char *hdrbuf; /* udp packet headers */ 96 int hdrsize; /* number of headers' worth of space is allocated */ 97 98 bool noreply; /* True if the reply should not be sent. */ 99 /* current stats command */ 100 struct { 101 char *buffer; 102 size_t size; 103 size_t offset; 104 } stats; 105 106 /* Binary protocol stuff */ 107 /* This is where the binary header goes */ 108 protocol_binary_request_header binary_header; 109 uint64_t cas; /* the cas to return */ 110 short cmd; /* current command being processed */ 111 112 // ? 不透明 113 int opaque; 114 int keylen; 115 116 // 可见是一个链表 117 conn *next; /* Used for generating a list of conn structures */ 118 119 // 指向服务于此连接的线程 120 LIBEVENT_THREAD *thread; /* Pointer to the thread object serving this connection */ 121 };