项目_仿Redis数据库的协议解析过程及命令的基本实现

本文介绍了一个仿Redis数据库的项目,详细讲解了Redis协议解析的过程,包括Redis与Memcached的区别、支持的数据类型。接着阐述了lpush、lrange、hset、hget命令的实现,涉及数据类型、命令解析和返回结果的处理。文章还提到了项目的使用手册、改进点以及测试方面的功能性与性能测试。
摘要由CSDN通过智能技术生成

Redis是一款数据跑在内存上的数据库


项目源码:我的github链接,仅供参考哦!


一、认识Redis

我们常用的是MySQL或者SqlServer数据库。接入层(http服务器)直接操作数据库,整体服务效率较低,因为数据库的内容主要在磁盘上。

我们引入Redis的理由也就是希望能够更快的访问到数据,提高效率。就像以下场景一样:

热加载:把热点数据提前加载到内存中,提升整体的访问速度。
缓存模型:把热点数据提前加载到读写速度更快的介质中。

我们在有缓存的前提下,为什么要引入redis或者memcached呢?

可以使用缓存,但是没必要。自己做缓存成本较高。

Tips:Redis和memcached是分布式缓存

1. Redis vs Memcached
  1. redis支持的数据结构丰富,memcached只支持key-value型的数据结构
  2. redis支持的社区更友好
  3. redis效率很高,Redis重启后数据还在,本身自带持久化。
  4. 是属于IT界的跟风???
2. Redis支持的类型
类型 返回值 Java中的类型 标记字节 格式说明
Simple String 返回OK String ‘+’ ‘+OK\r\n’
Error 通知出错 Exception ‘-’ '-ERR unknown command ‘put’\r\n
Integer 整数 long ‘:’ ':0\r\n
Bulk String 字节流 byte[] ‘$’ '$5\r\nhello\r\n
Array 数组 List ‘*’ '*2\r\n:0\r\n$5\r\nhello\r\n
Redis和Java语言的类型对应起来就需要"协议解析"
如将‘+OK\r\n’变为'OK'的过程,其他类型也是一样的道理。

二、协议解析

服务器接收到客户端发来的输入流,经过了协议解析,收到的实际上是带标记字节的字符串列表,因此我们可以根据标记字节解析出客户端输入的是哪一类型的Redis指令。

一般来说Redis命令传过来都是数组类型,即Java中的List;以*标记字节开头的输入流。
如“+OK\r\n”,判断为String类型。最后的返回结果应该为OK。
每个字符串的结尾都为\r\n,因此在readLine()方法中,一旦我们读到最后的\r\n,就将\r\n前(除了标记字节)的字符串返回。
所以,如果不是末尾的\r,就要加上转义符(\\r),否则\r返回到行首,就会将前面的字符串覆盖。

这里涉及到状态转换机:

其他字符-> \r -> \n->结束。
如果其他字符遇到\r,则判断\r的下一个字符是否为\n。如果下一个为\n,则结束;如果为\r,则继续判断当前\r的下一个字符是否为\n;如果是其他字符,拼接字符串即可,继续判断其他字符的下一个字符。

ProtocolInputStream 类

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

public class ProtocolInputStream extends FilterInputStream {
   

    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) {
   
                b= in.read();
                if (b == -1) {
   
                    throw new RuntimeException("不应该读到结尾的");
                }
            }else {
   
                needRead = true;
            }

            // +OK\r3\r\n -> 结果:
            // 3
            //

            // +OK\\r3\r\n -> 结果:
            // OK\r3
            //
            //如果末尾\r\n前存在\r,需要加上转义符\。
            //否则,\r后面的字符会覆盖前面的字符,产生数据覆盖的情况。

            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 {
   
    	/*
        如果读到的第二个字符为-,则为负数,标记isNegative为true。
        如果不是-,就拼接字符b
        继续读剩下的字符,如果是\r\n,则跳出循环,结束。
        如果不是\r,就拼接字符b。继续循环,直到符合跳出条件(到达末尾的\r\n)。

        最后将读到的数字字符串转为long型整数。如果是负数,v = -v。
        最终返回v即可。
  
        * */
        boolean isNegative = false;
        StringBuilder sb = new StringBuilder();
        int b = in.read();
        if (b == -
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值