持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情
发布订阅
Redis 中发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接受消息。发送者(pub)不是计划发送消息给特定的订阅者(sub),而是将发布的消息分到不同的频道(channel),不需要知道具体的订阅者是谁。同样订阅者(sub)只需要去频道(channel)获取自己想要的消息即可,不需要知道这个消息来源于哪个发布者(pub)。这是不是就让发布者(pub)和订阅者(sub)高度解耦了。下面我们就一起来看看它到底是如何实现的。
Redis 发布订阅(pub/sub)简单的实现原理图如下:
实际项目开发中,我们有时候会基于 Redis 的这种发布订阅的特性,完成像上图中的多组生产者、多组消费者的场景。它实际上可以看作一种队列模型,生产者(pub)生产消息发给频道(channel),消费者(sub)从频道(channel)获取消息进行消费。这里一个消息可以被一个消费者消费,也可以被多个消费者消费。
➡️ 一个生产者,一个消费者
-
开启一个客户端作为消费者(sub)订阅消息,使用
subscribe命令:subscribe q_channel✨ 说明:
subscribe是用来订阅给定的一个或多个频道的信息。上面订阅频道的名称为q_channel。 -
重新开启一个新客户端作为生产者(pub)生产消息,使用
publish命令:📖 需求:使用
publish命令将生产的hello,redis和hello,lanqiao者两个消息发送到频道q_channel中,让消费者进行订阅。publish q_channel hello,redis✨ 说明:
pushlish是用来将消息发送给指定的频道,返回接收到信息的订阅者的数量。从上图中可以发现:
- 开启两个客户端,一个消费者(使用
subscribe命令),一个生产者(使用publish命令)。 - 在生产者分别生产了
hello,redis和hello,lanqiao这两条消息,并且将这两条消息传递给了频道q_channel。 - 消费者通过订阅频道
q_channel,消费了这两条消息。
- 开启两个客户端,一个消费者(使用
➡️ 一个生产者,多个消费者
-
开启两个客户端作为消费者(一个使用
subscribe命令订阅,一个使用psubscribe命令订阅):subscribe:用来订阅给定的一个或多个频道的信息。subscribe ch_queue1✨ 说明:这里用来订阅
ch_queue1频道的消息。subscribe:用来订阅一个或多个符合给定模式的频道。psubscribe ch*✨ 说明:这里用来订阅所有符合
ch开头的频道的消息。 -
开启一个客户端作为生产者,使用
publish命令发布消息:📖 需求:使用
publish命令将生产的hello,lan发送到频道ch_queue1,将生产的hello,redis发送到频道ch_queue2,将生产的hello,java发送到频道ch_queue3,让这些消息被消费者进行订阅。publish ch_queue1 hello,lan publish ch_queue2 hello,redis publish ch_queue3 hello,java✨ 说明:
ch_queue1频道返回值为 2,说明被两个订阅者订阅了,其余的都是被一个订阅者订阅了。从上图中可以发现:
- 开启三个客户端,两个消费者(分别使用
subscribe和psubscribe命令订阅),一个生产者(使用publish命令)。 - 在生产者分别生产了
hello,lan、hello,redis和hello,java这三条消息,并且将这三条消息分别传递给了频道ch_queue1、ch_queue2和ch_queue3。 - 其中
hello,lan被两个订阅者消费了(ch_queue1和ch*)。
- 开启三个客户端,两个消费者(分别使用
➡️ 发布订阅的其他相关命令
-
pubsub subcommand [argument [argument ...]]:查看订阅和发布系统状态。 -
punsubscribe [pattern [pattern ...]]:用于退订所有给定模式的频道。 -
unsubscribe channel [channel ...]:用于退订给定的一个或多个频道。
事务
Redis 事务可以一次执行多个命令,并且带有以下三个重要保证:
- 批量操作在发送
exec命令前被放入队列缓存。 - 收到
exec命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。 - 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。
一个事务从开始到执行主要经历以下三个阶段:开始事务、命令入队、执行事务。Redis 事务相关的操作命令主要是有:discard、exec、multi、unwatch、watch。接下来我们就一起结合这些命令来学习 Redis 事务。
➡️ Redis 事务相关操作命令
-
multi和exec:multi用于开启一个事务,它总是返回OK;exec用于执行事务块内所有的命令,返回的结果是事务块内所有的命令的返回值,按照命令执行的先后顺序排列。redis-cli --raw multi set age 40 QUEUED incr age QUEUED exec get age✨ 说明:当执行
multi执行之后,客户端可以继续向服务端发送任意多条命了,但这些命令都不会立即执行,而是被放到队列中。当执行exec命令后,所有队列中的命令才会被执行。 -
discard:取消事务,放弃执行事务块内的所有命令,它总是返回OK。✨ 说明:当执行
discard命令后,返回OK。此时事务会被放弃,事务队列会被清空,并且客户端会从事务状态中推出。 -
watch:用于监视一个或多个 key ,如果在事务执行之前 key 被其他命令所改动,那么事务将被打断。 -
unwatch:用于取消watch命令对所有 key 的监视。
➡️ 事务中的错误
-
事务在执行
exec之前,入队的命令可能会出错(全体遭殃)。✨ 说明:从 Redis 2.6.5 开始,服务器会对命令入队失败的情况进行记录,并在客户端调用
exec命令时,拒绝执行并自动放弃这个事务。 -
命令可能在
exec调用之后失败(冤头债主)。✨ 说明:在
exec命令执行之后所产生的错误, 没有对它们进行特别处理: 即使事务中有某个/某些命令在执行时产生了错误, 事务中的其他命令仍然会继续执行。