消息通知
任务队列
优点:
1.松耦合 2.易于扩展
BRPOP
功能:
当列表中没有元素时BRPOP命令会一直阻塞住连接,直到有新元素加入.
- BRPOP接受两个参数,第一个是键名,第二个是超时时间,单位是秒.当超过了此时间仍然没有获得新元素就回返回nil.
当超时时间为0时,表示不限制等待的时间,即如果没有新元素加入列表就会永远阻塞下去 - 当获得一个元素后BRPOP命令返回两个值,分别是键名和元素值.
打开两个实例:
redisA> BRPOP queue 0 这时会陷入阻塞状态
redisB> LPUSH queue task 实例B向queue中加入一个元素
LPUSH命令执行完后实例A马上就返回了结果 "queue" "task"
- 除了BRPOP命令从队列右侧取数据外,BLPOP从队列左侧取值
优先级队列
- BRPOP命令可以接收多个键,其完整的格式为BLPOP key [key…] timeout
例: BLPOP queue:1 queue:2 queue:3
不论queue:3,queue:2中有多少值,都会优先弹出最前面的key值的队列中的值,由此可以配置取值优先级
"发布/订阅"模式
- 发布者发布消息(返回值表示接收到这条消息的订阅者数量)
publish channel message
- 订阅频道
subscribe channel_name channel_name channel_name...
进入订阅状态客户端可能收到三种类型的回复,每种类型包含3个值,第一个是消息的类型,根据消息类型的不同,第二,三个值的含义也不同,
消息类型取值
- subscribe.表示订阅成功的反馈信息,第二个值是订阅成功的频道名称,第三个值是当前客户端订阅的频道数量
- message.这个类型表示接收到的消息,第二个值表示产生消息的频道名称,第三个值是消息的内容
- unsubscribe.表示成功取消订阅某个频道.第二个值是对应的频道名称,第三个值是当前客户端订阅的频道数量,当此值为0时客户端会退出订阅状态,
之后就可以执行其他非"发布/订阅"模式的命令了
按照规则订阅
psubscribe channel.?* 订阅指定的规则
- channel.?*可以匹配channel.1和channel.10,但是不会匹配channel.
- 收到的结果为第一个值"pmessage"是通过psubscribe命令订阅频道得到的
- 第二个值"channel.?*" 表示订阅时使用的通配符
- 第三个值表示实际收到信息的频道命令
- 第四个值则是消息内容
注意:
- 使用PSUBSCRIBE命令可以重复订阅一个频道,如某客户端执行PSUBSCRIBE channel.? channel.?*的话,向channel1.10发送命令该客户端也会收到两个消息,
而同时PUBLISH命令返回的值也是2而不是1. - 如果有另一个客户端执行了SUBSCRIBE channel.10和PSUBSCRIBE channel.?*的话,向channel.10发送该命令该客户端也会收到两条消息
(但是是两种类型:message和pmessage),同时PUBLISH命令会返回2 - PUNSUBSCRIBE命令可以退订指定的规则,用法是PUNSUBSCRIBE pattern pattern …没有参数会退订所有规则
- 使用PUNSUBSCRIBE只能退订通过PSUBSCRIBE命令订阅的规则,不会影响SUBSCRIBE命令订阅的频道;UNSUBSCRIBE同理;
- 使用PUNSUBSCRIBE命令退订某个规则是时不会将其中的通配符展开,而是进行严格的字符串匹配,所以PUNSUBSCRIBE * 无法退订channel.*规则,
而是必须使用 PUNSUBSCRIBE channel.*才能退订
管道
- 通过管道可以一次性发送多条命令并在执行完后一次性将结果返回,当一组命令中每条命令都不依赖于之前命令的执行结果时,就可以将这组命令一起通过管道发出,
- 管道通过减少客户端与Redis的通信次数来实现降低往返时延累计值的目的
## python使用Redis
# 导入redis包
import redis
# 创建一个默认连接到127.0.0.1,端口为6379的redis连接
r = redis.StrictRedis()
# 也可以显示的指定需要连接的地址
r = redis.StrictRedis(host='127.0.0.1', port=6379, db=0)
# 使用set和get
r.set('foo', 'bar')
r.get('foo')
# 使用hmset和hset
#hset参数为(name, key, value)
r.hset('dict', 'name', 'bob')
# hmset参数为(key, mapping)
r.hmset('dict', {'name': 'bob', 'color': 'red'})
r.hgetall('dict')
# 使用事务
pipe = r.pipeline()
pipe.set('foo', 'bar')
pipe.get('foo')
result = pipe.execute() # result == [True, b'bar']
# 使用管道 管道的使用方式和事务相同,只不过需要在创建时加上参数transaction=False
pipe = r.pipeline(transaction=False)
# 事务和管道都支持链式调用
result = r.pipeline().set('foo', 'bar').get('foo').execute()