redis事务、管道及发布订阅

目录

redis事务

1、redis事务命令

2、示例

redis管道

1、管道命令

2、示例 

redis发布订阅

1、发布者(Publisher)

2、订阅者(Subscriber)

3、示例


redis事务

在Redis中,事务是一组命令的有序队列,可以一次执行多个命令,本质是一组命令的集合。一个

事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入。 

redis事务与数据库事务对比

单独的隔离操作Redis的事务仅仅是保证事务里的操作会被连续独占的执行,redis命令执行是单线程架构,在执行完事务内所有指令前是不可能再去同时执行其他客户端的请求的
没有隔离级别的概念因为事务提交前任何指令都不会被实际执行,也就不存在"事务内的查询要看到事务里的更新,在事务外查询不能看到"这种问题了
不保证原子性Redis的事务不保证原子性,也就是不保证所有指令同时成功或同时失败,只有决定是否开始执行全部指令的能力,没有执行到一半进行回滚的能力
排它性Redis会保证一个事务内的命令依次执行,而不会被其它命令插入
1、redis事务命令
DISCARD取消事务,放弃执行事务块内的所有命令。
EXEC执行所有事务块内的命令。
MULTI标记、个事务块的开始。
UNWATCH取消WATCH命令对所有key的监视。
WATCH key [key ...]监视一个(或多个)key,如果在事务执行之前这个(或这些)key被其他命令所改动,那么事务将被打断。
2、示例

正常执行:

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> set k1 1
QUEUED
127.0.0.1:6379(TX)> set k2 2
QUEUED
127.0.0.1:6379(TX)> set k3 3
QUEUED
127.0.0.1:6379(TX)> INCR count
QUEUED
127.0.0.1:6379(TX)> EXEC
1) OK
2) OK
3) OK
4) (integer) 1
127.0.0.1:6379> get k1
"1"

 放弃事务:multi  discard

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> incr count 
QUEUED
127.0.0.1:6379(TX)> discard
OK
127.0.0.1:6379> get k1
"1"

全体连坐,错一个所有的命令都不执行

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k1
"1"

冤头债主,错误的命令不执行,正确的执行

127.0.0.1:6379> del meail
(integer) 1
127.0.0.1:6379> set emial 1@qq.com
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> incr emial
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (error) ERR value is not an integer or out of range
127.0.0.1:6379> get k1
"v1"

所以事务执行时报错不会像数据库要么成功要么都不执行

watch监控:Redis使用watch来提供乐观锁定,类似于CAS(Check-and-Set)watch命令是一种乐观锁的实现,Redis在修改的时候会检测数据是否被更改,如果更改了,则执行失败

正常情况

127.0.0.1:6379> set balance 100
OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get balance
"100"
127.0.0.1:6379> watch balance
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 a1
QUEUED
127.0.0.1:6379(TX)> set balance 110
QUEUED
127.0.0.1:6379(TX)> get k1
QUEUED
127.0.0.1:6379(TX)> get balance
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) OK
3) "a1"
4) "110"

异常情况,在监控下修改


unwatch放弃监控

 注意:一旦执行了exec之前加的监控锁都会被取消掉了,当客户端连接丢失的时候(比如退出链

接),所有东西都会被取消监视。

redis管道

问题:如果同时需要执行大量的命令,那么就要等待上一条命令应答后再执行,这中间不仅仅多了RTT(Round Time Trip),而且还频繁调用系统IO,发送网络请求,同时需要redis调用多次read()和write()系统方法,系统方法会将数据从用户态转移到内核态,这样就会对进程上下文有比较大的影响。

管道(pipeline)可以一次性发送多条命令给服务端,服务端依次处理完完毕后,通过一条响应一次性将结果返回,通过减少客户端与redis的通信次数来实现降低往返延时时间。pipeline实现的原理是队列,先进先出特性就保证数据的顺序性。

1、管道命令
#docker操作
cat cmd.txt | docker exec -i redis2 redis-cli -a 123456 --pipe

#linux系统操作
cat cmd.txt | redis-cli -a 123456 --pipe
2、示例 

 将你要执行的命令写入一个文件里

