• Redis随记--pubsub学习


    PUBSUB学习

    基础知识

    在Redis中可以使用LIST来实现简单的消息队列功能,但基于LIST实现的消息队列无法实现"消息多播"的功能。

    Redis单独实现PubSub模块来实现"消息多播"功能,并支持模式订阅

    常用命令

    • PUBSUB:用于检查消息订阅的状态信息。
    • PUBLIST:将消息传递给特定的Channel。
    • SUBSCRIBE:订阅特定的Channel。
    • PSUBSCRIBE:基于模式订阅匹配该模式的所有Channel。
    • UNSUBSCRIBE:退订特定的Channel。
    • PUNSUBSCRIBE:特对特定模式的所有Channel。

    实例代码

    发布消息代码:

    import time
    import datetime
    import redis
    
    REDIS_HOST = "xxx.xxx.xxx.xxx"
    REDIS_PASSWORD = "xxxxxxxxxxxx"
    REDIS_PORT = 6379
    REDIS_CHARSET = "utf-8"
    PUB_SUB_CHANNEL = "demo_channel"
    
    
    def pub_demo():
        redis_client = redis.StrictRedis(
            host=REDIS_HOST,
            port=REDIS_PORT,
            password=REDIS_PASSWORD,
            charset=REDIS_CHARSET
        )
        for task_index in range(1, 1000):
            task_msg = "this is task {} at {}".format(
                task_index,
                datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            )
            redis_client.publish(PUB_SUB_CHANNEL, task_msg)
            print(task_msg)
            time.sleep(1)
    
    
    if __name__ == '__main__':
        pub_demo()
    

    使用监听方式订阅消息代码:

    import redis
    
    REDIS_HOST = "xxx.xxx.xxx.xxx"
    REDIS_PASSWORD = "xxxxxxxxxxxx"
    REDIS_PORT = 6379
    REDIS_CHARSET = "utf-8"
    PUB_SUB_CHANNEL = "demo_channel"
    
    
    def sub_demo():
        redis_client = redis.StrictRedis(
            host=REDIS_HOST,
            port=REDIS_PORT,
            password=REDIS_PASSWORD,
            charset=REDIS_CHARSET
        )
        sub_handler = redis_client.pubsub()
        sub_handler.subscribe(PUB_SUB_CHANNEL)
        for sub_msg in sub_handler.listen():
            if sub_msg["type"] == "subscribe":
                print("start to subscribe message")
            if sub_msg["type"] == "message":
                print("task message:{}".format(
                    str(sub_msg["data"], encoding="utf-8")
                ))
    
    
    if __name__ == '__main__':
        sub_demo()
    

    使用定期轮循方式订阅消息:

    import redis
    import time
    
    REDIS_HOST = "xxx.xxx.xxx.xxx"
    REDIS_PASSWORD = "xxxxxxxxxxxx"
    REDIS_PORT = 6379
    REDIS_CHARSET = "utf-8"
    PUB_SUB_CHANNEL = "demo_channel"
    
    
    def sub_demo():
        redis_client = redis.StrictRedis(
            host=REDIS_HOST,
            port=REDIS_PORT,
            password=REDIS_PASSWORD,
            charset=REDIS_CHARSET
        )
        sub_handler = redis_client.pubsub()
        sub_handler.subscribe(PUB_SUB_CHANNEL)
        while True:
            sub_msg = sub_handler.get_message()
            if sub_msg is None:
                time.sleep(1)
                continue
            if sub_msg["type"] == "subscribe":
                print("start to subscribe message")
            if sub_msg["type"] == "message":
                print("task message:{}".format(
                    str(sub_msg["data"], encoding="utf-8")
                ))
    
    
    if __name__ == '__main__':
        sub_demo()
    
    

    运行发布消息产生的结果:

    (venv) H:GGA_CODEpubsub_demo>python pub_demo.py
    this is task 1 at 2021-02-28 20:39:06
    this is task 2 at 2021-02-28 20:39:07
    this is task 3 at 2021-02-28 20:39:08
    this is task 4 at 2021-02-28 20:39:09
    this is task 5 at 2021-02-28 20:39:10
    this is task 6 at 2021-02-28 20:39:11
    this is task 7 at 2021-02-28 20:39:13
    this is task 8 at 2021-02-28 20:39:14
    this is task 9 at 2021-02-28 20:39:15
    

    运行订阅消息产生的结果(早于发布运行):

    (venv) H:GGA_CODEpubsub_demo>python sub_loop_demo.py
    start to subscribe message
    task message:this is task 1 at 2021-02-28 20:39:06
    task message:this is task 2 at 2021-02-28 20:39:07
    task message:this is task 3 at 2021-02-28 20:39:08
    task message:this is task 4 at 2021-02-28 20:39:09
    task message:this is task 5 at 2021-02-28 20:39:10
    task message:this is task 6 at 2021-02-28 20:39:11
    task message:this is task 7 at 2021-02-28 20:39:13
    task message:this is task 8 at 2021-02-28 20:39:14
    task message:this is task 9 at 2021-02-28 20:39:15
    

    运行订阅消息产生的结果(晚于发布运行):

    (venv) H:GGA_CODEpubsub_demo>python sub_listen_demo.py
    start to subscribe message
    task message:this is task 5 at 2021-02-28 20:39:10
    task message:this is task 6 at 2021-02-28 20:39:11
    task message:this is task 7 at 2021-02-28 20:39:13
    task message:this is task 8 at 2021-02-28 20:39:14
    task message:this is task 9 at 2021-02-28 20:39:15
    

    总结:

    • Python客户端支持lister和get_message两种方式订阅消息,区别在于是否阻塞方式调用parse_response方法。
    • Redis支持多用户订阅相同Channel,订阅的程序能收到从建立订阅连接开始的消息,建立连接前发布的消息会丢失。
    def listen(self):
    	"Listen for messages on channels this client has been subscribed to"
    	while self.subscribed:
    		response = self.handle_message(self.parse_response(block=True))
    		if response is not None:
    			yield response
    
    def get_message(self, ignore_subscribe_messages=False, timeout=0):
    	"""
    	Get the next message if one is available, otherwise None.
    
    	If timeout is specified, the system will wait for `timeout` seconds
    	before returning. Timeout should be specified as a floating point
    	number.
    	"""
    	response = self.parse_response(block=False, timeout=timeout)
    	if response:
    		return self.handle_message(response, ignore_subscribe_messages)
    	return None
    

    学习总结

    Redis的PubSub模块实现简单的发布订阅功能,支持消息多播,但PubSub模块不支持消息持久化,消费者断连期间的消息会丢失,同时PubSub也不支持消费组和消息确认等功能,导致在生产环境很难有场景可以使用PubSub模块。

  • 相关阅读:
    TWaver中文社区 » 关于
    RedMon Redirection Port Monitor
    dust good
    HiSpider(Hitask) is a fast and high performance spider with high speed
    42qu.com 找到给你答案的人
    yet another 牛人
    Simple Map Reduce at home
    China (googlegroups) [CPyUG:78205] 基于Python的MapReduce算法的快速构建框架
    retools 0.1 : Python Package Index
    Bloomfilter 的应用场景 黄刚的专栏 博客频道 CSDN.NET
  • 原文地址:https://www.cnblogs.com/gaogao67/p/14460537.html
Copyright © 2020-2023  润新知