Redis原理篇—通信协议

news2024/11/24 18:48:07

Redis原理篇—通信协议

笔记整理自 b站_黑马程序员Redis入门到实战教程

RESP协议

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

  • 客户端(client)向服务端(server)发送一条命令
  • 服务端解析并执行命令,返回响应结果给客户端

因此客户端发送命令的格式、服务端响应结果的格式必须有一个规范,这个规范就是通信协议

而在 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 种:

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

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

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

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

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

基于Socket自定义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();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (writer != null) writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                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();
    }
}

最终,我们测试发送请求和接收响应:

image-20221224151849680

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

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

相关文章

VMC证书是什么?获取认证标志证书步骤是怎样的?

VMC证书是什么&#xff1f; VMC证书(全称&#xff1a;Verified Mark Certificate)&#xff0c;也称认证标志证书&#xff0c;是由权威CA机构颁发&#xff0c;用于验证商标所有权的数字证书。 VMC 通过提供验证机制与 BIMI 协同工作&#xff0c;BIMI标准可以在电子邮件中的“发…

OSCS开源安全周报第23期:Foxit PDF Reader/Editor 任意代码执行漏洞

本周安全态势综述 OSCS 社区共收录安全漏洞10个&#xff0c;其中公开漏洞值得关注的是 Apache Airflow Hive Provider <5.0.0 存在操作系统命令注入漏洞&#xff08;CVE-2022-46421&#xff09;vm2 < 3.9.10 存在任意代码执行漏洞&#xff08;CVE-2022-25893&#xff0…

湖南软件工程自考本科总结

本人情况 在湖南长沙考试&#xff0c;从2021年初开始备考&#xff0c;社会考生&#xff0c;自己复习&#xff0c;从2021-4月到2022-10月&#xff0c;理论每次都考了4门课程&#xff0c;前3次每次挂了1门课程&#xff0c;刚刚好在4次考试完成了所有的理论考试。 经验分享 复习重…

2022 re:Invent 凌云驭势 重塑未来

2022年11月29日&#xff0c;一年一度的亚马逊 re:Invent全球大会在拉斯维加斯再度上演&#xff0c;这是亚马逊云科技第11年举办re:Invent&#xff0c;来自全球的5万多客户和合作伙伴参加了此次线下盛会&#xff0c;还有超过30万人线上参会。在此次大会上&#xff0c;亚马逊云科…

喜报 | 云畅科技再次入榜湖南省互联网企业50强

12月21日&#xff0c;湖南省互联网协会在国家网络安全产业园区&#xff08;长沙&#xff09;发布了2022年湖南省互联网企业综合实力30强榜单、互联网成长型企业10强榜单、互联网创新型企业10强榜单和《2022年湖南省互联网企业50强发展报告》。 湖南云畅网络科技有限公司&#x…

burpsuite靶场——CSRF

文章目录什么是CSRF&#xff1f;CSRF 攻击的影响是什么&#xff1f;CSRF 是如何工作的&#xff1f;没有防御的 CSRF 漏洞常见的 CSRF 漏洞Token验证取决于请求方法Token的验证取决于Token是否存在CSRF Token未绑定到用户会话Token未与会话 cookie绑定什么是CSRF&#xff1f; 跨…

【HTML】动画合集--跟着pink老师学习

1.奔跑小熊 奔跑小熊<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice…

【免杀前置课——shellcode】二十、初识shellcode——配合栈溢出漏洞利用shellcode在代码中返回MessageBox函数

初识shellcode栈溢出漏洞反弹shellcodeshellcode取出shellcode栈溢出漏洞反弹shellcode shellcode shellcode&#xff1a; shellcode是一段用于利用软件漏洞而执行的代码&#xff0c;shellcode为16进制的机器码&#xff0c;因为经常让攻击者获得shell而得名。.shellcode常常使…

自动控制原理笔记-线性系统的稳定性分析

目录 稳定的概念及定义&#xff1a; 系统稳定的充要条件——闭环极点全部落在虚轴左边&#xff1a; 系统的稳定性判据&#xff1a; 劳斯判据(充要性)判据&#xff1a; 劳斯表特殊情况例(出现计算过程分母为0)&#xff1a; 劳斯表特殊情况例(出现全0行)&#xff1a; 稳定的…

【Java】花费数十小时,带你体验Java文档搜索引擎的实现过程

