Redis复习-通信协议、内存回收

news/2025/2/27 18:02:13/文章来源:https://www.cnblogs.com/Helix6/p/18741619

通信协议

RESP协议

Redis是一个CS架构的软件,通信一般分两步(不包括pipeline和PubSub):
1.客户端(client)向服务端(server)发送一条命令
2.服务端解析并执行命令,返回响应结果给客户端
因此客户端发送命令的格式、服务端响应结果的格式必须有一个规范,这个规范就是通信协议。

而在Redis中采用的是RESP(Redis Serialization Protocol)协议:
Redis 1.2版本引入了RESP协议
Redis 2.0版本中成为与Redis服务端通信的标准,称为RESP2
Redis 6.0版本中,从RESP2升级到了RESP3协议,增加了更多数据类型并且支持6.0的新特性--客户端缓存

但目前,默认使用的依然是RESP2协议,也是我们要学习的协议版本(以下简称RESP)。

基于Socket的自定义Redis客户端

在RESP中,通过首字节的字符来区分不同数据类型,常用的数据类型包括5种:
1.单行字符串:首字节是 ‘+’ ,后面跟上单行字符串,以CRLF( "\r\n" )结尾。例如返回"OK": "+OK\r\n"
2.错误(Errors):首字节是 ‘-’ ,与单行字符串格式一样,只是字符串是异常信息,例如:"-Error message\r\n"
3.数值:首字节是 ‘:’ ,后面跟上数字格式的字符串,以CRLF结尾。例如:":10\r\n"
4.多行字符串:首字节是 ‘$’ ,表示二进制安全的字符串,最大支持512MB:
如果大小为0,则代表空字符串:"$0\r\n\r\n"
如果大小为-1,则代表不存在:"$-1\r\n"

5.数组:首字节是 ‘*****’,后面跟上数组元素个数,再跟上元素,元素数据类型不限:

指定命令的实现

