redis 协议介绍与应用

本文深入探讨了Redis协议中支持的各种数据类型,包括简单的字符串、错误消息、整数、批量字符串和数组。通过具体的Java代码示例,展示了如何解析这些不同类型的数据,并提供了完整的程序实现,帮助读者理解Redis协议的底层工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

redis协议支持的数据类型:

相关程序:

一、Protocol

import java.io.IOException;
import java.io.InputStream;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;

public class Protocol {
    private static String processSimpleString(ProtocolInputStream is) throws IOException {
        return is.readLine();
    }

    private static String processError(ProtocolInputStream is) throws IOException {
        return is.readLine();
    }

    private static long processInteger(ProtocolInputStream is) throws IOException {
        return is.readInteger();
    }

    private static byte[] processBulkString(ProtocolInputStream is) throws IOException {
        int len = (int)is.readInteger();
        if (len == -1) {
            // "$-1\r\n"    ==> null
            return null;
        }

        byte[] r = new byte[len];
        for (int i = 0; i < len; i++) {
            int b = is.read();
            r[i] = (byte)b;
        }

        // "$5\r\nhello\r\n";
        is.read();
        is.read();

        return r;
    }

    private static List<Object> processArray(ProtocolInputStream is) throws IOException {
        int len = (int)is.readInteger();
        if (len == -1) {
            // "*-1\r\n"        ==> null
            return null;
        }

        List<Object> list = new ArrayList<>(len);
        for (int i = 0; i < len; i++) {
            try {
                list.add(process(is));
            } catch (RemoteException e) {
                list.add(e);
            }
        }

        return list;
    }

    public static Object read(ProtocolInputStream is) throws IOException {
        return process(is);
    }
    private static Object process(ProtocolInputStream is) throws IOException {
        int b = is.read();
        if (b == -1) {
            throw new RuntimeException("不应该读到结尾的");
        }

        switch (b) {
            case '+':
                return processSimpleString(is);
            case '-':
                throw new RemoteException(processError(is));
            case ':':
                return processInteger(is);
            case '$':
                return processBulkString(is);
            case '*':
                return processArray(is);
            default:
                throw new RuntimeException("不识别的类型");
        }
    }
}

二、Main

import com.sun.xml.internal.messaging.saaj.util.ByteInputStream;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) throws IOException {
        //InputStream is = System.in;
        //String message = "+OK";
        //String message = "-ERR unknown command 'put'\r\n";
        //String message = ":-100\r\n";
        //String message = "$5\r\nhello\r\n";
        String message = "*5\r\n$5\r\nlpush\r\n$3\r\nkey\r\n$1\r\n1\r\n$1\r\n2\r\n$1\r\n3\r\n";
        ByteInputStream is = new ByteInputStream(message.getBytes(), message.getBytes().length);

        List<byte[]> list = (List<byte[]>)Protocol.read(new ProtocolInputStream(is));
        for (byte[] b : list) {
            System.out.println(new String(b));
        }
    }
}

三、ProtocolInputStream 

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

public class ProtocolInputStream extends FilterInputStream {
    /**
     * Creates a <code>FilterInputStream</code>
     * by assigning the  argument <code>in</code>
     * to the field <code>this.in</code> so as
     * to remember it for later use.
     *
     * @param in the underlying input stream, or <code>null</code> if
     *           this instance is to be created without an underlying stream.
     */
    public ProtocolInputStream(InputStream in) {
        super(in);
    }

    public String readLine() throws IOException {
        boolean needRead = true;
        StringBuilder sb = new StringBuilder();
        int b = -1;
        while (true) {
            if (needRead == true) {
                b = in.read();
                if (b == -1) {
                    throw new RuntimeException("不应该读到结尾的");
                }
            } else {
                needRead = true;
            }

            if (b == '\r') {
                int c = in.read();
                if (c == -1) {
                    throw new RuntimeException("不应该读到结尾的");
                }

                if (c == '\n') {
                    break;
                }

                if (c == '\r') {
                    sb.append((char) b);
                    b = c;
                    needRead = false;
                } else {
                    sb.append((char) b);
                    sb.append((char) c);
                }
            } else {
                sb.append((char)b);
            }
        }
        return sb.toString();
    }

    public long readInteger() throws IOException {
        boolean isNegative = false;
        StringBuilder sb = new StringBuilder();
        int b = in.read();
        if (b == -1) {
            throw new RuntimeException("不应该读到结尾");
        }

        if (b == '-') {
            isNegative = true;
        } else {
            sb.append((char)b);
        }

        while (true) {
            b = in.read();
            if (b == -1) {
                throw new RuntimeException("不应该读到结尾的");
            }

            if (b == '\r') {
                int c = in.read();
                if (c == -1) {
                    throw new RuntimeException("不应该读到结尾的");
                }

                if (c == '\n') {
                    break;
                }

                throw new RuntimeException("没有读到\\r\\n");
            } else {
                sb.append((char)b);
            }
        }

        long v = Long.parseLong(sb.toString());
        if (isNegative) {
            v = -v;
        }

        return v;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值