缓存学习(七):Redis的高级机制:管道、事务、脚本、发布订阅、持久化

目录

1.管道

1.1 RESP

1.2 通过管道交互

2 事务操作

3.脚本

4. 发布/订阅模式

5.持久化

5.1 RDB

5.2 AOF


1.管道

1.1 RESP

Redis的协议称为RESP,它将协议数据分为不同类型,根据数据的首字符决定,不过所有类型的数据均以CRLF(即“\r\n”)结束。

1)简单字符串

首字符为“+”,后续为字符串内容,字符串内容不能包括'\r'或'\n'。例如“+OK\r\n”,经过客户端转换就变成了“OK”。由于简单字符串没有转义的情况,所以反序列化就是直接把“+”和“\r\n”之间的部分复制出去。

2)块字符串

如果发送的字符串本身包含了'\r'或'\n',就不能使用简单字符串,此时有两种解决方案:一是加入转义机制,这种方式效率比较低;二是在字符串前/后加上一个数字,表示整个字符串的长度。Redis使用了后者。块字符串的首字符是'$',后面跟着整个字符串的长度,以“\r\n”分隔后,跟上字符串内容,最后以“\r\n”结尾。例如:“$12\r\nhello\r\nworld\r\n”转换后就是:

hello
world

如果字符串长度为0,说明是空字符串,如果为-1("$-1\r\n"),则说明是null

3)错误字符串

正常的字符串是“+”开头,所以错误字符串就是“-”开头,剩下的和简单字符串一样

4)数字

以“:”开头,紧跟着数字本身,以“\r\n”结尾

5)数组

以“*”开头,紧跟着数组长度,类似于块字符串,长度为0代表空数组,为-1代表null,数组内容夹在两个“\r\n”中间,每一个数组元素都是这五种类型的数据,例如:"*2\r\n+hello\r\n+world\r\n"代表["hello","world"],数组内元素类型可以不一样,也支持嵌套数组。

 

客户端在向服务端发送数据时,参数以块字符串的形式发送,命令本身因为不属于以上任何类型,所以以原型发送

服务器向客户端发送消息时,有两种情况:第一种是对客户端的命令返回响应,可以返回以上五种类型;第二种是对Pub/Sub模式的订阅者推送消息,此时以数组类型发送。

1.2 通过管道交互

在Linux中,管道是进程间通信的重要手段,可以让前一条命令的结果传递给下一条命令作为参数,但是Redis的管道和Linux的不太一样,它的作用是将一批命令序列化地发送到服务端,执行后再将结果集序列化发送回客户端,从而节约网络I/O的时间。

Redis是单线程架构,即一次只能处理一条命令,在串行实现中,客户端命令的执行有如下四个步骤:

  1. 命令发送
  2. 命令排队
  3. 命令执行
  4. 返回结果

该实现的优点在于简单,缺点则是效率低,因为每一条命令必须等待前一条命令完全执行后才会执行,同样地,从客户端角度来看,每一条命令的发送都需要前一条命令的响应被接收,导致吞吐量很低,尤其是内存速度比网络I/O快太多,会导致客户端空等待。

为了解决这个问题,Redis提供了两种方案:

第一种就是如mget、mset这样的批量操作,这种操作具有很多优点,如原子执行、原生支持等,缺点也很明显,并不是所有操作都有批量版本;

第二种就是管道机制,Redis管道可以将一批命令一次性发送出去,和原生批量操作的区别在于:首先,管道不是原子操作;其次,批量操作是对多个key执行相同操作,而管道可以将不同的操作封装成一批;最后,管道的实现需要客户端和服务端共同完成。

对于Redis自带的客户端,即redis-cli,在启动时加上--pipe选项即可使用pipe机制,例如:

root@Yhc-Surface:~# echo -en '*3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n*2\r\n$4\r\nincr\r\n$9\r\ntestcount\r\
n' | redis-cli --pipe
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 2

该命令将 set hello world 和 incr testcount 两个命令合并,通过管道发送给服务端,美中不足的是看不到服务端响应内容,下面的用法可以看到服务端响应:

root@Yhc-Surface:~# printf '*3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n*2\r\n$4\r\nincr\r\n$9\r\ntestcount\r\n'
 | nc localhost 6379
+OK
:2

可以看到,服务端返回了一条简单字符串和一个数字。

现在计算pipeline的性能提升幅度:

对于串行模式,每一条命令都有两倍的网络延迟RTT(一收一发),还要加上客户端和服务端对命令的处理时间,分别设为m和n,则其吞吐量公式为:

TPS=\frac{1}{2*RTT+m+n}

对于管道模式,设一批执行了k条命令,仍然只有两倍的网络延迟,不过客户端和服务端的处理时间变成了k*m、k*n,即:

TPS=\frac{k-2*RTT}{k*(m+n)}

当k足够大时,可以忽略网络延迟,即TPS=1/(m+n)。如果假设网络I/O所需时间是命令处理时间的10倍,那么使用管道最大可以将

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值