Redis Resp协议

一、Redis

  • Redis是一个开源(BSD许可),内存数据结构存储,用作数据库,缓存和消息代理。 它支持数据结构,如字符串,散列,列表,集合,带有范围查询的排序集,位图,超级日志,具有半径查询和流的地理空间索引。 Redis具有内置复制,Lua脚本,LRU驱逐,事务和不同级别的磁盘持久性,并通过Redis Sentinel提供高可用性并使用Redis Cluster自动分区。

二、RESP协议(Redis 序列化协议):

2.1 Redis client和Redis server之间的通信协议,也是Redis快速的原因之一,RESP协议

有如下特点:

resp有下面 的特点:
    1.实现简单
    2.解析快速
    3.人类可读

2.2 协议格式

  • java代码:jedis.set("name ", "mozping "); 对应的命令是set name mozping ,协议解析如下:
*3  //请求参数个数
$3  //第一个参数的字符长度
SET //第一个参数
$4  //第二个参数的字符长度
name //第二个参数
$7  //第三个参数的字符长度
mozping  //第三个参数

三、服务端观察协议

3.1 先启动伪Redis Server端

    public static void main(String[] args) throws Exception {
            ServerSocket serverSocket = new ServerSocket(6379);
            Socket socket = serverSocket.accept();
            InputStream inputStream = socket.getInputStream();
            byte[] b = new byte[64];
            inputStream.read(b);
            int a = 0;
            for (byte c : b) {
                System.out.print(c);
                System.out.print(" ");
                a++;
                if (a == 16) {
                    a = 0;
                    System.out.println();
                }
            }
            System.out.println("\n");
            System.out.println(new String(b));
        }

3.2 再启动redis client端

public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1",6379);
        jedis.set("name","mozping");
    }

3.3 检查server端打印

42 51 13 10 36 51 13 10 83 69 84 13 10 36 52 13 
10 110 97 109 101 13 10 36 55 13 10 109 111 122 112 105 
110 103 13 10 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 

3.4 解析

3.3中的数字是原始的数组打印,这里对照ascii码表可知,42 51是*3 ,13 10是CR LF 也就是回车
和换行后面的36 51是$3,然后13 10又是回车换行,因此我们看到这样的协议定义比较简单,计算
机解析速度会比较快,且具备比较好的可读性。
42 51 13 10 36 51 13 10 83 69 84 13 10 36 52 13 10 110 97 109 101 13 10 36 55 13 10 109 111 122 112 105 110 103 13 10
*  3  CR LF $  3  CR LF S  E  T  CR LF $  4  CR LF  n  a   m  e   CR LF $  7  CR LF  m  o   z   p    i   n   g  CR LF

3.5 打印对应的ASCII码

*3       
$3       
SET     
$4       
name     
$7       
mozping  

四、客户端观察协议

4.1 客户端代码

    public static void main(String[] args) {
        Jedis jedis = new Jedis("192.168.11.199");
        jedis.set("foo", "bar123");
        String value = jedis.get("foo");
        System.out.println(value);
    }

4.2 断点调试

  • jedis依赖

            redis.clients
            jedis
            3.0
  
  • redis.clients.jedis.Protocol#sendCommand
 /**
   * RESP协议:
   * *3
   * $3
   * SET
   * $4
   * foo
   * $7
   * bar123
   * */
  private static void sendCommand(final RedisOutputStream os, final byte[] command,
      final byte[]... args) {
    try {
      //'*'字符
      os.write(ASTERISK_BYTE);
      //参数总长度,这里是3
      os.writeIntCrLf(args.length + 1);
      //'$'字符
      os.write(DOLLAR_BYTE);
      //命令长度,如果是SET命令,就是3
      os.writeIntCrLf(command.length);
      //写入命令,比如SET
      os.write(command);
      //回车换行\r\n
      os.writeCrLf();
      //上面几行代码把RESP协议的操作命令部分写完了,下面开始写操作的key-value部分
      
      //遍历value
      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);
    }
  }

五、小结

  • 由以上的服务端调试我们看到了服务端拿到的就是客户端发送的字符的ASCII编码,客户端就是按照RESP这个简单的协议规则发送的。

你可能感兴趣的:(Redis和缓存)