Redis通信协议

文章目录

  • Redis通信协议
    • RESP协议
      • 数据类型
    • 模拟Redis客户端

Redis通信协议

RESP协议

Redis是一个CS架构的软件,通信一般分为两步(不包含pipeline和PubSub):

  1. 客户端(client)向服务端(server)发送一条命令。
  2. 服务器解析并执行命令,返回响应结果到客户端。

因此,客户端发送命令好服务端响应结果的格式需要有一个规范(否则便无法正常通信),这个规范便是通信协议。

在Redis中采用的是RESP协议:

  • Redis1.2版本引入RESP协议。
  • Redis2.0版本中称为Redis服务通信的标准,成为REST2。
  • Redis6.0版本中,从RESP2升级到RESP3协议,增加了更多数据类型并且支持6.0的新特性(客户端缓存)。

但目前默认使用的依旧是RESP2协议,

数据类型

在RESP中,通过首字节的字符来区分不同数据类型,常用的数据类型包括5种:

  • 单行字符串:首字节是 ‘+’ ,后面跟上单行字符串,以CRLF( “\r\n” )结尾。例如返回"OK": “+OK\r\n”。

  • 错误(Errors):首字节是 ‘-’ ,与单行字符串格式一样,只是字符串是异常信息,例如:“-Error message\r\n”。

  • 数值:首字节是 ‘:’ ,后面跟上数字格式的字符串,以CRLF结尾。例如:“:10\r\n”。

  • 多行字符串:首字节是 ‘$’ ,表示二进制安全的字符串,最大支持512MB:

    image-20230604110955872

    • 如果大小为0,则代表空字符串:“$0\r\n\r\n”。
    • 如果大小为-1,则代表不存在:“$-1\r\n”
  • 数组:首字节是 ‘*****’,后面跟上数组元素个数,再跟上元素,元素数据类型不限:

    image-20230604111126867


模拟Redis客户端

Redis支持TCP通信,这里边使用Socket模拟客户端与Redis建立连接

