今天在整理以前开发相关时的一些资料,其中对于redis protocol的解析有些小记录,记录在此:
一.reidis client-server协议是有如下特点
1.实现简单
2.能够被计算机快速解析。
3.使用者也容易理解二.通信
client与redis server建立TCP连接,每个命令与数据传送最后都以\r\n结尾。
Redis跟据不同的命令进行不同的回复。redis server回复的内容类型通过第一个参数可以判断:
1."+"号开头表示单行字符串的回复 如:+OK
2."-"号开头表示错误的信息回复。 如:-wrong date type
3.":"号开头表示一个整数回复。 如":0\r\n"
4."$"号开头表示一个批量的回复。 如GET mykey 返回$6\r\nfoobar\r\n 其中6为字节数,foobar为实现的字符串数据。
5."*"号开头表示多个批量回复。
批量回复
对于$得到单个批量的回复,如果请求不存在数据块,返回$-1,这种情况对于客户端API返回的是null对象还不是空串.
多个批量回复
例如:
C: LRANGE mylist 0 3
s: *4
s: $3
s: foo
s: $3
s: bar
s: $5
s: Hello
s: $5
s: World
参上返回四个参数:
*4\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$5\r\nHello\r\n$5\r\nWorld\r\n
对于LRANGE nokey0 1
返回*0,此情况说明key不存在,返回空的list,而对于命令超时异常时,此时返回*-1.
对于client发送给server端的指令也是跟以上相关组装指令的方式一样,相关指令的name被以String.encode序列化,传送到server,然后相应的解析。
从以上可以看到,redis的server与client通信协议相对而言很简单,相关client的编写其实也很简单。
三.谈谈zipmap与ziplist编码方式
对于redis中的hash结构会使用zipmap编码格式,而ziplist会采用ziplist编码格式,而其中主要通过
hash-max-zipmap-entries 64 hash-max-zipmap-value 512
与
list-max-ziplist-entries 64 list-max-ziplist-value 512以上两组参数控制,当结构的数量小于64,数据value值小于512时,可以采用一维数组的方式来存储相应的数据,而且一维数组采用了Varint编码方式,这样的话对于通用数据,会节省内存空间的开销。
在此值得说明的,以上参数是可以配制。
另外由于配制的参数不要过大,都是常数,所以在get操作时虽然是O(n)的开销,但也会很快。
对于Varint编码方式的在此简单介绍下:
Redis使用了跟protobuf一样的编码方式:Varint中的每个 byte 的最高位 bit 有特殊的含义,如果该位为 1,表示后续的 byte 也是该数字的一部分,如果该位为 0,则结束。其他的 7 个 bit 都用来表示数字。因此小于 128 的数字都可以用一个 byte表示。大于 128 的数字,比如 300,会用两个字节来表示:1010 1100 0000 0010。基于以上方式,可以节省ziplist与zipmap存储占用空间。(当然,在可配制下的存储数下,使用一维数组存储,才是这两种结构存储的关键,所以数据结构设计时需要考虑这些)