设为首页 加入收藏

TOP

用Java写一个分布式缓存——RESP服务端(一)
2023-07-26 08:17:08 】 浏览:131
Tags:Java RESP

前言

本篇我们将完成一个RESP的socket的服务端,初步完成一个单机版缓存。

另外在其中我们还需要完成命令的动态路由

源码:https://github.com/weloe/Java-Distributed-Cache

本篇代码:

https://github.com/weloe/Java-Distributed-Cache/tree/master/src/main/java/com/weloe/cache/server

上篇:缓存管理 https://www.cnblogs.com/weloe/p/17068891.html

RESP协议

RESP协议支持5种数据类型:字符串,异常,整数,多行字符串,数组

数据类型由第一个字节进行区分,不同部分使用\r\n来分开

  • '+' : 简单字符串
  • '-' : 异常
  • ':' : 整数
  • '$': 多行字符串
  • '*': 数组

简单字符串一般用来返回该操作无误,操作成功,例如返回+ok\r\n

异常: -error msg\r\n

整数:: 1\r\n

多行字符串:

$4\r\n
test

这里的4是实际数据的长度

实际信息为 test

数组:

*2\r\n
$2\r\n
ab\r\n
$3\r\n
cde\r\n

信息为字符串数组[ab][cde]

实现

https://github.com/weloe/Java-Distributed-Cache/blob/master/src/main/java/com/weloe/cache/util/RESPUtil.java

根据协议我们就能编写出对请求信息的解析类了,我们把它抽象为一个工具类

对返回内容解析的代码

	/**
     * 读取RESP协议的字节,转为String
     *
     * @return String
     */
    public static String parseRESPBytes(InputStream inputStream) {
        byte[] bytes;

        String result = null;
        try {
            while (inputStream.available() == 0) {
            }
            bytes = new byte[inputStream.available()];
            inputStream.read(bytes);
            result = new String(bytes);

        } catch (IOException e) {
            e.printStackTrace();
        }

        return result;
    }

    /**
     * 解析RESP协议的String
     *
     * @param raw
     * @return
     */
    public static Object parseRESPString(String raw) {
        byte type = raw.getBytes()[0];
        String result = raw.substring(1);
        switch (type) {
            case '+':
                // +ok\r\n
                // 读单行
                return result.replace("\r\n", "");
            case '-':
                // 异常
                // -Error msg\r\n
                throw new RuntimeException(result.replace("\r\n", ""));
            case ':':
                // 数字
                return result.replace("\r\n", "");
            case '$':
                return result.split("\r\n")[1];
            case '*':
                // 多行字符串
                String[] strList = result.substring(result.indexOf("$")).split("\r\n");
                System.out.print("多条批量请求:");
                List<String> list = new LinkedList<>();
                for (int i = 1; i < strList.length; i += 2) {
                    System.out.print(strList[i] + " ");
                    list.add(strList[i]);
                }
                System.out.println();
                return list;
            default:
                throw new RuntimeException("错误的数据格式");
        }
    }

发送请求的代码

    /**
     * 发送RESP请求
     * @param host
     * @param port
     * @param args
     * @return
     * @throws IOException
     */
    public static byte[] sendRequest(String host,Integer port, String ... args) throws IOException {
        Socket socket = new Socket(host,port);
        RESPRequest request = new RESPRequest(socket);
        PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8));
        sendRequest(writer,args);

        byte[] param = request.getBytes();

        request.close();
        writer.close();
        socket.close();
        return param;
    }

    /**
     * 发送RESP请求
     * @param writer
     * @param args
     * @throws IOException
     */
    public static void sendRequest(PrintWriter writer, String ... args) throws IOException {
        writer.println("*"+args.length);
        for (String arg : args) {
            writer.println("$"+arg.getBytes(StandardCharsets.UTF_8).length);
            writer.println(arg);
        }
        writer.flush();
    }

命令的解析

通过RESP协议的实现,我们就能做到对我们的缓存发送命令,那么我们又该怎么对命令进行解析,然后做出对应的操作呢?

这里我们使用前缀树结构来进行动态路由

Node

https://github.com/weloe/Java-Distributed-Cache/blob/master/src/main/java/com/weloe/cache/server/parser/Node.java

首先要构建树的节点

需要注意的是只有叶子节点才有pattern

isWild来判断是否有通配符则是为了来匹配用户输入的参数,我们设置路由的时候用:作为通配符

例如设置路由set :group :k :v

首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/8/8
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇ChatGPT国内也能用吗?ChatGPT国.. 下一篇《分布式技术原理与算法解析》学..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目