消息队列(2) -- Redis实现消息队列(多应用)

异步任务: 很多时候服务器做的事情不需要客户端等待,所以可以把这些任务异步去做,主要原理是处理通知消息,然后针对通知消息通常是采取的队列结构。

实现消费者和生产者的方式很多,可以使用Python的标准库Queue:

import random
import time
from Queue import Queue
from threading import Thread

queue = Queue(10)

class Producer(Thread):
    def run(self):
        while True:
            elem = random.randrange(9)
            queue.put(elem)
            print "厨师 {} 做了 {} 饭 --- 还剩 {} 饭没卖完".format(self.name, elem, queue.qsize())
            time.sleep(random.random())

class Consumer(Thread):
    def run(self):
        while True:
            elem = queue.get()
            print "吃货{} 吃了 {} 饭 --- 还有 {} 饭可以吃".format(self.name, elem, queue.qsize())
            time.sleep(random.random())

def main():
    for i in range(3):
        p = Producer()
        p.start()
    for i in range(2):
        c = Consumer()
        c.start()

if __name__ == '__main__':
    main()


Redis队列

redis有两种方式来实现消息队列:

  1. 生产者消费模式(不推荐使用):让一个或者多个客户端监听消息队列,一旦消息达到,消费者马上消费,谁先抢到就算谁的,如果消息队列里面没有消息,那么消费者就继续监听。
  2. 发布订阅模式:一个或者多个客户端订阅消息频道,只要发布者发布消息,所有的订阅者都会收到消息,订阅者之间是平等的。

发布订阅者模式:

使用redis的pubsub功能,订阅者订阅频道,发布者发布消息到频道,频道就是一个消息队列:

class publisher():
    def __init__(self, topic='', host='127.0.0.1', port=6379, db=0):
        self.srv = redis.StrictRedis(host=host, port=port, db=0, charset='utf-8', decode_responses=True)
        self.topic = topic # 这个topic就是发布的频道

    def publish(self, msg=''):
        self.srv.publish(self.topic, msg) # 往该频道里面发布消息

class subscriber():
    def __init__(self, topic, host='127.0.0.1', port=6379, db=0):
        self.srv = redis.StrictRedis(host=host, port=port, db=0, charset='utf-8', decode_responses=True)
        self.pubsub = self.srv.pubsub(ignore_subscribe_messages=True)
        self.pubsub.subscribe(topic)  # 订阅频道为topic

    def listen(self):
        for message in self.pubsub.listen():
            print(message)  # 这里可以获取频道里面的每一条信息
            yield message['data']

所以这里实例化publisher()传入topic其实是创建topic频道,调用它的.publish()方法可以往频道里面发布信息。
实例化subscriber()传入topic其实是订阅topic频道,调用它的.listen()方法可以获取频道里面发布的消息。

使用上面构造的Pubsub类

 def p():
     pub = publisher(topic='test')
     while 1:
         time.sleep(3)
         pub.publish(msg='Hello, Test')

pt = threading.Thread(target=p)
pt.setDaemon(True)
pt.start()

创建一个名为test的频道,每过三秒钟往频道发送一条信息

sub = subscriber(topic='test')
    listen = sub.listen()
    for msg in listen:
        print(msg)

订阅这个频道,并且打印出收到的消息

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章