Redis通信协议
Redis基于RESP(Redis Serialization Protocol)协议来完成客户端和服务端通信。RESP本质是一种文本协议,实现简单、易于解析。
啥?你不信?那好我们来抓包看一下吧,以单条命令为例子set name bigold ex 1。
| |
细心的大佬可能发现,哎?不对呀。为啥我在客户端不是这样的?
| |
那是因为客户端对其进行转化,才显示出来的,见redis-cli.c文件:
| |
这里我们可以使用nc命令,来代替redis-cli命令行:
| |
其他说明
- 常见的错误
12345678910111213141516171819#define REDIS_ERR -1#define REDIS_OK 0/* When an error occurs, the err flag in a context is set to hold the type of * error that occurred. REDIS_ERR_IO means there was an I/O error and you * should use the "errno" variable to find out what is wrong. * For other values, the "errstr" field will hold a description. */#define REDIS_ERR_IO 1 /* Error in read or write */#define REDIS_ERR_EOF 3 /* End of file */#define REDIS_ERR_PROTOCOL 4 /* Protocol error */#define REDIS_ERR_OOM 5 /* Out of memory */#define REDIS_ERR_OTHER 2 /* Everything else... */#define REDIS_REPLY_STRING 1#define REDIS_REPLY_ARRAY 2#define REDIS_REPLY_INTEGER 3#define REDIS_REPLY_NIL 4#define REDIS_REPLY_STATUS 5#define REDIS_REPLY_ERROR 6- 字符串错误信息——共享对象
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364void createSharedObjects(void) { int j; shared.crlf = createObject(OBJ_STRING,sdsnew("\r\n")); shared.ok = createObject(OBJ_STRING,sdsnew("+OK\r\n")); shared.err = createObject(OBJ_STRING,sdsnew("-ERR\r\n")); shared.emptybulk = createObject(OBJ_STRING,sdsnew("$0\r\n\r\n")); shared.czero = createObject(OBJ_STRING,sdsnew(":0\r\n")); shared.cone = createObject(OBJ_STRING,sdsnew(":1\r\n")); shared.cnegone = createObject(OBJ_STRING,sdsnew(":-1\r\n")); shared.nullbulk = createObject(OBJ_STRING,sdsnew("$-1\r\n")); shared.nullmultibulk = createObject(OBJ_STRING,sdsnew("*-1\r\n")); shared.emptymultibulk = createObject(OBJ_STRING,sdsnew("*0\r\n")); shared.pong = createObject(OBJ_STRING,sdsnew("+PONG\r\n")); shared.queued = createObject(OBJ_STRING,sdsnew("+QUEUED\r\n")); shared.emptyscan = createObject(OBJ_STRING,sdsnew("*2\r\n$1\r\n0\r\n*0\r\n")); shared.wrongtypeerr = createObject(OBJ_STRING,sdsnew( "-WRONGTYPE Operation against a key holding the wrong kind of value\r\n")); shared.nokeyerr = createObject(OBJ_STRING,sdsnew( "-ERR no such key\r\n")); shared.syntaxerr = createObject(OBJ_STRING,sdsnew( "-ERR syntax error\r\n")); shared.sameobjecterr = createObject(OBJ_STRING,sdsnew( "-ERR source and destination objects are the same\r\n")); shared.outofrangeerr = createObject(OBJ_STRING,sdsnew( "-ERR index out of range\r\n")); shared.noscripterr = createObject(OBJ_STRING,sdsnew( "-NOSCRIPT No matching script. Please use EVAL.\r\n")); shared.loadingerr = createObject(OBJ_STRING,sdsnew( "-LOADING Redis is loading the dataset in memory\r\n")); shared.slowscripterr = createObject(OBJ_STRING,sdsnew( "-BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.\r\n")); shared.masterdownerr = createObject(OBJ_STRING,sdsnew( "-MASTERDOWN Link with MASTER is down and replica-serve-stale-data is set to 'no'.\r\n")); shared.bgsaveerr = createObject(OBJ_STRING,sdsnew( "-MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-writes-on-bgsave-error option). Please check the Redis logs for details about the RDB error.\r\n")); shared.roslaveerr = createObject(OBJ_STRING,sdsnew( "-READONLY You can't write against a read only replica.\r\n")); shared.noautherr = createObject(OBJ_STRING,sdsnew( "-NOAUTH Authentication required.\r\n")); shared.oomerr = createObject(OBJ_STRING,sdsnew( "-OOM command not allowed when used memory > 'maxmemory'.\r\n")); shared.execaborterr = createObject(OBJ_STRING,sdsnew( "-EXECABORT Transaction discarded because of previous errors.\r\n")); shared.noreplicaserr = createObject(OBJ_STRING,sdsnew( "-NOREPLICAS Not enough good replicas to write.\r\n")); shared.busykeyerr = createObject(OBJ_STRING,sdsnew( "-BUSYKEY Target key name already exists.\r\n")); shared.space = createObject(OBJ_STRING,sdsnew(" ")); shared.colon = createObject(OBJ_STRING,sdsnew(":")); shared.plus = createObject(OBJ_STRING,sdsnew("+")); for (j = 0; j < PROTO_SHARED_SELECT_CMDS; j++) { char dictid_str[64]; int dictid_len; dictid_len = ll2string(dictid_str,sizeof(dictid_str),j); shared.select[j] = createObject(OBJ_STRING, sdscatprintf(sdsempty(), "*2\r\n$6\r\nSELECT\r\n$%d\r\n%s\r\n", dictid_len, dictid_str)); } ....}
Redis命令对象
Redis的命令使用的是redisCommand数据结构来管理的.
数据结构
| |
针对sflag标识,在这里引用《Redis设计与实现》中的一张图
flag记录的是flag值与sflag进行位运算的结果,见populateCommandTable函数
| |
具体命令太多,只给出如下几个:
| |
以set为例{“set”,setCommand,-3,”wm”,0,NULL,1,1,1,0,0}





