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.rhkb.cn/news/107100.html

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

相关文章

远程调试环境配置

远程调试环境配置 前期准备ssh连接 前期准备 安装vscode中的两个扩展包php-debug和remote-ssh 然后安装与PHP版本对应的xdebug 访问xdebug的官方网页&#xff0c;复制自己的phpinfo源码到方框中&#xff0c;再点击Analyse ssh连接 输入&#xff0c;你想要远程连接的主机i…

Unity中的数学基础——贝塞尔曲线

一&#xff1a;前言 一条贝塞尔曲线是由一组定义的控制点P0到 Pn&#xff0c;n1为线性&#xff0c;n2为二次......第一个和最后一个控制点称为起点和终点&#xff0c;中间的控制点一般不会位于曲线上 获取两个点之间的点就是通过线性插值&#xff08; Mathf.Lerp&#xff09…

分布式 - 服务器Nginx:一小时入门系列之TCP反向代理和负载均衡

文章目录 1. HTTP反向代理和TCP反向代理2. http 块和 stream 块3. TCP反向代理配置4. TCP 负载均衡 1. HTTP反向代理和TCP反向代理 Nginx可以作为HTTP反向代理和TCP反向代理。 HTTP反向代理是指Nginx作为Web服务器的代理服务器&#xff0c;接收客户端的HTTP请求&#xff0c;然…

计算机竞赛 基于大数据的社交平台数据爬虫舆情分析可视化系统

文章目录 0 前言1 课题背景2 实现效果**实现功能****可视化统计****web模块界面展示**3 LDA模型 4 情感分析方法**预处理**特征提取特征选择分类器选择实验 5 部分核心代码6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于大数据…

C语言练习4(巩固提升)

C语言练习4 选择题 前言 面对复杂变化的世界&#xff0c;人类社会向何处去&#xff1f;亚洲前途在哪里&#xff1f;我认为&#xff0c;回答这些时代之问&#xff0c;我们要不畏浮云遮望眼&#xff0c;善于拨云见日&#xff0c;把握历史规律&#xff0c;认清世界大势。 选择题 …

新型数据中心网络安全体系研究

当前&#xff0c;新型基础设施建设已上升至国家战略&#xff0c;被赋予了数字化、智能化的新意义。作为算力基础设施&#xff0c;新型数据中心是信息基础设施中的重要内容&#xff0c;是数字政府、数字经济的“信息底座”&#xff0c;是未来引领数字经济发展的关键载体和支柱&a…

java八股文面试[多线程]——sleep wait join yield

sleep和wait有什么区别 sleep 方法和 wait 方法都是用来将线程进入阻塞状态的&#xff0c;并且 sleep 和 wait 方法都可以响应 interrupt 中断&#xff0c;也就是线程在休眠的过程中&#xff0c;如果收到中断信号&#xff0c;都可以进行响应并中断&#xff0c;且都可以抛出 In…

npm常用命令 + 前端常用的包管理工具 以及 npm淘宝镜像配置等

npm常用命令 前端常用的包管理工具 以及 npm淘宝镜像配置等 1. 前言1.1 NodeJs的下载安装1.2 windows上1.3 常用包管理工具 2. npm2.1 npm 的安装2.2 npm初始化包2.3 npm 安装、卸载包2.3.1 非全局安装2.3.1.1 单个包的安装2.3.1.1.1 默认版本安装2.3.1.1.2 指定版本安装 2.3.…

