Redis 通信协议

来源:互联网 发布:淘宝助理怎么导入模板 编辑:程序博客网 时间:2024/06/05 14:08

客户端和服务器通过 TCP 连接来进行数据交互, 服务器默认的端口号为 6379 客户端和服务器发送的命令或数据一律以 \r\n(CRLF)结尾。Redis 服务器通信协议中, 所有发送至 Redis 服务器的参数都是二进制安全(binary safe)的。

形式:                                                    举例:*<参数数量> CR LF                                        *3$<参数 1 的字节数量> CR LF                                $3<参数 1 的数据> CR LF                                     SET...                                                      $4$<参数 N 的字节数量> CR LF                                name<参数 N 的数据> CR LF                                     $8                                                         zhangsan这个命令的实际协议值如下:"*3\r\n$3\r\nSET\r\n$4\r\nname\r\n$8\r\nzhangsan\r\n"

Jedis - Redis通信协议的实现


Redis 命令会返回多种不同类型的回复:

"+": 状态回复(status reply)

    状态回复通常由那些不需要返回数据的命令返回,这种回复不是二进制安全的,它也不能包含新行。
    eg:        cli: set name zhangsan        server: +OK

"-": 错误回复(error reply)

    错误回复只在某些地方出现问题时发送: 比如说, 当用户对不正确的数据类型执行命令, 或者执行一个不存在的命令。
    ERR 是一个通用错误,而 WRONGTYPE 则是一个更特定的错误。 一个客户端实现可以为不同类型的错误产生不同类型的异常, 或者提供一种通用的方式, 让调用者可以通过提供字符串形式的错误名来捕捉(trap)不同的错误。
    eg:        cli: incr name        server: -ERR value is not an integer or out of range

":": 整数回复(integer reply)

    整数回复就是一个以 ":" 开头, CRLF 结尾的字符串表示的整数。
    eg:        cli: exists name        server: :1

"$": 批量回复(bulk reply)

    服务器使用批量回复来返回二进制安全的字符串,字符串的最大长度为 512 MB。
    eg:        cli: get name        server: $8\r\nzhangsan\r\n
    空批量回复:
    如果被请求的值不存在, 那么批量回复会将特殊值 -1 用作回复的长度值。当请求对象不存在时,客户端应该返回空对象,而不是空字符串。
    eg:        cli: get age        server: $-1

"*": 多条批量回复(multi bulk reply)

    多条批量回复是由多个回复组成的数组, 数组中的每个元素都可以是任意类型的回复, 包括多条批量回复本身。
    eg:        cli: lrange mylist 0 3        server: *4\r\n                :1\r\n                :2\r\n                :3\r\n                $3\r\n                foo\r\n
    多条批量回复也可以是空白的,
    eg:        cli: lrange mylist 7 8        server: *0\r\n
    无内容的多条批量回复(null multi bulk reply)也是存在的, 比如当 BLPOP 命令的阻塞时间超过最大时限时, 它就返回一个无内容的多条批量回复, 这个回复的计数值为 -1 :
    eg:        cli: blpop key 1        server: *-1\r\n

    多条批量回复中的元素可以将自身的长度设置为 -1 , 从而表示该元素不存在, 并且也不是一个空白字符串(empty string)。

    通过检查服务器发回数据的第一个字节, 可以确定这个回复类型。


多命令和流水线:

       客户端可以通过流水线, 在一次写入操作中发送多个命令:
               在发送新命令之前, 无须阅读前一个命令的回复。
               多个命令的回复会在最后一并返回。
       redis 是一个 cs 模式的 tcp server,使用和 http 类似的请求响应协议。一个 client 可以通过一个 socket 连接发起多个请求命令。每个请求命令发出后 client 通常会阻塞并等待 redis 服务处理, redis 处理完后请求命令后会将结果通过响应报文返回给 client。基本的通信过程如下:
    Client: INCR X    Server: 1    Client: INCR X    Server: 2    Client: INCR X    Server: 3    Client: INCR X    Server: 4
       基本上四个命令需要 8 个 tcp 报文才能完成。由于通信会有网络延迟,假如从 client 和 server之间的包传输时间需要 0.125秒。那么上面的四个命令 8 个报文至少会需要 1 秒才能完成。这样即使 redis 每秒能处理 100 个命令,而我们的 client也只能一秒钟发出四个命令。这显示没有充分利用 redis 的处理能力,怎么样解决这个问题呢? 我们可以利用 pipeline的方式从client 打包多条命令一起发出,不需要等待单条命令的响应返回,而redis服务端会处理完多条命令后会将多条命令的处理结果打包到一起返回给客户端。通信过程如下
    Client: INCR X    Client: INCR X    Client: INCR X    Client: INCR X    Server: 1    Server: 2    Server: 3    Server: 4
       假设不会因为 tcp 报文过长而被拆分。可能两个 tcp 报文就能完成四条命令,client 可以将四个 incr 命令放到一个 tcp 报文一起发送,server 则可以将四条命令的处理结果放到一个 tcp报文返回。通过 pipeline 方式当有大批量的操作时候,我们可以节省很多原来浪费在网络延迟的时间,需要注意到是用 pipeline 方式打包命令发送, redis 必须在处理完所有命令前先缓存起所有命令的处理结果。打包的命令越多,缓存消耗内存也越多。所以并不是打包的命令越多越好。具体多少合适需要根据具体情况测试。

Redis命令参考>>通信协议

0 0
原创粉丝点击