通信协议
Redis监听默认6379的端口号,可以通过TCP方式建立连接。
服务端约定了一种特殊的消息格式,每个命令都是以rn(CRLF回车+换行)结尾。这种编码格式我们之前在AOF文件里面见到了,叫做Redis Serialization Protocol(RESP,Redis序列化协议),发消息或者响应消息需要按这种格式编码,接收消息需要按这种格式解码。Redis设计这种格式的原因:容易实现、解析快、可读性强。Redis6.0新特性里面说的RESP协议升级到了3.0版本,其实就是对于服务端和客户端可以接收的消息进行了升级扩展,比如客户端缓存的功能就是在这个版本里面实现的。
我们来看下这种编码格式实际内容是什么。使用wireshark对jedis抓包:
执行一个set请求(set qingshan 2673):
可以看到实际发出的数据包是:
其实就是把他们的长度命令、命令和参数用\r\n连接起来。
我们也可以自己实现一个Redis的Java客户端。
public class MyClient {
private Socket socket;
private OutputStream write;
private InputStream read;
public MyClient(String host, int port) throws IOException {
socket = new Socket(host, port);
write = socket.getOutputStream();
read = socket.getInputStream();
}
/**
* 实现了set方法
* @param key
* @param val
* @throws IOException
*/
public void set(String key, String val) throws IOException {
StringBuffer sb = new StringBuffer();
// 代表3个参数(set key value)
sb.append("*3").append("\r\n");
// 第一个参数(set)的长度
sb.append("$3").append("\r\n");
// 第一个参数的内容
sb.append("SET").append("\r\n");
// 第二个参数key的长度(不定,动态获取)
sb.append("$").append(key.getBytes().length).append("\r\n");
// 第二个参数key的内容
sb.append(key).append("\r\n");
// 第三个参数value的长度(不定,动态获取)
sb.append("$").append(val.getBytes().length).append("\r\n");
// 第三个参数value的内容
sb.append(val).append("\r\n");
// 发送命令
write.write(sb.toString().getBytes());
byte[] bytes = new byte[1024];
// 接收响应
read.read(bytes);
System.out.println("-------------set-------------");
System.out.println(new String(bytes));
}
/**
* 实现了get方法
* @param key
* @throws IOException
*/
public void get(String key) throws IOException {
StringBuffer sb = new StringBuffer();
// 代表2个参数
sb.append("*2").append("\r\n");
// 第一个参数(get)的长度
sb.append("$3").append("\r\n");
// 第一个参数的内容
sb.append("GET").append("\r\n");
// 第二个参数key的长度
sb.append("$").append(key.getBytes().length).append("\r\n");
// 第二个参数内容
sb.append(key).append("\r\n");
write.write(sb.toString().getBytes());
byte[] bytes = new byte[1024];
read.read(bytes);
System.out.println("-------------get-------------");
System.out.println(new String(bytes));
}
public static void main(String[] args) throws IOException {
MyClient client = new MyClient("192.168.44.181", 6379);
client.set("shihui", "2673");
client.get("shihui");
}
}
使用这种协议,我们可以用Java实现所有的Redis操作命令。
官网推荐的Java客户端有3个:Jedis,Redisson和Luttuce.
Spring操作Redis提供了一个模板方法,RedisTemplate。这并不是Spring实现了一个Redis的客户端,实际上是Spring定义了一个连接工厂接口:RedisConnectionFactory。这个接口有很多实现,例如:JedisConnectionFactory、JredisConnectionFactory、LettuceConnectionFactory、SrpConnectionFactory。也就是说,RedisTemplate对其他现成的客户端再进行了一层封装而已。在Spring Boot 2.x版本之前,RedisTemplate默认使用Jedis,2.x版本之后,默认使用Lettuce.。
https://github.com/redis/jedis/
如果不用RedisTemplate,就可以直接创建Jedis的连接。
public class BasicTest {
public static void main(String[] args) {
Jedis jedis = new Jedis("这个参数是ip地址", 6379);
jedis.set("shihui", "2673jedis");
System.out.println(jedis.get("shihui"));