2022年03月 C/C++(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;拦截导弹 某国为了防御敌国的导弹袭击&#xff0c; 发展出一种导弹拦截系统。 但是这种导弹拦截系统有一个缺陷&#xff1a; 虽然它的第一发炮弹能够到达任意的高度&#xff0c;但是以后每一发炮弹都不能高于前一发的高度。 某天&#xff0c; 雷达捕捉到敌国的…

yolov8热力图可视化

安装pytorch_grad_cam pip install grad-cam自动化生成不同层的bash脚本 # 循环10次&#xff0c;将i的值从0到9 for i in $(seq 0 13) doecho "Running iteration $i";python yolov8_heatmap.py $i; done热力图生成python代码 import warnings warnings.filterwarn…

同源策略以及SpringBoot的常见跨域配置

先说明一个坑。在跨域的情况下&#xff0c;浏览器针对复杂请求&#xff0c;会发起预检OPTIONS请求。如果服务端对OPTIONS进行拦截&#xff0c;并返回非200的http状态码。浏览器一律提示为cors error。 一、了解跨域 1.1 同源策略 浏览器的同源策略&#xff08;Same-Origin Po…

Django学习笔记-AcApp端授权AcWing一键登录

笔记内容转载自 AcWing 的 Django 框架课讲义&#xff0c;课程链接&#xff1a;AcWing Django 框架课。 AcApp 端使用 AcWing 一键授权登录的流程与之前网页端的流程一样&#xff0c;只有申请授权码这一步有一点细微的差别&#xff1a; 我们在打开 AcApp 应用之后会自动向 AcW…

05.sqlite3学习——DML(数据管理:插入、更新、删除)

目录 DML&#xff08;数据管理&#xff1a;插入、更新、删除&#xff09; 插入 更新 删除整个表 语法 实例 DML&#xff08;数据管理&#xff1a;插入、更新、删除&#xff09; 数据操纵&#xff08;DML&#xff09;&#xff1a;用于增、删、改数据 作用&#xff1a;负…

Java设计模式-职责链模式

1 概述 在现实生活中&#xff0c;常常会出现这样的事例&#xff1a;一个请求有多个对象可以处理&#xff0c;但每个对象的处理条件或权限不同。例如&#xff0c;公司员工请假&#xff0c;可批假的领导有部门负责人、副总经理、总经理等&#xff0c;但每个领导能批准的天数不同…

Mac OS 13.4.1 搜狗输入法导致的卡顿问题

一、Mac OS 系统版本 搜狗输入法已经更新到最新 二、解决方案 解决方案一 在我的电脑上面需要关闭 VSCode 和 Chrmoe 以后&#xff0c;搜狗输入法回复正常。 解决方案二 强制重启一下搜狗输入法。 可以用 unix 定时任务去隔 2个小时自动 kill 掉一次进程 # kill 掉 mac …

【SpringBoot】第一篇:redis使用

背景&#xff1a; 本文是教初学者如何正确使用和接入redis。 一、引入依赖 <!--redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><depen…

MyBatis快速入门以及环境搭建和CRUD的实现

目录 前言 一、MyBatis简介 1.MyBatis是什么 2.MyBatis的特点 3.mybatis的作用 4.MyBatis的应用场景 5.MyBatis优缺点 二、相关概念 1.ORM概述 2.常见的ORM框架 3.什么是持久层框架 三、MyBatis的工作原理 1.框架交互 2.工作原理 ​编辑 四、MyBatis环境搭建 1…

多次跑网络流(用于构造类)+霍尔定理证明可行:AGC317G

https://atcoder.jp/contests/abc317/tasks/abc317_g 一个很显然的思路&#xff0c;就是行向颜色连边&#xff0c;但约束条件展现出多个维度&#xff0c;所以可以考虑跑多次网络流。 但跑同样的网络流没有意义&#xff0c;所以每次跑完都要在残余网络上操作一下才可行。此题中…

JVM理论知识

一、JVM内存结构 java的内存模型主要分为5个部分&#xff0c;分别是&#xff1a;JVM堆、JVM栈、本地栈、方法区还有程序计数器&#xff0c;他们的用途分别是&#xff1a; JVM堆&#xff1a;新建的对象都会放在这里&#xff0c;他是JVM中所占内存最大的区域。他又分为新生区还…

项目---日志系统

目录 项目系统开发环境核心技术日志系统介绍为什么需要日志系统? 日志系统框架设计日志系统模块划分代码实现通用工具实现日志等级模块实现日志消息模块实现格式化模块实现落地模块实现日志器模块同步日志器异步日志器缓冲区实现异步工作器实现 回归异步日志器模块建造者模式日…