Java文档搜索引擎项目运行效果一、简述搜索引擎概念二、搜索引擎实现思路2.1倒排索引介绍2.2项目目标2.3获取java文档2.4模块划分2.5创建项目2.6认识分词2.7分词的原理2.8使用第三方分词库三、实现索引模块-parser类3.1 实现索引模块-递归枚举文件3.2 排除非HTML文件3.3 实现索…

旁瓣消隐技术在雷达中应用

电子对抗在现代战争中的作用日趋重要&#xff0c;没有雷达抗干扰技术的雷达完全失去其发现测定敌人目标的功能。从降低天线旁瓣干扰方面考虑&#xff0c;雷达抗干扰技术主要包括旁瓣对消技术和旁瓣消隐技术&#xff0c;旁瓣对消器在有一个辅助天线的情况下抑制一个干扰源的效果…

正式入职开发工程师工作近半年有感

一、前言 博主是毕业于集美大学的一枚软件工程本科生&#xff0c;不知不觉已经毕业近半年了&#xff0c;由于工作繁忙 个人的懒惰&#xff0c;对CSDN的博客记录频率已经大不如之前。说起这里也是惭愧&#xff0c;之后博主会尽量抽出时间&#xff0c;继续保持各种学习&#xf…

代码随想录算法训练营第43天 | 1049. 最后一块石头的重量 II 494. 目标和 474.一和零

一、Leetcode 1049. 最后一块石头的重量 II 这几个题都很不好给转成01问题。本题一开始我以为怎么撞都行&#xff0c;其实不是&#xff0c;相当于给每项前面加1&#xff0c; 就是说有时候不能浪费小石头&#xff0c;得跟大石头碰。 那么问题就很明显了&#xff0c;类似于分割…

AC自动机

AC自动机 AC自动机是干嘛的&#xff1f; 我有一个敏感词数组&#xff0c;里面装的是所有的敏感词&#xff0c;还有一篇大文章&#xff0c;我要求出大文章里面所有的敏感词。 敏感词数组本身的组织是一颗前缀树。 AC自动机就是在前缀树的基础上做升级。 流程 我们在前缀树的…

已来到 “后云原生时代” 的我们,如何规模化运维?

文&#xff5c;李大元 &#xff08;花名&#xff1a;达远&#xff09; Kusion 项目负责人 来自蚂蚁集团 PaaS 核心团队&#xff0c;PaaS IaC 基础平台负责人。 本文 4331 字 阅读 11 分钟 PART. 1 后云原生时代 距离 Kubernetes 第一个 commit 已经过去八年多了&#xff0c…

chrome extensions mv3与mv2比较 执行eval

文章目录背景1、mv3版本与mv2版本之间的一些区别2、解决mv3版本DOM交互 & JS执行问题2.1、关于引入eval52.2、关于在background.js执行script脚本3、background执行fetch调用URL参考背景 老的扩展项目使用的是mv2版本的API&#xff0c;计划升级mv3版本的时候遇到了下面的问…

MySQL索引为什么使用B+树,而不用二叉树、红黑树、哈希表、B树?

索引是帮助MySQL高效获取数据的排好序的数据结构。 索引数据结构&#xff1a; 1.二叉树 2.红黑树 3.Hash表 4.B-Tree 1. 二叉查找树&#xff08;Binary Search Trees&#xff09; 左节点比父节点要小&#xff0c;右节点比父节点要大。它的高度决定的查找效率。 如果某一列数…

Java面试题-框架篇

框架篇 文章目录框架篇1. Spring refresh 流程2. Spring bean 生命周期3. Spring bean 循环依赖解决 set 循环依赖的原理4. Spring 事务失效5. Spring MVC 执行流程6. Spring 注解7. SpringBoot 自动配置原理8. Spring 中的设计模式1. Spring refresh 流程 要求 掌握 refresh…

【服务器数据恢复】EMC存储raid5多块磁盘掉线的数据恢复案例

服务器数据恢复环境&#xff1a; EMC某型号存储&#xff1b; 8块硬盘组成raid5磁盘阵列。 服务器故障&#xff1a; raid5磁盘阵列中2块硬盘离线&#xff0c;服务器崩溃&#xff0c;上层应用不可用。 服务器数据恢复过程&#xff1a; 1、数据恢复工程师将故障存储设备内的所有硬…

嵌入式开发--PID控制

PID简介 讲解PID的文章书籍很多&#xff0c;本文就不详细讲了&#xff0c;只讲一下我在学习过程中不容易理解的一些问题点&#xff0c;以供大家参考。比如很多书籍对于PID&#xff0c;只讲了计算&#xff0c;但是最后计算出来的值如何应用&#xff0c;则完全不讲&#xff0c;当…