04: redis 消费模式 和 事务 - 扩展slow日志

Redis发布消息模式

生产消费模型

 04: redis 消费模式 和 事务 - 扩展slow日志

Redis发布消息通常有两种模式:

1:队列模式(queuing

2:发布-订阅模式(publish-subscribe)

任务队列:顾名思义,就是“传递消息的队列”。与任务队列进行交互的实体有两类,一类是生产者(producer),另一类则是消费者(consumer)。生产者将需要处理的任务放入任务队列中,而消费者则不断地从任务独立中读入任务信息并执行。

任务队列的好处:

松耦合。

生产者和消费者只需按照约定的任务描述格式,进行编写代码。

易于扩展。

多消费者模式下,消费者可以分布在多个不同的服务器中,由此降低单台服务器的负载。

 

 

其实从publish-subscribe的机制来看,它更像是一个广播系统,多个Subscriber可以订阅多个Channel,多个Publisher可以往多个Channel中发布消息。可以这么简单的理解:

Subscriber:收音机,可以收到多个频道,并以队列方式显示

Publisher:电台,可以往不同的FM频道中发消息

Channel:不同频率的FM频道

--------------------------------------------------------------------------------------------------------------------------------

(1) 一个Publisher,多个Subscriber模型

如下图所示,可以作为消息队列或者消息管道。

主要应用:通知、公告

 04: redis 消费模式 和 事务 - 扩展slow日志

 

 

(2) 多个Publisher,一个Subscriber模型

可以将PubSub做成独立的HTTP接口,各应用程序作为PublisherChannel中发送消息,Subscriber端收到消息后执行相应的业务逻辑,比如写数据库,显示等等。

主要应用:排行榜、投票、计数。

 04: redis 消费模式 和 事务 - 扩展slow日志

 

 

(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后只能收到后续发布到该频道的消息,之前发送的不会缓存,必须ProviderConsumer同时在线。

 

发布订阅例子:

窗口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 PSUBSCRIBEUNSUBSCRIBE PUNSUBSCRIBE 四个命令。 开启的订阅客户端,无法收到该频道之前的消息,因为 Redis 不会对发布的消息进行持久化。 和很多专业的消息队列系统(例如KafkaRocketMQ)相比,Redis的发布订阅略显粗糙,例如无法实现消息堆积和回溯。但胜在足够简单,如果当前场景可以容忍的这些缺点,也不失为一个不错的选择。

 

------redis 事务--------

redis中的事务跟关系型数据库中的事务是一个相似的概念,但是有不同之处。关系型数据库事务执行失败后面的sql语句不在执行,而redis中的一条命令执行失败,其余的命令照常执行。

redis中开启一个事务是使用multi,相当于begin\start transactionexec提交事务,discard取消队列命令(非回滚操作)。

 04: redis 消费模式 和 事务 - 扩展slow日志

 

 

开启事务功能时(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的值,然后正常购买,如果此时ticket0了,就会提示失败,否则成功

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