经过这几天的学习,要将RDMA移植到memcached上,主要有下面3个方面的工作需要完成:
1、TCP连接到QP(Queue Pair)的创建
Memcached在建立网络连接时,只是使用socket创建了TCP的数据链路;而使用RDMA时还需要在客户端和服务器端创建SQ和RQ队列并创建指针指向注册内存区域。
2、Get和Set操作
数据库最主要的操作就是查询和插入,对应于Get和Set操作。客户端读写数据时首先会访问memcached服务器,对服务器Hash表中的kv对(key-value)进行操作,这里要将客户端和缓存服务器间的基于TCP的数据传输换成RDMA方式。上一次的总结结尾说过读写操作和我们这次比赛的关系不大,后来发现还是有关系的。
3、Update操作
在访问缓存服务器失效时(第一次访问该数据或者被LRU替换掉了),数据返回给用户的同时还要写入缓存服务器,以便下次访问;缓存服务器中改动过的数据也要写回数据库中,保持数据的一致性。缓存服务器和数据库之间的数据传输也可以改成RDMA方式。
这几天具体看了下memcached数据处理的过程和get、set操作过程,跟大家分享一下。
Memcached在网络连接建立后,由Master线程分发给Worker线程,而Worker线程处理业务逻辑,采用状态机的方式,状态机按不同的状态处理业务逻辑。Memcached.h中定义的11种状态如下:
enum conn_states {
conn_listening, /**< the socket which listens for connections */ //监听状态
conn_new_cmd, /**< Prepare connection for next command */ //为新连接做一些准备
conn_waiting, /**< waiting for a readable socket */ //等待读取一个数据包
conn_read, /**< reading in a command line */ //读取网络数据
conn_parse_cmd, /**< try to parse a command from the input buffer */ //解析缓冲区的数据
conn_write, /**< writing out a simple response */ //简单的回复数据
conn_nread, /**< reading in a fixed number of bytes */ //读取固定数据的网络数据
conn_swallow, /**< swallowing unnecessary bytes w/o storing */ //处理不需要的写缓冲区的数据
conn_closing, /**< closing this connection */ //关闭连接
conn_mwrite, /**< writing out many items sequentially */ //顺序的写多个item数据
conn_closed, /**< connection is closed */ //连接已关闭
conn_max_state /**< Max state value (used for assertion) */ //最大状态,做断言使用
};
状态转换关系如下图,有些状态没什么用,就没展现。
while(!stop)
{
switch(c->state)
{
case conn_listening:
break;
case conn_waiting:
b