前言
最近研究下redis源码,现在从最基本的命令行操作来分析,redis是如何处理命令操作的
1. redis的set命令操作
我们在redis-cli执行下面的命令
set c c
debug 发现 t_string.c ,执行了 void setCommand(client *c)
其中 client 的定义,client 有非常多的参数,现在我们比较关心的是 querybuf 参数
typedef struct client {
....
sds querybuf; /* 请求参数 */
} redisClient;
2. 命令解析
redis-cli 客户端执行 set c c 命令后,redis服务会保存到 client的querybuf 字段里面,数据封装成 "*3\r\n$3\r\nset\r\n$1\r\nc\r\n$1\r\nc\r\n"
其中 *3 表示 有3个数据, \r\n 作为分隔符
$3 代表 第一个参数有3个字节数目,就是 set
$1 代表 第二个参数c
3.解析好参数后,最后调用 setGenericCommand
继续debug ,发现 key 和value 都会保存成 robj对象,
robj 定义
typedef struct redisObject { // 类型 (包含 字符串,int 等等) unsigned type: 4; // 编码 unsigned encoding: 4; int refcount; void *ptr;//字符串地址(通过不同的类型,保存了不同的指针对象) } robj;
验证下,是不是我们刚才提交的 set c c ,其中 key 是 c value 也是 c
打印一下,果然是我们输入的参数,
继续 debug,先 lookupKeyWrite 查找key是否存在,然后 setKey 写入redis的hashtable中,最后发送通知,写入回复 reply
总结
- set 命令是在 t_string.c 文件的 setCommand函数处理的
- key和value 会包装成 robj 对象
- 判断是否有过期时间,有的话,会处理 expire ,其中 setExpire 会处理过期时间
- setKey函数会写入redis的hashtable中
- 调用 notifyKeyspaceEvent 事件通知
- 调用 addReply方法,写入回复到客户端