Redis20-通信协议

news2024/11/23 21:42:36

目录

RESP协议

概述

数据类型

模拟Redis客户端


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)

数据类型

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

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

2.错误(Errors):首字节是 ‘-’ ,以CRLF( "\r\n" )结尾,只是字符串是异常信息,例如:"-Error message\r\n"

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

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

  • 如果大小为0,则代表空字符串:"$0\r\n\r\n"
  • 如果大小为-1,则代表不存在:"$-1\r\n"

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

模拟Redis客户端

Redis支持TCP通信,因此可以使用Socket来模拟客户端,与Redis服务端建立连接:

public class Main {

    static Socket s;
    static PrintWriter writer;
    static BufferedReader reader;

    public static void main(String[] args) {
        try {
            // 1.建立连接
            String host = "192.168.150.101";
            int port = 6379;
            s = new Socket(host, port);
            // 2.获取输出流、输入流
            writer = new PrintWriter(new OutputStreamWriter(s.getOutputStream(), StandardCharsets.UTF_8));
            reader = new BufferedReader(new InputStreamReader(s.getInputStream(), StandardCharsets.UTF_8));

            // 3.发出请求
            // 3.1.获取授权 auth 123321
            sendRequest("auth", "123321");
            Object obj = handleResponse();
            System.out.println("obj = " + obj);

            // 3.2.set name 张三
            sendRequest("set", "name", "张三");
            // 4.解析响应
            obj = handleResponse();
            System.out.println("obj = " + obj);

            // 3.2.set name 张三
            sendRequest("get", "name");
            // 4.解析响应
            obj = handleResponse();
            System.out.println("obj = " + obj);

            // 3.2.set name 张三
            sendRequest("mget", "name", "num", "msg");
            // 4.解析响应
            obj = handleResponse();
            System.out.println("obj = " + obj);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 5.释放连接
            try {
                if (reader != null) reader.close();
                if (writer != null) writer.close();
                if (s != null) s.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    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.parseLong(reader.readLine());
            case '$': // 多行字符串
                // 先读长度
                int len = Integer.parseInt(reader.readLine());
                if (len == -1) {
                    return null;
                }
                if (len == 0) {
                    return "";
                }
                // 再读数据,读len个字节。假设没有特殊字符,所以读一行(简化)
                return reader.readLine();
            case '*':
                return readBulkString();
            default:
                throw new RuntimeException("错误的数据格式!");
        }
    }

    private static Object readBulkString() throws IOException {
        // 获取数组大小
        int len = Integer.parseInt(reader.readLine());
        if (len <= 0) {
            return null;
        }
        // 定义集合,接收多个元素
        List<Object> list = new ArrayList<>(len);
        // 遍历,依次读取每个元素
        for (int i = 0; i < len; i++) {
            list.add(handleResponse());
        }
        return list;
    }

    // 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();
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

6RA8075-6DV62-0AA0模块可面价

6RA8075-6DV62-0AA0模块可面价 6RA8075-6DV62-0AA0模块可面价 6RA8075-6DV62-0AA0模块可面价 6ES7655-5DX40-2AA0模块接线图 6ES7655-5DX40-2AA0模块说明书 6ES7655-5DX40-2AA0模块选型手册 6ES7655-5DX40-2AA0功能模块是指数据说明、可执行语句等程序元素的集合&#xf…

permutation sequence(

60. Permutation Sequence class Solution:def getPermutation(self, n: int, k: int) -> str:def rec(k, l, ans, n):if(n0): return# 保留第一个位置&#xff0c;剩下数字的组合leftCom math.factorial(n - 1) #用于计算 (n-1) 的阶乘值ele k // leftCommod k % leftCo…

SpringBoot入门笔记

本文是看黑马老师讲课视频学习笔记整理 目录 入门案例 基于IDEA联网 基于Springboot官网创建 基于阿里云创建项目 手工创建 隐藏文件 入门案例解析: parent​编辑 starter 引导类 内嵌tomcat 入门案例 基于IDEA联网 RestController RequestMapping("/books&…

Electron:摄像头录制和屏幕录制

摄像头录制 main.js const { app, BrowserWindow} require(electron)let mainWin null const createWindow () > {mainWin new BrowserWindow({width: 800,height: 600,title: 自定义菜单,webPreferences: {// 允许渲染进程使用nodejsnodeIntegration: true,// 允许渲…

首站,北京!OpenCSG邀您共赴AI之约【2024戴尔科技峰会预告】

图片来源&#xff1a;戴尔 在数字化浪潮的推动下&#xff0c;人工智能正成为推动社会进步的关键力量及带来生产力的提升。据相关数据显示,全球企业对人工智能的投资已增长50%&#xff0c;预计到2025年&#xff0c;人工智能将为全球经济贡献15.7万亿美元。人工智能将革新我们的生…

PyTorch深度学习实战(12)—— 神经网络工具箱nn.functional

1. nn.functional torch.nn中还有一个很常用的模块&#xff1a;nn.functional。torch.nn中的大多数layer&#xff0c;在functional中都有一个与之相对应的函数。nn.functional中的函数和nn.Module的主要区别在于&#xff1a;使用nn.Module实现的layer是一个特殊的类&#xff0c…

【人工智能】Transformers之Pipeline(九):物体检测(object-detection)

目录​​​​​​​ 一、引言 二、物体检测&#xff08;object-detection&#xff09; 2.1 概述 2.2 技术原理 2.3 应用场景 2.4 pipeline参数 2.4.1 pipeline对象实例化参数 2.4.2 pipeline对象使用参数 2.4 pipeline实战 2.5 模型排名 三、总结 一、引言 pipel…

黑马头条vue2.0项目实战(八)——文章评论

目录 1. 展示文章评论列表 1.1 准备组件 1.2 获取文章评论数据并展示 1.3 展示文章评论总数量 1.4 文章评论项 2. 评论点赞 3. 发布文章评论 3.1 准备弹出层 3.2 封装发布文章评论组件 3.3 请求发布 4. 评论回复 4.1 准备回复弹层 4.2 封装内容组件 4.3 处理头部…

【深度学习】创建和训练Transformer神经网络模型,将葡萄牙语翻译成英语

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言1. 安装2. 数据处理2.1 下载数据集2.2 设置标记器2.3 使用tf.data设置数据管道 3. 测试数据集4. 定义组件4.1 嵌入和位置编码层4.2 添加并规范化4.3 基础注意力…

Android 12系统源码_多屏幕(二)模拟辅助设备功能开关实现原理

前言 上一篇我们通过为Android系统开启模拟辅助设备功能开关&#xff0c;最终实现了将一个Activity显示到多个屏幕的效果。 本篇文章我们具体来分析一下当我们开启模拟辅助设备功能开关的时候&#xff0c;Android系统做了什么哪些操作。 一、模拟辅助设备功能开关应用位置 …

Qt5编译qmqtt库使用MQTT协议连接华为云IOT完成数据上传与交互

一、前言 随着物联网技术的发展,越来越多的设备通过网络互相连接,形成了庞大的智能系统。这些系统能够收集、分析并响应各种数据,从而实现自动化控制和智能化管理。在这个背景下,MQTT 成为了一个广泛使用的轻量级消息传输协议,特别适用于资源受限的环境,如移动应用或远程…

WebSocket 实现:注解与原生方式对比

WebSocket 作为一种在单个长连接上进行全双工、双向通信的协议&#xff0c;已经成为现代Web应用中实现实时通信的重要技术。本文将探讨如何使用注解和原生方式来实现 WebSocket&#xff0c;并对这两种方法进行比较。 一、注解方式实现 WebSocket 在许多现代Java框架中&#x…

GBJ406-ASEMI无人机专用GBJ406

编辑&#xff1a;ll GBJ406-ASEMI无人机专用GBJ406 型号&#xff1a;GBJ406 品牌&#xff1a;ASEMI 封装&#xff1a;GBJ-4 批号&#xff1a;2024 现货&#xff1a;50000 最大重复峰值反向电压&#xff1a;600V 最大正向平均整流电流(Vdss)&#xff1a;4A 功率(Pd)&am…

43.【C语言】指针(重难点)(F)

目录 15.二级指针 *定义 *演示 16.三级以及多级指针 *三级指针的定义 *多级指针的定义 17.指针数组 *定义 *代码 18.指针数组模拟二维数组 往期推荐 15.二级指针 *定义 之前讲的指针全是一级指针 int a 1; int *pa &a;//一级指针 如果写成 int a 1; int *pa &a…

MES生产执行系统源码,支持 SaaS 多租户,技术架构:springboot + vue-element-plus-admin

MES的定义与功能 MES是制造业中一种重要的管理信息系统&#xff0c;用于协调和监控整个生产过程。它通过收集、分析和处理各种生产数据&#xff0c;实现对生产流程的实时跟踪和监控&#xff0c;并为决策者提供准确的数据支持。MES涵盖了工厂运营、计划排程、质量管理、设备维护…

AI时代下的智慧体育, 用科技赋能体育创新

在科技飞速发展的今天&#xff0c;人工智能&#xff08;AI&#xff09;已成为推动各行各业创新的重要力量。体育&#xff0c;作为人类文明的重要组成部分&#xff0c;同样在AI的浪潮中迎来了新的变革机遇。AI时代下的智慧体育&#xff0c;不再局限于传统的运动模式&#xff0c;…

Spring Boot集成Devtools实现热更新?

1.什么Devtools&#xff1f; DevTools是开发者工具集&#xff0c;主要用于简化开发过程中的热部署问题。 热部署是指在开发过程中&#xff0c;当代码发生变化时&#xff0c;无需手动重启应用&#xff0c;系统能够自动检测并重新加载修改后的代码&#xff0c;大大提高了开发效率…

量化投资策略与技术学习PART2:量化选股之风格轮动

市场上的投资者是有偏好的&#xff0c;有时候偏好于价值股&#xff0c;有时候偏好于成长股&#xff0c;有时偏于大盘&#xff0c;有时又偏于小盘&#xff0c;由于投资者的这种不同的交易行为&#xff0c;形成了市场风格&#xff0c;本节主要研究如何判断市场风格&#xff0c;以…

MyBatis介绍(1)

前言 MyBatis 是一个半 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;它内部封装了 JDBC&#xff0c;开发时只需要关注 SQL 语句本身&#xff0c;不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。程序员直接编写原生态 sql&#xff0c;可以…

【java报错已解决】error: metadata-generation-failed

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 一、问题描述1.1 报错示例1.2 报错分析1.3 解决思路二、解决方法2.1 方法一&#xff1a;检查环境变量2.2 步骤二&…