Gitlib Gitlib
首页
  • 分类
  • 标签
  • 归档
  • Golang开发实践万字总结
  • MySQL核心知识汇总
  • Redis实践总结
  • MQ实践万字总结
  • Docker数据持久化总结
  • Docker网络模式深度解读
  • 常用游戏反外挂技术总结
  • 读书笔记
  • 心情杂货
  • 行业杂谈
  • 友情链接
关于我
GitHub (opens new window)

Ravior

以梦为马,莫负韶华
首页
  • 分类
  • 标签
  • 归档
  • Golang开发实践万字总结
  • MySQL核心知识汇总
  • Redis实践总结
  • MQ实践万字总结
  • Docker数据持久化总结
  • Docker网络模式深度解读
  • 常用游戏反外挂技术总结
  • 读书笔记
  • 心情杂货
  • 行业杂谈
  • 友情链接
关于我
GitHub (opens new window)
  • 操作系统

  • 计算机网络

  • 数据结构和算法

  • MySQL

  • Redis

    • Redis持久化和数据数据恢复
    • Redis发布订阅
    • Redis管道技术
    • Redis事务机制
    • Redis数据过期和淘汰策略
    • Redis中BitMap使用
    • Redis中lua脚本使用
    • Redis通信协议(RESP)入门
      • Redis性能测试Redis-benchmark
      • Redis主从模式搭建及应用
      • Redis集群及高可用实现
      • Redis和Memcache对比
      • Redis缓存穿透、缓存击穿、缓存雪崩
      • Redis万字总结
      • 如此简单:Redis安装
      • Memcached安装部署
    • Nginx

    • MongoDB

    • 其他

    • 计算机基础
    • Redis
    Ravior
    2019-01-17
    目录

    Redis通信协议(RESP)入门

    Redis客户端和服务器端采用RESP(Redis Serialization Protocal)进行通信。RESP协议有以下特点:

    • 二进制安全;
    • 以行作为单位,客户端和服务器发送的命令或数据一律以\r\n (CRLF)作为换行符;
    • 第一个字节作为数据格式标记;

    二进制安全是指允许协议中出现任意字符而不会导致故障。比如 C 语言的字符串以 \0 作为结尾不允许字符串中间出现\0, 而 Go 语言的 string 则允许出现 \0,我们说 Go 语言的 string 是二进制安全的,而 C 语言字符串不是二进制安全的。


    RESP 定义了5种格式, 通过第一个字符来表示格式:

    • 简单字符串(单行字符串, Simple String): 服务器用来返回简单的结果,比如"OK"。非二进制安全,且不允许换行。
    • 错误信息(Error): 服务器用来返回简单的错误信息,比如"ERR Invalid Synatx"。非二进制安全,且不允许换行。
    • 整数(Integer): llen、scard 等命令的返回值, 64位有符号整数。
    • 字符串(多行字符串,Bulk String): 二进制安全字符串, 比如 get 等命令的返回值。
    • 数组(Array, 又称 Multi Bulk Strings): Bulk String 数组,客户端发送指令以及 lrange 等命令响应的格式。

    # 简单字符串(Simple String)

    Simple Strings用于服务端对一些客户端命令的响应

    格式:"+"开头 "\r\n"结尾,中间内容不能含有'\r'或'\n'

    # set命令得到响应
    127.0.0.1:6379> set name Foo
    OK
    # 服务端返回完整内容:"+OK\r\n“
    # 退出命令
    127.0.0.1:6379> quit
    # 服务端返回的完整内容:+OK\r\n
    
    1
    2
    3
    4
    5
    6
    7

    Simple Strings的结构是非常简单的,而且不是二进制安全的;所以只会在服务端的简单内容返回。只是GET、MGET等命令的内容返回会用Buik Strings。

    # 错误信息(Error)

    Errors 用于服务端对客户端一些错误命令的返回内容

    格式:"-"开头 "\r\n"结尾

    # 执行不存在的命令
    127.0.0.1:6379> gee name
    (error) ERR unknown command 'gee'
    # 服务端返回完整内容:"-ERR unknown command 'gee'\r\n"
    # 错误的类型操作
    127.0.0.1:6379> set name Bob
    OK
    127.0.0.1:6379> zadd name 1 Foo
    (error) WRONGTYPE Operation against a key holding the wrong kind of value
    # 服务端返回完成内容:"-WRONGTYPE Operation against a key holding the wrong kind of value\r\n"
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    从例子中可以看出Erorrs响应中间部分的内容由两部分构成:大写代表错误类型,消息的表示错误详情。即-Error message\r\n

    # 整数(Integer)

    用于需要返回整数内容的命令,比如:INCR、LLEN等

    格式:":"开头,\r\n结尾,中间部分必须是有效的整数

    # incr
    127.0.0.1:6379> set count 1
    OK
    127.0.0.1:6379> incr count
    (integer) 2
    # 服务端返回完整内容:":2\r\n"
    # lpush llen del
    127.0.0.1:6379> lpush userList Bob
    (integer) 1
    127.0.0.1:6379> llen userList
    (integer) 1
    # 服务端返回完整内容:":1\r\n",代表列表中当前元素书,数量
    # del
    127.0.0.1:6379> del userList
    (integer) 1
    # 服务端返回完整内容:":1\r\n", 含义是执行成功
    # exists
    127.0.0.1:6379> set name Bob
    OK
    127.0.0.1:6379> exists name2
    (integer) 0
    # 服务端返回完整内容:":0\r\n",含义是不存在
    127.0.0.1:6379> exists name
    (integer) 1
    # 服务端返回完整内容:":1\r\n",含义是存在
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25

    这些命令的响应内容都是使用Integers:SETNX, DEL, EXISTS, INCR, INCRBY, DECR, DECRBY, DBSIZE, LASTSAVE, RENAMENX, MOVE, LLEN, SADD, SREM, SISMEMBER, SCARD

    # 字符串(Bulk String)

    用来传输二进制安全的字符内容,最大长度是512MB

    格式:'$'开头,后跟整数代表真正字符长度,然后\r\n,后面接真正的字符串内容,最后\r\n结尾,例:"$6\r\nfoobar\r\n"

    正常返回

    127.0.0.1:6379> set name foo
    OK
    127.0.0.1:6379> get name
    "foo"
    # 服务端返回完整内容:"$3\r\nfoo\r\n"
    
    1
    2
    3
    4
    5

    空字符串返回

    127.0.0.1:6379> set name ""
    OK
    127.0.0.1:6379> get name
    ""
    # 服务端返回完整内容:"$0\r\n\r\n"
    
    1
    2
    3
    4
    5

    null返回,即get不存在的key

    127.0.0.1:6379> del name
    (integer) 1
    127.0.0.1:6379> get name
    (nil)
    # 服务端返回完整内容:"$-1\r\n"
    
    1
    2
    3
    4
    5

    当服务器返回Null Bulk Strings时,客户端库应该转换为Null对象返回,而不要返回空字符。空字符串和nil是两个含义,空字符串代表键的值为'',nil代表键不存在。

    # Bulk String 数组

    用作客户端向服务端发送命令时的内容格式,也用于服务端对一些命令的内容格式,如:LRANGE

    格式:"*"开头,后跟整数表示数组长度,然后\r\n,后面是数组中的每个元素,他们可以是任意RESP类型(上面提到的Intergers、Bulk String等,格式如上),他们之间用\r\n分割,结尾\r\n

    来看看set name Foo这条命令,client是怎么传给server的

    127.0.0.1:6379> set name Foo
    OK
    # 客户端发的完整内容"*3\r\n$3\r\nset\r\n$4\r\nname\r\n$3\r\nFoo\r\n"
    
    1
    2
    3
    字段 解析
    *3 数组长度为3
    \r\n 分割符
    $3 第一个字符串长度为3
    \r\n 分割符
    set 具体内容set
    \r\n 分割符
    $4 第二个字符串长度为4
    \r\n 分割符
    name 具体内容name
    \r\n 分割符
    $3 第三个字符串长度为3
    \r\n 分割符
    Foo 具体内容Foo
    \r\n 结尾

    接着看看mget name name1这条命令发出后,server返回的内容

    127.0.0.1:6379> mget name name2
    1) "Foo"
    2) (nil)
    # 服务端返回完成内容:*2\r\n$3\r\nFoo\r\n$-1\r\n"
    
    1
    2
    3
    4
    字段 解析
    *2 数组长度为2
    \r\n 分割符
    $3 第一个字符串长度为3
    \r\n 分割符
    Foo 具体内容Foo,即刚才set name Foo命令生效结果
    \r\n 分割符
    $-1 第二个字符串长度为-1,表示nil,不存在
    \r\n 结尾

    null数组表示

    127.0.0.1:6379> blpop foo 1
    (nil)
    # 服务端返回完成内容: "*-1\r\n"
    同样,客户端库也要区别null数组和空数组的区别。
    
    1
    2
    3
    4
    #Redis
    上次更新: 2022/12/01, 11:09:34
    Redis中lua脚本使用
    Redis性能测试Redis-benchmark

    ← Redis中lua脚本使用 Redis性能测试Redis-benchmark→

    最近更新
    01
    常用游戏反外挂技术总结
    11-27
    02
    Golang开发实践万字总结
    11-11
    03
    Redis万字总结
    10-30
    更多文章>
    Theme by Vdoing | Copyright © 2011-2022 Ravior | 粤ICP备17060229号-3 | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式