public static void  RedisRequest(String address,String password,String...request) {Socket socket = null;PrintWriter writer = null;BufferedReader reader = null;try {// 1. 建立连接String host = address.substring(0,address.indexOf(":")); // redis的所在ip地址int port = Integer.parseInt(address.substring(address.indexOf(":") + 1)); //redis的端口号(默认6379)socket = new Socket(host, port);// 2. 获取输出流、输入流writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8));reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));// 获取授权(登录)if(password!=null && !"".equals(password)){sendRequest(writer,"auth "+password);}// 3. 发出请求 set name xiaomingsendRequest(writer,request);// 4. 解析响应(多次解析)for(int i = 0;i<request.length;i++){Object obj = handleResponse(reader);System.out.println(obj);}} catch (IOException e) {e.printStackTrace();} finally {// 5. 释放连接if(reader !=null){try {reader.close();} catch (IOException e) {e.printStackTrace();}}if(writer!=null){writer.close();}if(socket!=null){try {socket.close();} catch (IOException e) {e.printStackTrace();}}}
}

发送一条set命令和一条get命令(set name xiaoming , get name)

private static void sendRequest (PrintWriter writer,String...request) {String[][] req = new String[request.length][];for(int i = 0;i<request.length;i++){req[i] = request[i].split(" ");}for (String[] strings : req) {int n = strings.length;writer.println("*" + n);for (String s : strings) {writer.println("$" + s.getBytes(StandardCharsets.UTF_8).length);writer.println(s);}writer.flush();}
}

根据响应的类型来读取响应结果

private static Object handleResponse (BufferedReader reader) {// 读取首字节int prefix  = 0;try {prefix = reader.read();} catch (IOException e) {e.printStackTrace();}try {// 判断数据类型标示switch (prefix) {case '+' -> {  // 单行字符串,直接读一行return reader.readLine();}case '-' -> // 异常,读一行throw new RuntimeException(reader.readLine());case ':' -> { // 数字return Long.parseLong(reader.readLine());}case '$' -> { // 多行字符串// 读长度int len = Integer.parseInt(reader.readLine());if (len == -1) {return null;} else if (len == 0) {return "";}//读数据(这里使用的是字符流,直接读一行)return reader.readLine();}case '*' -> {return readbulkString(reader);}default -> throw new RuntimeException("错误的数据格式!");}} catch (IOException e) {e.printStackTrace();}return null;
}private static Object readbulkString (BufferedReader reader) {// 获取数据大小int len = 0;try {len = Integer.parseInt(reader.readLine());} catch (IOException e) {e.printStackTrace();}if(len <= 0){return null;}// 接收多个元素List<Object> list = new ArrayList<>(len);// 遍历,依次获取每个元素for(int i = 0;i < len;i++){list.add(handleResponse(reader));}return list;
}

使用单元测试方法,测试发送请求和接收响应

@Test
public void test(){Main.RedisRequest("192.168.45.138:6379",null,"set name xiaoming","get name");
}

测试结果为:

image-20230604160430155

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/84367.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【DETR】3、Conditional DETR | 拆分 content 和 spatial 来实现对 DETR 的加速

文章目录 一、Conditional DETR 是怎么被提出来的二、Conditional DETR 的具体实现2.1 框架结构2.2 DETR 的 cross-attention 和 Conditional DETR 的 cross-attention 对比 三、效果 论文&#xff1a;Conditional DETR for Fast Training Convergence 代码&#xff1a;https:…

c++ qt--事件过滤(第七部分)

c qt–事件过滤&#xff08;第七部分&#xff09; 一.为什么要用事件过滤 上一篇博客中我们用到了事件来进行一些更加细致的操作&#xff0c;如监控鼠标的按下与抬起&#xff0c;但是我们发现如果有很多的组件那每个组件都要创建一个类&#xff0c;这样就显得很麻烦&#xff…

springboot源码编译问题

问题一 Could not find artifact org.springframework.boot:spring-boot-starter-parent:pom:2.2.5.RELEASE in nexus-aliyun (http://maven.aliyun.com/nexus/content/groups/public/) 意思是无法在阿里云的镜像仓库中找到资源 解决&#xff1a;将配置的镜像删除即可&#…

我的128天创作纪念日-东离与糖宝

文章目录 机缘收获日常成就憧憬 不知不觉我也迎来了自己的128天创作纪念日&#xff0c;一起来看看我有什么想对大家说的吧 机缘 我的写博客之旅始于参加了代码随想录算法训练营。在训练营期间&#xff0c;代码随想录作者卡尔建议我们坚持每天写博客记录刷题学习的进度和心得体…

Vue3.0 新特性以及使用变更总结

Vue3.0 在2020年9月正式发布了&#xff0c;也有许多小伙伴都热情的拥抱Vue3.0。去年年底我们新项目使用Vue3.0来开发&#xff0c;这篇文章就是在使用后的一个总结&#xff0c; 包含Vue3新特性的使用以及一些用法上的变更。 图片.png 为什么要升级Vue3 使用Vue2.x的小伙伴都熟悉…

【Qt学习】02:信号和槽机制

信号和槽机制 OVERVIEW 信号和槽机制一、系统自带信号与槽二、自定义信号与槽1.基本使用student.cppteacher.cppwidget.cppmain.cpp 2.信号与槽重载student.cppteacher.cppwidget.cppmain.cpp 3.信号连接信号4.Lambda表达式5.信号与槽总结 信号槽机制是 Qt 框架引以为豪的机制之…

记录一个诡异的bug

将对接oa跳转到会议转写的项目oa/meetingtranslate项目发布到天宫&#xff0c;结果跳转到successPage后报错 这一看就是successPage接口名没对上啊&#xff0c;查了一下代码&#xff0c;没问题啊。 小心起见&#xff0c;我就把successPage的方法请求方式从Post改为Get和POST都…

司徒理财:8.21黄金空头呈阶梯下移!今日操作策略

黄金走势分析 盘面裸k分析&#xff1a;1小时周期的行情局部于1896附近即下行通道上轨附近录得一系列的K线呈震荡下行并筑圆顶&#xff0c;上轨压制有效&#xff0c;下行通道并未突破&#xff0c;后市建议延续看下行。4小时周期局部录得一系列的纺锤线呈震荡&#xff0c;但行情整…

元矿山下的音视频应用

// 近年来&#xff0c;矿业的技术和管理模式随着元宇宙的火爆和自动驾驶技术的发展逐渐变化、升级&#xff0c;进而衍生出元矿山的概念&#xff0c;音视频技术也在其中成为了关键一环。LiveVideoStackCon 2023 上海站邀请了来自希迪智驾的任思亮&#xff0c;为大家分享希迪智…

STM32 BOOT 启动配置 ISP升级 介绍

启动配置 在STM32F10xxx里&#xff0c;可以通过BOOT[1:0]引脚选择三种不同启动模式。 启动模式选择引脚启动模式说明BOOT1BOOT0X0主闪存存储器主闪存存储器被选为启动区域01系统存储器系统存储器被选为启动区域11内置SRAM内置SRAM被选为启动区域 在系统复位后&#xff0c; S…

Linux学习之Ubuntu 20中OpenResty的nginx目录里内容和配置文件

参考的文章是《nginx配置详解》 可以参考我以前的文章安装OpenResty。 cd /usr/local/openresty切换目录&#xff0c;ls -l查看目录里边的内容。 我的系统中&#xff0c;nginx目录是/usr/local/openresty/nginx&#xff0c;在这个目录里边有一些目录&#xff0c;如下&#xff…

电商版面设计之首页设计

首页设计资料 1、首页----多看大美工 2、手表首页 3、水密码官方旗舰店 4、AK男装 5、百雀羚首页设计 6、活动专区 7、店铺有一些活动&#xff0c;会在里面进行体现 8、提前构思&#xff0c;多看别人的店铺设计&#xff0c;是提升自己店铺设计最好的方法 9、产品专区 10、买一送…