1.1 redis定义的客户端命令发送格式
标准命令发送协议:
Redis2.0版本的协议成为redis服务器目前的通信标准方式
redis客户端需要严格遵循这个规则
所有发送的参数都要是二进制安全的
*<参数数量> CR LF
$<参数 1 的字节数量> CR LF
<参数 1 的数据> CR LF
...
$<参数 N 的字节数量> CR LF
<参数 N 的数据> CR LF
发送的例子如下: <br />
这是一个set
操作命令,操作的值有三个
//整个命令的参数个数为3
*3
//第一个命令的字符长度为3
$3
//第一个命令的名称
SET
//第二个命令的字符长度为5
$5
//第二个命令的名称
mykey
//...
$7
myvalue
根据redis的命令传输协议
命令的实际传输协议值如下
`"*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nmyvalue\r\n"`
1.2 jedis命令发送协议
jedis作为redis的客户端也引用了redis的命令发送协议
对命令的发送进行标志
//多条命令中的单个命令
public static final byte DOLLAR_BYTE = '$';
//多条命令,后面跟行数
public static final byte ASTERISK_BYTE = '*';
//状态命令
public static final byte PLUS_BYTE = '+';
//错误状态命令
public static final byte MINUS_BYTE = '-';
//整数命令
public static final byte COLON_BYTE = ':';
于是在jedis中,遵循这样的规则进行命令的组装
private static void sendCommand(final RedisOutputStream os,
final byte[] command, final byte[]... args) {
try {
//写入批量命令标志符
os.write(ASTERISK_BYTE);
//写入总的命令个数 = 参数个数 + 1 (命令)
os.writeIntCrLf(args.length + 1);
//写入单个命令符
os.write(DOLLAR_BYTE);
//写入单个操作命令的字节数
os.writeIntCrLf(command.length);
//写入单个操作命令名称
os.write(command);
//写入 \r\n
os.writeCrLf();
for (final byte[] arg : args) {
//表示符 $,单个命令分割符
os.write(DOLLAR_BYTE);
//参数的字节数
os.writeIntCrLf(arg.length);
//参数名称
os.write(arg);
// 写入/r/n
os.writeCrLf();
}
} catch (IOException e) {
throw new JedisConnectionException(e);
}
}
1.3 redis-server的回应
以上是发送到服务器的协议内容
private static Object process(final RedisInputStream is) {
try {
byte b = is.readByte();
//返回的消息头为"-"
if (b == MINUS_BYTE) {
processError(is);
//返回的消息头为"*"处理单个命令指令
} else if (b == ASTERISK_BYTE) {
return processMultiBulkReply(is);
//返回的消息头为":"
} else if (b == COLON_BYTE) {
return processInteger(is);
//返回的消息头为"$"处理多命令指令
} else if (b == DOLLAR_BYTE) {
return processBulkReply(is);
//返回的消息头为"+"处理状态信息
} else if (b == PLUS_BYTE) {
return processStatusCodeReply(is);
//其他情况都是无法分析返回消息类型,Unknown reply
} else {
throw new JedisConnectionException("Unknown reply: " + (char) b);
}
} catch (IOException e) {
throw new JedisConnectionException(e);
}
return null;
}
这里对于读到的信息头分为以下几种情况
- 1
:
状态回复 - 2
-
错误信息回复 - 3
+
integer值回复 - 4
*
多消息回复 - 5
$
多消息回复里的单个命令