Redis 客户端与服务器之间的通讯使用的协议Redis Serialization Protocol,简称RESP。
insight jedis核心功能:RESP通信实现。
1. 通信实现 (redis.clients.jedis.Connection);
2. RESP协议实现 (redis.clients.jedis.Protocol, redis.clients.util.RedisOutputStream, redis.clients.util.RedisInputStream)
jedis 通信实现(典型的socket 编程template):
/**
* jedis执行命令的典型模板
* 1. check
* 2. send command
* 3. recive result
**/
public String set(final String key, String value) {
checkIsInMultiOrPipeline();
//
client.set(key, value);
return client.getStatusCodeReply();
}
// 客户端command + arguments 发送的实现
protected Connection sendCommand(final Command cmd, final byte[]... args) {
try {
// 主动check connection,兼容socket初始化过程,常用的做法
connect();
// 根据RESP,请求信息以字节码写入os
Protocol.sendCommand(outputStream, cmd, args);
pipelinedCommands++;
return this;
} catch (JedisConnectionException ex) {
// 即使报错,在断开连接前,得到server 的报错信息
// ...
// 关键标识
broken = true;
throw ex;
}
}
RESP协议实现
首先,了解协议内容: https://redis.io/topics/protocol#resp-protocol-description
特点: 实现简单、解析快速、可读性强。
然后,insight:
/**
* 典型的协议编码实现
*
* 支持的数据类型: Simple Strings, Errors, Integers, Bulk Strings and Arrays.
* 数据类型的表示:Simple Strings(+), Errors, Integers(:), Bulk Strings($) and Arrays(*)
* 不同的块之间一定要用CRLF间隔(\r\n)
**/
private static void sendCommand(final RedisOutputStream os, final byte[] command, final byte[]... args) {
try {
os.write(ASTERISK_BYTE);// * 我是数组
os.writeIntCrLf(args.length + 1);// 命令1 + 参数n
os.write(DOLLAR_BYTE);// $
os.writeIntCrLf(command.length);// 长度
os.write(command);// 操作命令
os.writeCrLf();// 间隔符号
for (final byte[] arg : args) {// 追加入参
os.write(DOLLAR_BYTE);
os.writeIntCrLf(arg.length);
os.write(arg);
os.writeCrLf();
}
} catch (IOException e) {
throw new JedisConnectionException(e);
}
}
总结:通信必用socket,jedis 简洁的实现RESP 协议完成与服务的通信,值得借鉴。
后续会Insight pool 的简单实用。