天天看点

redis 多条指令 一次操作_Redis管道-发布订阅-事务

管道(pipeline)

redis执行一次命令包括下面几个流程:

1、客户端发送命令(经过网络传输)。

2、服务端执行命令-。

3、服务端响应结果(经过网络传输)。

redis 多条指令 一次操作_Redis管道-发布订阅-事务

如上图,Redis每一次指令的发送都要经过发送指令请求、执行指令、响应结果,而这个过程中所消耗的时间大部分都是在网络传输上,所以如果能减少网络传输的次数,也就意味着性能也会大幅度提高。

redis 多条指令 一次操作_Redis管道-发布订阅-事务

沿着这个思路所以就有了管道的概念,管道可以在我们批量操作一些指令的时候,不需要每个指令都依次的去进行发送、执行、响应的流程,而是把多个指令一次性发送给服务端,在服务端执行完成后,把结果统一响应给客户端,最终以达到减少网络请求从而提升了整体的效率。

redis 多条指令 一次操作_Redis管道-发布订阅-事务

使用管道技术可以显著提升Redis处理命令的速度,其原理就是将多条命令打包,只需要一次网络开销,在服务器端和客户端只需要一次请求和响应,以此来节约时间。

发布订阅

Redis里也提供了发布订阅的机制,如果一个消息想要被多个人收到,或者发消息的人不知道会有哪些人需要收到这些消息,那么Redis的发布订阅功能就可以解决这个问题。发布订阅模式是通过创建一个频道,然后消息发送者统一把对应的消息发送到这个频道里,然后频道可以支持多个订阅者进行消息订阅,订阅了该频道的订阅者都会收到发送者的消息。

redis 多条指令 一次操作_Redis管道-发布订阅-事务

在Redis客户端可通过subscribe 和 publish命令可以分别实现消息订阅和消息推送的功能,如下面,左边的客户端通过subscribe订阅了一个频道为 test的频道,然后右边的频道通过publish往test频道发送一条消息后,左边订阅了该频道的客户端就会收到消息。

redis 多条指令 一次操作_Redis管道-发布订阅-事务

Redis实现发布|订阅的原理

简单的说Redis是通过一个字典(pubsub_channels)和一个链表实现发布订阅功能的。 字典记录着Redis里面所创建的频道,然后每个频道有一个对应的链表记录着订阅了该频道的客户端。当执行publish channel message 指令时,首先会找到对应channel的频道,然后找到该频道对应的链表数据,通过遍历链表中的客户端逐一的把消息发送出去。

redis 多条指令 一次操作_Redis管道-发布订阅-事务

需要注意的是Redis实现的发布订阅模式并不能保证消息的可靠性,这主要体现在两个方面,一是客户端只有在线的情况下才会收到订阅消息,因为Redis并不会像专业的消息队列一样把消息进行持久化保存的。另外一个方面是何网络系统在执行操作时都可能会遇到断网的情况,而断线产生的连接错误通常会使得网络连接两端中的一端进行重新连接。如果客户端在执行订阅操作的过程中断线,那么客户端将会丢失在断线期间的消息。所以如果业务对于消息可靠性没有这种高的要求,那么是可以尝试Redis的发布订阅功能。

事务

Redis里也提供了事务机制,在Redis里可以通过如下方式开启和执行一个事务。

1、开启事务:
multi
           
2、发送多个指令到事务队列中
set  t1   1
 set  t2   2
 set  t3   3
           
3、执行或取消事务
exec
 discard
           

Redis开始事务后,后面的发出的指令并不会马上执行,而是会放入到一个队列里,直到输入事务指令(exec或者discard)指令才会决定对事务队列的命令进行执行或者取消。

redis 多条指令 一次操作_Redis管道-发布订阅-事务

事务中断机制(watch)

如果我们在执行事务的过程中涉及到的数据有可能会被其他地方修改,那么这个时候就有可能出现数据脏读的问题。为了解决脏读的问题,Redis提供了watch机制,watch就是事先对可能出现脏读的key进行监控,执行事务的过程中如果有其它地方对监控的key进行了数据变更,那么watch会将对应的key进行标记,那么最终在执行事务的时候会根据watch里对应key的标记来决定是否最终执行指令。

如果在客户端1执行的事务的过程中,客户端2对客户端1监控的key进行修改,那么最后事务会取消执行,整个过程如下图:

redis 多条指令 一次操作_Redis管道-发布订阅-事务

Redis事务与传统的ACID

从上面我们了解的事务来看,Redis里的事务并非我们常识里带有ACID特性的事务,相比于传统的ACID事务,Redis里的事务缺少事务的回滚机制,并没有办法实现事务的一致性、原子性。

原子性:

Redis的事务中能保证指令执行的原子性,整体事务的指令要么全部执行,要么全部不执行。

一致性:

在Redis的事务中,如果某个指令执行失败,那么后面的指令依然会执行,Redis并没有传统事务的回滚机制,所以在指令错误的情况下,是无法保证数据的一致性。

隔离性:

Redis是串行化执行事务的,多个事务同时开启时,事务的执行顺序,是以最终提交事务的顺序执行,所以Redis事务之间天然就具备隔离性。

持久性:

Redis的事务持久性由设定的持久化模式决定,只有在AOF持久化模式下并且appendfsync选项的值为always时,这时指令都将同步写入AOF文件中,此时事务具备持久性的。如果在AOF异步同步指令模式下,又或者在RDB模式下都有可能丢失指令数据,这种场景中Redis事务是不具备持久性的。