管道pipeline与原生命令对比

原生批量命令是原子性(例如:mset,mget),pipeline是非原子性。

原生批量命令一次只能执行一种命令,pipeline支持批量执行不同命令。

原生批命令是服条端实现,而pipeline需要服务端与客户端共同完成。

管道pipeline与事务对比

事务具有原子性,管道不具有原子性。

管道一次性将多条命令发送到服务器,事务是一条一条的发,事务只有在接收到exec命令后才会执行,管道不会。

执行事务时会阻塞其他命令的执行,而执行管道中的命冬时不会

使用管道pipeline注意事项 

pipeline缓冲的指令只是会依次执行,不保证原子性,如果执行中指令发生异常,将会继续执行后续的指令。

使用pipeline组装的命令个数不能太多,不然数据量过大客户端阻塞的时间可能过久,同时服务端此时也被迫回复一个队列答复,占用很多内存。

redis发布订阅

Redis提供了发布订阅(Pub/Sub)模式,允许不同的客户端之间通过消息传递进行通信。在发布订阅模式中,有两个主要角色:发布者(Publisher)和订阅者(Subscriber)。

发布订阅命令

1、发布者(Publisher)

PUBLISH命令: 发布者使用PUBLISH命令将消息发送到指定的频道其中

PUBLISH channel message

channel 是消息的频道,message 是要发送的消息内容。

2、订阅者(Subscriber)

SUBSCRIBE命令: 订阅者使用SUBSCRIBE命令订阅一个或多个频道。

SUBSCRIBE channel

订阅者可以通过多次调用SUBSCRIBE命令订阅多个频道。

UNSUBSCRIBE命令: 订阅者使用UNSUBSCRIBE命令取消对一个或多个频道的订阅。

UNSUBSCRIBE [channel [channel ...]]

如果不提供频道参数,订阅者将取消对所有频道的订阅。

PSUBSCRIBE命令: 订阅者使用PSUBSCRIBE命令订阅一个或多个符合指定模式的频道。

PSUBSCRIBE pattern

PUNSUBSCRIBE命令: 订阅者使用PUNSUBSCRIBE命令取消对一个或多个符合指定模式的频道的订阅。

PUNSUBSCRIBE [pattern [pattern ...]]
3、示例

创建3个对话窗口,1号窗口订阅c1,2号窗口订阅c1,c2

#1号窗口订阅c1
127.0.0.1:6379> subscribe c1
1) "subscribe"
2) "c1"
3) (integer) 1

#2号窗口订阅c1,c2
127.0.0.1:6379> subscribe c1 c2
1) "subscribe"
2) "c1"
3) (integer) 1
1) "subscribe"
2) "c2"
3) (integer) 2

#3号窗口发布消息
127.0.0.1:6379> publish c1 hello
(integer) 2


#1号窗口收到消息
127.0.0.1:6379> subscribe c1
1) "subscribe"
2) "c1"
3) (integer) 1
127.0.0.1:6379(subscribed mode)> 
1) "message"
2) "c1"
3) "hello"


#2号窗口收到消息
127.0.0.1:6379> subscribe c1 c2
1) "subscribe"
2) "c1"
3) (integer) 1
1) "subscribe"
2) "c2"
3) (integer) 2
1) "message"
2) "c1"
3) "hello"

 在发布端查看

 PUBSUB CHANNELS:命令用于列出当前存在的频道

127.0.0.1:6379> pubsub channels
1) "c1"
2) "c2"

pubsub numsub:某个频道有几个订阅者 

127.0.0.1:6379> pubsub numsub c1
1) "c1"
2) (integer) 2

 PUBSUB NUMPAT:只统计使用PSUBSCRIBE命令执行的,返回客户端订阅的唯一模式的数量

 取消订阅

127.0.0.1:6379(subscribed mode)> unsubscribe c* c?
1) "unsubscribe"
2) "c*"
3) (integer) 1
1) "unsubscribe"
2) "c?"
3) (integer) 0

  • 25
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值