消息隊列(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)

訂閱這個頻道,並且打印出收到的消息

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