【redis知识点整理】 --- RESP协议 + 手写一个简单的redis客户端

RESP协议官网:https://redis.io/topics/protocol
RESP协议中文官网:http://www.redis.cn/topics/protocol.html
本文代码对应的github地址:https://github.com/nieandsun/redis-study



1 RESP协议简介

RESP( REdis Serialization Protocol) 是Redis客户端与Redis服务器间进行通讯的协议。其主要特点如下:

  • 容易实现
  • 解析快
  • 人类可读

RESP 底层采用的是 TCP 的连接方式, 通过 tcp 进行数据传输, 然后根据解析规则解析相应信息, 完成交互。

我们可以测试下, 首先运行一个 serverSocket 监听 6379, 来接收 redis 客户端的请求信息, 实现如下:

//模拟redis服务器
public class ServerRedis {
    public static void main(String[] args) {
        try {
            //监听6379端口
            ServerSocket serverSocket = new ServerSocket(6379);
            Socket rec = serverSocket.accept();
            byte[] result = new byte[2048];
            rec.getInputStream().read(result);
            System.out.println(new String(result));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

再通过redis的客户端jedis给6379端口发送请求:

public class ClientRedis {

    /***
     * 使用redis客户端jedis给6379端口发送消息
     * @param args
     */
    public static void main(String[] args) {

        Jedis jedis = new Jedis("127.0.0.1", 6379);
        jedis.set("name", "lisonLength");
        jedis.close();
    }
}

测试发现,服务端打印的信息如下:
在这里插入图片描述
这就是Resp协议的结构 — 》 AOF存储的就是这些命令,有兴趣的可以回看一下我的文章《【redis知识点整理】 — Redis的持久化》。


2 自己手写一个简单的redis客户端

1中可以看到,其实Jedis就是将我们的key 和 Value拼装成满足RESP协议的字符串通过Socket发送给了Redis服务器来完成与Redis服务器的交互。

这时候我们肯定会想,假如我们自己按照RESP的规范,拼装一个字符串,然后通过Socket发送给redis服务器,能不能完成存储和查询呢???

其实是可以的,举例如下:

package com.nrsc.redis.learning.resp;

import java.io.IOException;
import java.net.Socket;

public class SelfRedisClient {
    /*
    *3
    $3
    SET
    $4
    name
    $6
    rehash
     */
    public static String set(Socket socket, String key, String value) throws IOException {
        //按照RESP协议拼接字符串
        StringBuffer str = new StringBuffer();
        str.append("*3").append("\r\n");
        str.append("$3").append("\r\n");
        str.append("SET").append("\r\n");
        str.append("$").append(key.getBytes().length).append("\r\n");
        str.append(key).append("\r\n");
        str.append("$").append(value.getBytes().length).append("\r\n");
        str.append(value).append("\r\n");

        socket.getOutputStream().write(str.toString().getBytes());
        byte[] response = new byte[2048];
        socket.getInputStream().read(response);
        return new String(response);

    }

    /*
    *2
    $3
    GET
    $4
    name
     */
    public static String get(Socket socket, String key) throws IOException {
        //按照RESP协议拼接字符串
        StringBuffer str = new StringBuffer();
        str.append("*2").append("\r\n");
        str.append("$3").append("\r\n");
        str.append("GET").append("\r\n");
        str.append("$").append(key.getBytes().length).append("\r\n");
        str.append(key).append("\r\n");
        socket.getOutputStream().write(str.toString().getBytes());
        byte[] response = new byte[2048];
        socket.getInputStream().read(response);
        return new String(response);
    }

    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 6379);
        String set = set(socket, "shaka", "loveStus");
        System.out.println(set);
        System.out.println(get(socket, "shaka"));
    }
}

测试结果如下,可以看到用我们自己写的客户端确实可以与redis服务器进行交互,完成存储和读取数据。
在这里插入图片描述


end!!!

猜你喜欢

转载自blog.csdn.net/nrsc272420199/article/details/106448856
今日推荐