Redis是内存中的数据结构存储,用于缓存、高速数据摄取、处理消息队列、分布式锁定等等。html
与其余内存存储相比,使用Redis的优点在于它提供了持久性和数据结构,好比列表、集合、排序集合和散列。python
在这篇文章中,介绍一个Redis keyspace通知的简短概述。并演示如何配置Redis来接收它们。并展现如何在python中订阅Redis通知git
在开始以前,请安装并启动Redis服务器,以下所述:https://redis.io/topics/quickstartgithub
默认状况下,redis的通知事件是关闭的,在终端执行如下命令开启:redis
$ redis-cli config set notify-keyspace-events KEA
OK
KEA字符串表示启用了全部可能的事件。要查看每一个字符的含义,请查看文档缓存
CLI 能够在特殊模式下工做,容许您订阅一个通道以接收消息。服务器
如今检查事件是否起做用:数据结构
# 用于检查事件 # psubscribe '*'表示咱们想订阅全部带有模式*的事件 $ redis-cli --csv psubscribe '*' Reading messages... (press Ctrl-C to quit) "psubscribe","*",1
开启一个新的终端,设置一个值分布式
127.0.0.1:6379> set key1 value1
OK
在上一个终端,会看到:ide
$ redis-cli --csv psubscribe '*' Reading messages... (press Ctrl-C to quit) "psubscribe","*",1 "pmessage","*","__keyspace@0__:key1","set" "pmessage","*","__keyevent@0__:set","key1
发现通知是工做中的
Redis的键盘空间通知从2.8.0版起就可使用了。对于更改任何Redis键的每一个操做,能够配置Redis将消息发布到发布/订阅。而后能够订阅这些通知。值得一提的是,事件仅在确实修改了键的状况下才生成。例如,删除不存在的键将不会生成事件。
以上收到三个事件:
"psubscribe","*",1 "pmessage","*","__keyspace@0__:key1","set" "pmessage","*","__keyevent@0__:set","key1
事件是经过Redis的Pub/Sub层交付的。
为了订阅channel channel1和channel2,客户端发出带有通道名称的subscribe命令
第一步,须要python操做redis的包
$ pip install redis
事件循环,请看如下代码:
import time from redis import StrictRedis redis = StrictRedis(host='localhost', port=6379) # redis 发布订阅 pubsub = redis.pubsub() # 监听通知 pubsub.psubscribe('__keyspace@0__:*') # 开始消息循环 print('Starting message loop') while True: # 获取消息 message = pubsub.get_message() if message: print(message) else: time.sleep(0.01)
分析:
这是建立 `redis` 链接的代码
redis = StrictRedis(host='localhost', port=6379)
默认状况下,全部响应都以字节的形式返回。用户负责解码。若是客户机的全部字符串响应都应该被解码,那么用户能够指定decode_responses=True to StrictRedis。在这种状况下,任何返回字符串类型的Redis命令都将用指定的编码进行解码。
接下来,建立一个订阅频道并侦听新消息的pubsub对象:
pubsub = redis.pubsub() pubsub.psubscribe('__keyspace@0__:*')
继而经过一个无限循环来等待事件
while True: message = pubsub.get_message() ...
若是有数据,get_message()将读取并返回它。若是没有数据,该方法将不返回任何数据。
从pubsub实例中读取的每条消息都是一个字典,其中包含如下键:
如今启动 `python` 脚本,在终端中设置一个key值
127.0.0.1:6379> set mykey myvalue
OK
将看到脚本如下输出
$ python subscribe.py Starting message loop {'type': 'psubscribe', 'data': 1, 'channel': b'__keyspace@0__:*', 'pattern': None} {'type': 'pmessage', 'data': b'set', 'channel': b'__keyspace@0__:mykey', 'pattern': b'__keyspace@0__:*'}
注册回调函数来处理已发布的消息。消息处理程序接受一个参数,即消息。要使用消息处理程序订阅通道或模式,请将通道或模式名称做为关键字参数传递,其值为回调函数。当使用消息处理程序在通道或模式上读取消息时,将建立消息字典并将其传递给消息处理程序。在这种状况下,get_message()返回一个None值,由于消息已经被处理
import time from redis import StrictRedis redis = StrictRedis(host='localhost', port=6379) pubsub = redis.pubsub() def event_handler(msg): print('Handler', msg) pubsub.psubscribe(**{'__keyspace@0__:*': event_handler}) print('Starting message loop') while True: message = pubsub.get_message() if message: print(message) else: time.sleep(0.01)
选择是在单独的线程中运行事件循环
import time from redis import StrictRedis redis = StrictRedis(host='localhost', port=6379) def event_handler(msg): print(msg) thread.stop() pubsub = redis.pubsub() pubsub.psubscribe(**{'__keyevent@0__:expired': event_handler}) thread = pubsub.run_in_thread(sleep_time=0.01)
Redis的一个常见用例是,应用程序须要可以响应存储在特定键或键中的值可能发生的更改。因为有了键盘空间通知和发布/订阅,能够对Redis数据中的变化作出响应。通知很容易使用,而事件处理器可能在地理位置上分布。
最大的缺点是,Pub/Sub的实现要求发布者和订阅方始终处于启动状态。用户在中止或链接丢失时丢失数据。