package com.demo;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;public class Main {static Socket socket;static PrintWriter writer;static BufferedReader reader;public static void main(String[] args) {try {//建立连接String host = "localhost";int port = 6379;socket = new Socket(host, port);//获取输入、输出流writer = new PrintWriter(socket.getOutputStream());//输入流reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));//输出流//发请求sendRequest();//解析响应Object res = handleResponse();System.out.println(res);} catch (Exception e) {throw new RuntimeException(e);} finally {//释放连接try {if (reader!=null) reader.close();} catch (IOException e) {throw new RuntimeException(e);}if (writer!=null) writer.close();try {if (socket!=null) socket.close();} catch (IOException e) {throw new RuntimeException(e);}}}//发送请求(set name 张三)private static void sendRequest() {writer.println("*3");writer.println("$3");writer.println("set");writer.println("$4");writer.println("name");writer.println("$6");writer.println("张三");writer.flush();}//解析响应private static Object handleResponse() throws IOException {int prefix = reader.read();//读取第一个字符switch (prefix){case '+':return reader.readLine();case '-':throw new RuntimeException(reader.readLine());case ':':return Long.valueOf(reader.readLine());case '$':int len = Integer.parseInt(reader.readLine());//读取长度if (len == 0) return "";else if (len == 1) return null;return reader.readLine();case '*':return handleMultiple();default:throw new RuntimeException("不支持的数据类型");}}private static Object handleMultiple() throws IOException {Integer len = Integer.valueOf(reader.readLine());if (len <= 0) return null;List<Object> list = new ArrayList<>();for (int i = 0; i < len; i++) {list.add(handleResponse());}return list;}
}

将命令改为可以自定义输入命令的方式

package com.demo;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;public class Main {static Socket socket;static PrintWriter writer;static BufferedReader reader;public static void main(String[] args) {try {//建立连接String host = "localhost";int port = 6379;socket = new Socket(host, port);//获取输入、输出流writer = new PrintWriter(socket.getOutputStream());//输入流reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));//输出流//发请求sendRequest("set", "name", "张三");//解析响应Object res = handleResponse();System.out.println(res);sendRequest("set", "num", "22");//解析响应System.out.println(handleResponse());//发请求sendRequest("mget", "name","num");//解析响应System.out.println(handleResponse());} catch (Exception e) {throw new RuntimeException(e);} finally {//释放连接try {if (reader != null) reader.close();} catch (IOException e) {throw new RuntimeException(e);}if (writer != null) writer.close();try {if (socket != null) socket.close();} catch (IOException e) {throw new RuntimeException(e);}}}//发送请求(set name 张三)private static void sendRequest(String... args) {writer.println("*" + args.length);//数组长度for (String arg : args) {writer.println("$" + arg.getBytes(StandardCharsets.UTF_8).length);//二进制位数writer.println(arg);}writer.flush();//刷新}//解析响应private static Object handleResponse() throws IOException {int prefix = reader.read();//读取第一个字符switch (prefix) {case '+':return reader.readLine();case '-':throw new RuntimeException(reader.readLine());case ':':return Long.valueOf(reader.readLine());case '$':int len = Integer.parseInt(reader.readLine());//读取长度if (len == 0) return "";else if (len == 1) return null;return reader.readLine();case '*':return handleMultiple();default:throw new RuntimeException("不支持的数据类型");}}private static Object handleMultiple() throws IOException {Integer len = Integer.valueOf(reader.readLine());if (len <= 0) return null;List<Object> list = new ArrayList<>();for (int i = 0; i < len; i++) {list.add(handleResponse());}return list;}
}

内存回收

过期Key处理

内存淘汰策略

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

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

相关文章

vi和vim快捷键

vi和vim常用的一些快捷键分类 快捷键 说明模式切换 i 进入插入模式(在光标前插入文本)。a 进入插入模式(在光标后插入文本)。o 在当前行下方插入新行并进入插入模式。O 在当前行上方插入新行并进入插入模式。Esc 退出插入模式,返回命令模式。: 进入命令模式(用于输入命令…

Go红队开发—语法补充

之前有师傅问这个系列好像跟红队没啥关系,前几期确实没啥关系,因为这都是进行红队工具开发的前置知识点,对于我个人强迫症而言只是想让这个系列更加完善而已,所以前置知识也加进去了,有GO只是的大佬可以等下一期哈!感谢支持。目录错误控制使用自定义错误类型错误包装erro…

Security认证失败逻辑

通过一系列的过滤器最终走到 FilterSecurityInterceptor package org.springframework.security.access.vote;public class AffirmativeBased extends AbstractAccessDecisionManager {public AffirmativeBased(List<AccessDecisionVoter<? extends Object>> deci…

关于书店管理系统的二次开发

一、来源 来自同学期末大作业。实现了基本的书店业务功能,包括书本信息管理、客户信息管理、购物车操作以及订单生成与保存等。 二、运行环境 + 运行结果的截图 操作系统:Windows 11 开发工具:Visual Studio 2022// BookStore.h点击查看代码 #ifndef BOOKSTORE_H #define BO…

CNC数控机床运行状态参数采集联网 对接软件MES 系统

IP 端口 TCP端口 流程任务 当前位置或者目标位置及描述 状态 需要接口内容 请求地址-AGV 请求AGV参数 请求AGV返回信息 PLC-地址 写入PLC值 读取PLC值 EDM-地址 写入EDM值 读取EDM值进入上下料进程 进入EDM上料台动作-动作 即将进入EDM上料台 "1.达…

Redis+Docker集群部署

机器故障了怎么办? Redis 是内存数据库,我们知道可以通过持久化机制,保存快照或者保存记录日志的方式,将数据持久化到磁盘。但是,如果机器故障了或磁盘坏了,数据就不就全没了吗?这种情况应该怎么办呢?别担心,考虑主从模式。 主从模式 给主节点 Master 配置一个从节点 …

【T20天正电气V10.0软件下载与安装教程】

1、安装包 扫描下方二维码关注「软知社」,后台回复【024】三位数字即可免费获取分享链接,无广告拒绝套路; 2、安装教程双击T20天正电气V10.0安装包,弹窗安装对话框选择我接收,点击下一步选择安装位置,点击下一步点击下一步等待安装进度完成安装完成,点击完成按钮点击下…

windows底层激活破解一步到位,TSforge也太暴力了!

windows底层激活破解一步到位,TSforge也太暴力了! windows底层激活破解一步到位,TSforge也太暴力了! 微软系统一直是需要收费的,也是电脑用户们经常遇到的问题,市面上也有很多工具, 但是今天的工具是最新的且**呼声最高、最彻底的**,需要的话赶紧保存下来,实际使用只需…

No.23 CSS--定位

一、定义position属性指定了元素的定位类型。其中,绝对定位和固定定位会脱离文档流. 设置定位之后:可以使用四个方向值进行调整位置:Ieft、top、right、bottom.二、相对定位<head><meta charset="UTF-8"><meta name="viewport" content=&q…

机器人保养指南周期性检修

机器人保养指南——那智不二越机器人日常维护、专业维修与周期性检修在进行那智不二越机器人的日常检查、维修、部件更换或任何其他相关作业时,首要且至关重要的一步是确保已切断电源,只有在完全断电的情况下,方可安全地进行后续操作。此外,还应在一次电源等关键位置设置明…

OERV兴趣探索:模拟器移植

最近看了很多开源项目,主要都集中在模拟器方面,我指的是游戏模拟器比如GameBoy或者PlayStation这一类。现在想玩这系列的游戏可以在手机或者电脑下载相应的模拟器,并且获取对应的ROM文件,不过也有一些模拟器是可以运行在Linux上面的,为了进一步探索,我选择了相对较小的项…

HTTP协议与RESTful API实战手册(二):用披萨店故事说透API设计奥秘

title: HTTP协议与RESTful API实战手册(二):用披萨店故事说透API设计奥秘 🍕 date: 2025/2/27 updated: 2025/2/27 author: cmdragon excerpt: 📦 本系列第二篇通过披萨店创业的完整案例,手把手教你: 用外卖订单理解HTTP协议细节 5个RESTful设计常见误区与修正方案 …