Redis发布订阅及事务管理

目录

一、发布订阅

1.1、常用命令

1.2、示例演示

二、事务管理

2.1 Multi、Exec、Discard

2.2 示例演示

2.3 事务的错误处理

2.4 事务的冲突问题

2.4.1 事务场景

2.4.2 悲观锁

2.4.3 乐观锁

2.4.4 事务解决冲突—WATCH

2.4.5 UNWATCH

2.4.6 Redis事务的三个特性


一、发布订阅

        Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。Redis 客户端可以订阅任意数量的频道。下图展示了频道 channel1 ,以及订阅这个频道的三个客户端 —— client1 、client2 和 client3 之间的关系:

Redis发布订阅及事务管理_第1张图片

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

Redis发布订阅及事务管理_第2张图片

1.1、常用命令

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

1.2、示例演示

创建四个客户端Client1------Client 4 :

#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一次

二、事务管理

        Redis 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。Redis 事务的主要作用就是串联多个命令防止别的命令插队。

2.1 Multi、Exec、Discard

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

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

Redis发布订阅及事务管理_第3张图片

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

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

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

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

2.2 示例演示

#组队阶段成功、提交成功的情况
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"

2.3 事务的错误处理

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

Redis发布订阅及事务管理_第4张图片

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

Redis发布订阅及事务管理_第5张图片

2.4 事务的冲突问题

2.4.1 事务场景

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

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

Redis发布订阅及事务管理_第6张图片

2.4.2 悲观锁

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

Redis发布订阅及事务管理_第7张图片

2.4.3 乐观锁

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

Redis发布订阅及事务管理_第8张图片

2.4.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

2.4.5 UNWATCH

用于取消命令对所有key的监视,如果在执行watch命令之后,Exec或DisCard命令先被执行的话,那么就不需要再次执行unwatch。

2.4.6 Redis事务的三个特性

1、单独的隔离操作

事务中所有命令都会序列化,按顺序执行。事务在执行过程中,不会被其他客户端发来的请求锁打断。

2、没有隔离级别的概念

队列中的命令没有提交前都不会被实际执行,因为事务提交前,所有指令都是处于等待状态。

3、不保证原子性

事务中如果有一条命令执行失败,其后命令依旧会执行,并不会回滚。

你可能感兴趣的:(DATABASES,redis,数据库,缓存)