本文共 1712 字,大约阅读时间需要 5 分钟。
题记:看了《》,发现作者跳过了一些简单的地方,但这些简单的地方正好是我没看明白的地方,于是做点补充,也随便做个笔记。
版本:2.04。
1.Requests格式
*参数的个数 CRLF$第一个参数的长度CRLF第一个参数CRLF...$第N个参数的长度CRLF第N个参数CRLF
如果在redis_cli里键入get a,经过协议组装后的请求为
2\r\n$3\r\nget\r\n$1\r\na\r\n
2.流程
1.readQueryFromClient从fd读取数据:nread = read(fd, c->querybuf+qblen, readlen);
2.processInputBuffer判断是否是telnet的请求。
2.1 c->querybuf[0] == '*' -->processMultibulkBuffer。
2.2 telnet -->processInlineBuffer。
3.processMultibulkBuffer:解析指令,分解参数到c->argc和c->argv里面,argc表示个数,argv是
redis_object的指针数组。
4.processCommand:在redis server启动的时候,会调用populateCommandTable,将redisCommandTable数组转行成一个hash table(server.commands),lookupCommand通过key(get)查找对映的函数指针,如下:
struct redisCommand redisCommandTable[] = { {"get",getCommand,2,"r",0,NULL,1,1,1,0,0}, {"set",setCommand,3,"wm",0,noPreloadGetKeys,1,1,1,0,0},。。。。5.call(redisClient *c, int flags):执行指令函数。个人感觉最重要的一个调用:c->cmd->proc(c)。前面的c->cmd = c->lastcmd = lookupCommand(c->argv[0]->ptr),已经为cmd赋值了一个redisCommand指针。因为是get指令。c->cmd->proc(c) ==getCommand(c)。
typedef void redisCommandProc(redisClient *c);struct redisCommand { char *name; redisCommandProc *proc; int arity; .. long long microseconds, calls;};6.华丽的来到getCommand。
void getCommand(redisClient *c) { getGenericCommand(c);}int getGenericCommand(redisClient *c) { ... if (o->type != REDIS_STRING) { addReply(c,shared.wrongtypeerr); return REDIS_ERR; } else { addReplyBulk(c,o); return REDIS_OK; }}7.addReplyBulk。
void addReplyBulk(redisClient *c, robj *obj) { addReplyBulkLen(c,obj); addReply(c,obj); addReply(c,shared.crlf);}8.prepareClientToWrite:通过事件分离器转到写出操作:sendReplyToClient,。把c->buf的内容写到fd。
参考资料:
1.http://www.hoterran.info/redis_protocol <<>>
转载地址:http://mpqli.baihongyu.com/