Redis发布订阅及事务管理

本文详细介绍了Redis的发布订阅模式,包括其工作原理、常用命令以及示例。同时深入探讨了Redis事务的概念,包括定义、Multi、Exec和discard命令的使用,以及事务的错误处理和冲突解决策略,如悲观锁、乐观锁和watch/unwatch机制。
摘要由CSDN通过智能技术生成

目录

1.1 发布订阅

1.1.1 什么是发布订阅

1.1.2 常用命令

1.1.3 示例演示

1.2 事务管理

1.2.1 事务定义

1.2.2 Multi、Exec、discard

1.2.3 示例

1.2.4 事务的错误处理

1.2.5 事务的冲突问题

1.2.5.1 事务场景

1.2.5.2 悲观锁

1.2.5.3 乐观锁

1.2.5.4 事务解决冲突(WATCH)

1.2.5.5 unwatch

1.2.6 Redis事务的三个特征


1.1 发布订阅

1.1.1 什么是发布订阅

        Redis发布订阅(pub/sub)是一种消息通信模式发送者(pub)发送消息,订阅者(sub)接收消息Redis客户端可以订阅任意数量的频道

img

        当有新的消息通过 PUBLISH 命令发送给频道 channel1 时,这个消息就会被发送给订阅的三个客户端

img

1.1.2 常用命令

命令语法描述
PSUBSCRIBE pattern [pattern......]订阅一个或多个符合给定模式的频道
PUBSUB subcommand [argument [argument...]]查看订阅与发布系统的状态
PUBLISH channel message将信息发送到指定的频道
PUNSUBSCRIBE [pattern [pattern......]]退订所有给定模式的频道
SUBSCRIBE channel [channel......]订阅给定的一个或者多个频道信息
UNSUBSCRIBE [channel [channel......]]退订给定的频道

1.1.3 示例演示

创建四个客户端Cli_1~Cli4

#cli1 创建订阅的频道redisChat
127.0.0.1:6379> SUBSCRIBE redisChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1

#cli2 在同一频道redisChat 发布消息
127.0.0.1:6379> PUBLISH redisChat "SendMessage_1"
(integer) 1
#此处可切换到 cli1内查看是否读取到cli2发布的消息

#cli3 在同一频道redisChat 发布消息
127.0.0.1:6379> PUBLISH redisChat "SendMessage_2"
(integer) 1
#此处可切换到 cli1内查看是否读取到cli3发布的消息

#cli4 创建订阅的频道redisChat
127.0.0.1:6379> SUBSCRIBE redisChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1

#cli3 在同一频道redisChat 发布消息
127.0.0.1:6379> PUBLISH redisChat "SendMessage_2"
(integer) 1
#此处可切换到 cli1及cli4内查看是否读取到cli3发布的消息
cli1收到3条信息 分别来自于 cli2一次  以及 cli3两次
cli4收到1条信息 cli3一次

1.2 事务管理

1.2.1 事务定义

        Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行行事务在执行的过程中,不会被其他客户端发送来的命令请求所打断

        Redis 事务的主要作用就是串联多个命令防止别的命令插队

1.2.2 Multi、Exec、discard

        从输入Multi命令开始,后面输入的数量命令都会一次进入到命令队列当中,但是不会执行,直到输入Exec后,Redis会将之前的命令队列中的命令依次执行

        组队过程中,可以通过 discard 来放弃组队

image-20220719113832106

Redis的事务可以一次执行多条命令

        批量操作在发送 Exec 命令前被放入队列缓存

        收到 Exec 命令后,进入事务执行,如果事务中有任意命令执行失败,其余的命令依旧会执行

        在事务的执行过程中,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求,不会插入到事务执行的命令序列中

1.2.3 示例

#组队阶段成功、提交成功的情况
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)> exec
1) OK
2) OK


#组队阶段报错、提交必然报错(所有数据全部回滚)
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> set k4
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379(TX)> set k5 v5
QUEUED
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.


#组队阶段成功、提交时发现组队命令有异常
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> incr k3
QUEUED
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> get k3
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
4) "v3"

1.2.4 事务的错误处理

        组队时某个命令出现了错误报告,执行时整个的队列都会被取消

image-20220719114521604

        执行时某个命令报错,则只有报错的命令不会被执行,而其他命令都会执行,不会回滚

image-20220719114548697

1.2.5 事务的冲突问题

1.2.5.1 事务场景

        有一账户余额为10000元,现在出现三个请求,第一个请求想给金额-8000元,第二个请求想给金额-5000元,第三个请求想给金额-1000元

        如果没有事务管理,则有可能出现如下场景

image-20220719121307625

1.2.5.2 悲观锁

        悲观锁(Pessimistic Lock)顾名思义,就是很悲观。每次去拿数据时都认为别人会修改,所以在每次拿数据时都会上锁,这样别人想拿到这个数据就会停顿,直到它拿到锁为止。在传统的关系型数据库内就会用到这种锁机制,比如 行锁 表锁 读锁 写锁,都是在操作之前先进行上锁处理

image-20220719121359881

1.2.5.3 乐观锁

        乐观锁(Optimistic Lock)顾名思义,就是很乐观。每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis就是利用这种check-and-set机制实现事务的

image-20220719121620157

1.2.5.4 事务解决冲突(WATCH)

        在执行multi之前,先执行 watch key1 [key2 ....] 用于指定key的监视,如果在事务执行前这些key被其他命令锁改动,那么事务将被打断

#cli1
set money 10000
#cli2
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 8000
QUEUED
#cli3
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 3000
QUEUED

#cli2
exec
#cli3
exec

1.2.5.5 unwatch

        用于取消命令对所有key的监视

        如果在执行 watch 命令之后,Exec 或 DisCard 命令先被执行的话,那么就不需要再次执行 unwatch

1.2.6 Redis事务的三个特征

单独的隔离操作事务中所有命令都会序列化,按顺序执行。事务在执行过程中,不会被其他客户端发来的请求所打断
没有隔离级别的概念队列中的命令没有提交前都不会被实际执行,因为事务提交前,所有指令都是处于等待状态
不保证原子性事务中如果有一条命令执行失败,其后命令以及会执行,并且不会回滚

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值