当前位置: 首页 > news >正文

Redis的resp协议

resp协议

redis客户端和服务端交互使用的是redis作者制定的一个协议,叫resp(REdis Serialization Protocol)。

具体分如下几个层次

  • 基于tcp
  • 请求响应模式,但在两种情况下不再是简单的请求和响应模式(下文介绍)
  • 支持五种类型的数据,分别是简单字符串,错误,整型,bulk strings ,数组

客户端发给服务端的命令都会序列化为array,而服务端返回给客户端的可以为如上任意一种类型,各简单举例如下

  • 简单字符串,第一个byte为 '+',例如 "+OKrn"
  • 错误,第一个byte为'-',例如 "-Error messagern"
  • 整型, 第一个byte为':",例如 ":10rn"
  • bulk strings,第一个byte为"$",例如 "$6rnfoobarrn"(此处为美元符号,没有前边的反斜杠)
  • 数组,第一个byte为'',例如"2rn$3\r\nfoo\r\n$3rnbarrn"

具体介绍参考:https://redis.io/topics/protocol

sub pattern

请求响应模式有两种特殊情况

  • pipeline模式,客户端同时发送多条命令到服务端
  • sub pattern:当客户端执行subscribe命令后,不再要求客户端发送命令,当有其他客户端在订阅渠道上publish消息后,服务端会主动push信息到客户端

我们拿redis-cli客户端试一下执行subscribe

127.0.0.1:6379> subscribe foo
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "foo"
3) (integer) 1

可以看到,redis-cli会阻塞,当另起一个客户端,publish消息后,会收到该消息并打印

xiaoju@zsh_test ~$redis-cli
127.0.0.1:6379> publish foo bar
(integer) 1
127.0.0.1:6379>


xiaoju@zsh_test ~$redis-cli
127.0.0.1:6379> subscribe foo
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "foo"
3) (integer) 1
1) "message"
2) "foo"
3) "bar"

直观感觉是服务端阻塞了,没有返回数据给客户端。但看redis源码,实际服务端并没有阻塞,并且可以在连接上继续接收并处理命令

void subscribeCommand(client *c) {
    int j;
    //将订阅的渠道加入相应结构体并直接返回
    for (j = 1; j < c->argc; j++)
        pubsubSubscribeChannel(c,c->argv[j]);
    //将客户端置CLINET_PUBSUB标记
    c->flags |= CLIENT_PUBSUB;
}

当客户端置了CLINET_PUBSUB标记后,命令处理会做如下特殊逻辑

int processCommand(client *c) {
    ...
    //当置CLIENT_PUBSUB标记后,只有ping/subscribe/unsubscribe/psubscribe/punsubscribe命令能够执行
    if (c->flags & CLIENT_PUBSUB &&
        c->cmd->proc != pingCommand &&
        c->cmd->proc != subscribeCommand &&
        c->cmd->proc != unsubscribeCommand &&
        c->cmd->proc != psubscribeCommand &&
        c->cmd->proc != punsubscribeCommand) {
            addReplyError(c,"only (P)SUBSCRIBE / (P)UNSUBSCRIBE / PING / QUIT allowed in this context");
            return C_OK;
    }
     ...
}

godis-cli
如上文所示,当客户端执行subscribe命令后,实际上是可以继续订阅或者取消订阅渠道,并且可以执行ping命令。redis-cli客户端实际上是自己阻塞了,如下代码:

if (config.pubsub_mode) {
    if (config.output != OUTPUT_RAW)
        printf("Reading messages... (press Ctrl-C to quit)\n");
    //进入死循环,一直等待服务端发送消息
    while (1) {
        if (cliReadReply(output_raw) != REDIS_OK) exit(1);
    }
}

那么,我们可以拿go写一个不阻塞的版本,并且可以测试redis的subscribe 模式。效果如下

>bogon:godis-cli didi$ go run godis-cli.go
> set k1 v1 
OK
> get k1
v1
> subscribe foo
subscribe foo 1
[sub]>subscribe foo1//sub模式下可以继续订阅其他渠道
subscribe foo1 2
[sub]> unsubscribe foo1//取消订阅
unsubscribe foo1 1
[sub]> ping//sub模式也可以执行ping
pong
[sub]> get k1 //sub模式下不能执行get命令
Redis Error: only (P)SUBSCRIBE / (P)UNSUBSCRIBE / PING / QUIT allowed in this context
[sub]> exit
exit sub pattern....
>get k1//退出sub模式后可以继续正常执行get命令
v1
> exit

由于godis-cli直接实现了resp协议,虽然只是为了观察subscribe pattern的效果,但实际上可以支持所有redis命令的执行

具体代码地址见:https://github.com/erpeng/god...

相关文章:

  • 炒冷饭系列:设计模式 工厂方法模式
  • 2019年寒假作业2 - 7-1 币值转换
  • JavaScript-如何实现克隆(clone)函数
  • [总结]Android系统体系结构
  • 给第三方使用接口的 URL 签名实现
  • JVM【第四回】:【对象访问】
  • Flask 教程 第一章:Hello, World!
  • Netty源码解析1-Buffer
  • SCCM 2012 R2实战系列之一:SQL安装
  • 【CuteJavaScript】Angular6入门项目(3.编写服务和引入RxJS)
  • ahjesus 让我的MVC web API支持JsonP跨域
  • 《剑指offer》分解让复杂问题更简单
  • 文件编码
  • 关于springcloud Gateway中的限流
  • 老婆!辛苦了
  • CSS魔法堂:Absolute Positioning就这个样
  • Hexo+码云+git快速搭建免费的静态Blog
  • java2019面试题北京
  • Java到底能干嘛?
  • Material Design
  • Next.js之基础概念(二)
  • Promise初体验
  • SQLServer之创建显式事务
  • Webpack 4 学习01(基础配置)
  • 使用agvtool更改app version/build
  • Nginx实现动静分离
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • ​软考-高级-系统架构设计师教程(清华第2版)【第20章 系统架构设计师论文写作要点(P717~728)-思维导图】​
  • ​业务双活的数据切换思路设计(下)
  • #14vue3生成表单并跳转到外部地址的方式
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • (12)Linux 常见的三种进程状态
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (蓝桥杯每日一题)love
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理 第13章 项目资源管理(七)
  • (排序详解之 堆排序)
  • (三十五)大数据实战——Superset可视化平台搭建
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (一)Linux+Windows下安装ffmpeg
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • (转载)Linux网络编程入门
  • (最全解法)输入一个整数,输出该数二进制表示中1的个数。
  • .Net Remoting常用部署结构
  • .NET与java的MVC模式(2):struts2核心工作流程与原理
  • @Autowired标签与 @Resource标签 的区别
  • [ 英语 ] 马斯克抱水槽“入主”推特总部中那句 Let that sink in 到底是什么梗?
  • [20171101]rman to destination.txt
  • [AR]Vumark(下一代条形码)
  • [AX]AX2012 SSRS报表Drill through action
  • [BZOJ 1040] 骑士
  • [BZOJ4337][BJOI2015]树的同构(树的最小表示法)