Redis发布消息模式
生产消费模型
Redis发布消息通常有两种模式:
1:队列模式(queuing)
2:发布-订阅模式(publish-subscribe)
任务队列:顾名思义,就是“传递消息的队列”。与任务队列进行交互的实体有两类,一类是生产者(producer),另一类则是消费者(consumer)。生产者将需要处理的任务放入任务队列中,而消费者则不断地从任务独立中读入任务信息并执行。
任务队列的好处:
松耦合。
生产者和消费者只需按照约定的任务描述格式,进行编写代码。
易于扩展。
多消费者模式下,消费者可以分布在多个不同的服务器中,由此降低单台服务器的负载。
其实从publish-subscribe的机制来看,它更像是一个广播系统,多个Subscriber可以订阅多个Channel,多个Publisher可以往多个Channel中发布消息。可以这么简单的理解:
Subscriber:收音机,可以收到多个频道,并以队列方式显示
Publisher:电台,可以往不同的FM频道中发消息
Channel:不同频率的FM频道
--------------------------------------------------------------------------------------------------------------------------------
(1) 一个Publisher,多个Subscriber模型
如下图所示,可以作为消息队列或者消息管道。
主要应用:通知、公告
(2) 多个Publisher,一个Subscriber模型
可以将PubSub做成独立的HTTP接口,各应用程序作为Publisher向Channel中发送消息,Subscriber端收到消息后执行相应的业务逻辑,比如写数据库,显示等等。
主要应用:排行榜、投票、计数。
(3) 多个Publisher,多个Subscriber模型
故名思议,就是可以向不同的Channel中发送消息,由不同的Subscriber接收。
主要应用:群聊、聊天。
发布订阅实践:
PUBLISH channel msg
将信息 message 发送到指定的频道 channel
SUBSCRIBE channel [channel ...]
订阅频道,可以同时订阅多个频道
UNSUBSCRIBE [channel ...]
取消订阅指定的频道, 如果不指定频道,则会取消订阅所有频道
PSUBSCRIBE pattern [pattern ...]
订阅一个或多个符合给定模式的频道,每个模式以 * 作为匹配符,比如 it* 匹配所 有以 it 开头的频道( it.news 、 it.blog 、 it.tweets 等等), news.* 匹配所有 以 news. 开头的频道( news.it 、 news.global.today 等等),诸如此类
PUNSUBSCRIBE [pattern [pattern ...]]
退订指定的规则, 如果没有参数则会退订所有规则
PUBSUB subcommand [argument [argument ...]]
查看订阅与发布系统状态
注意:使用发布订阅模式实现的消息队列,当有客户端订阅channel后只能收到后续发布到该频道的消息,之前发送的不会缓存,必须Provider和Consumer同时在线。
发布订阅例子:
窗口1: 订阅zhangsan频道
127.0.0.1:6379> SUBSCRIBE zhangsan
窗口2: 给zhangsan频道发送消息,此时窗口1会实时显示出消息出来
127.0.0.1:6379> PUBLISH zhangsan "jin tian zhen kaixin!"
订阅多频道:
窗口1: 订阅多个zhangsan* 频道,比如zhangsan01 zhangsan02
127.0.0.1:6379> PSUBSCRIBE zhangsan*
窗口2: 给zhangsan*频道发送消息,此时窗口1会实时显示出消息出来
127.0.0.1:6379> PUBLISH zhangsan01 "jintian zhennanshou "
127.0.0.1:6379> PUBLISH zhangsan02 "jintian zhennanshou "
客户端在执行订阅命令之后进入了订阅状态,只能接收 SUBSCRIBE 、PSUBSCRIBE、 UNSUBSCRIBE 、PUNSUBSCRIBE 四个命令。 开启的订阅客户端,无法收到该频道之前的消息,因为 Redis 不会对发布的消息进行持久化。 和很多专业的消息队列系统(例如Kafka、RocketMQ)相比,Redis的发布订阅略显粗糙,例如无法实现消息堆积和回溯。但胜在足够简单,如果当前场景可以容忍的这些缺点,也不失为一个不错的选择。
------redis 事务--------
redis中的事务跟关系型数据库中的事务是一个相似的概念,但是有不同之处。关系型数据库事务执行失败后面的sql语句不在执行,而redis中的一条命令执行失败,其余的命令照常执行。
redis中开启一个事务是使用multi,相当于begin\start transaction,exec提交事务,discard取消队列命令(非回滚操作)。
开启事务功能时(multi)
multi
command1
command2
command3
command4
4条语句作为一个组,并没有真正执行,而是被放入同一队列中。
如果,这时候执行discard,会直接丢弃队列中所有的命令,而不是做回滚。
exec
当执行exec时,对列中所有操作,要么全成功要么全失败
----------
127.0.0.1:6379> set a b
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set a b
QUEUED
127.0.0.1:6379> set c d
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
Redis中事务中的锁机制:
举例:我正在买票
Ticket -1 , money -100
而票只有1张, 如果在我multi之后,和exec之前, 票被别人买了---即ticket变成0了.
我该如何观察这种情景,并不再提交
悲观的想法:
世界充满危险,肯定有人和我抢, 给 ticket上锁, 只有我能操作. [悲观锁]
乐观的想法:
没有那么人和我抢,因此,我只需要注意,
--有没有人更改ticket的值就可以了 [乐观锁]
Redis的事务中,启用的是乐观锁,只负责监测key没有被改动.
发布一张票
set ticket 1
窗口1:先观察ticket的值,然后正常购买,如果此时ticket是0了,就会提示失败,否则成功
watch ticket
multi
set ticket 0 1---->0
窗口2:直接提交把票买了。
multi
set ticket 0
exec
窗口1:
Exec
--------------------------------
Redis 常用管理命令
Info
Clinet list
Client kill ip:port
config get *
CONFIG RESETSTAT 重置统计
CONFIG GET/SET 动态修改
Dbsize
FLUSHALL 清空所有数据
select 1
FLUSHDB 清空当前库
MONITOR 监控实时指令
SHUTDOWN 关闭服务器
关闭数据库:
redis-cli -a root shutdown
------- ---扩展 slow慢日志查询---------------------------
慢日志查询
Slow log 是 Redis 用来记录查询执行时间的日志系统。
slow log 保存在内存里面,读写速度非常快
可以通过改写 redis.conf 文件或者用 CONFIG GET 和 CONFIG SET 命令对它们动态地进行修改
slowlog-log-slower-than 10000 超过多少微秒
CONFIG SET slowlog-log-slower-than 100
CONFIG SET slowlog-max-len 1000 保存多少条慢日志
CONFIG GET slow*
SLOWLOG GET
SLOWLOG RESET