關於 Redis的訂閱發布

來源:互聯網
上載者:User

關於 Redis的訂閱發布

文章目錄

  1. 1. 為什麼做訂閱分布?
  2. 2. Redis中的訂閱發布
  3. 3. Redis生產者消費者
  4. 4. Redis中訂閱發布
  5. 5. Java Jedis踩過的坑
為什麼做訂閱分布?

隨著業務複雜, 業務的項目依賴關係增強, 使用訊息佇列協助系統降低耦合度.

  • 訂閱分布本身也是一種生產者消費者模式, 訂閱者是消費者, 發行者是生產者.
  • 訂閱發布模式, 發行者發布訊息後, 只要有訂閱者, 則多個訂閱者會收到同樣的訊息
  • 生產者消費者模式, 生產者往隊列裡放入訊息, 由多個消費者對一條訊息進行搶佔.

  • 訂閱分布模式可以將一些不著急完成的工作放到其他進程或者線程中進行離線處理.

 

Redis中的訂閱發布

Redis中的訂閱發布模式, 當沒有訂閱者時, 訊息會被直接丟棄(Redis不會持久化儲存訊息)

Redis生產者消費者

生產者使用Redis中的list資料結構進行實現, 將待處理的訊息塞入到訊息佇列中.

1234567891011 class Producer(object): def __init__(self, host="localhost", port=6379):self._conn = redis.StrictRedis(host=host, port=port)self.key = "test_key"self.value = "test_value_{id}" def produce(self):for id in xrange(5):msg = self.value.format(id=id)self._conn.lpush(self.key, msg)

消費者使用redis中brpop進行實現, brpop會從list頭部訊息, 並能夠設定逾時等待時間.

12345678910111213141516171819202122232425 class Consumer(object): def __init__(self, host="localhost", port=6379):self._conn = redis.StrictRedis(host=host, port=port)self.key = "test_key" def consume(self, timeout=0):# timeout=0 表示會無線阻塞, 直到獲得訊息while True:msg = self._conn.brpop(self.key, timeout=timeout)process(msg)  def process(msg):print msg if __name__ == '__main__':consumer = Consumer()consumer.consume()# 輸出結果('test_key', 'test_value_1')('test_key', 'test_value_2')('test_key', 'test_value_3')('test_key', 'test_value_4')('test_key', 'test_value_5')
Redis中訂閱發布

在Redis Pubsub中, 一個頻道(channel)相當於一個訊息佇列

1234567891011 class Publisher(object): def __init__(self, host, port):self._conn = redis.StrictRedis(host=host, port=port)self.channel = "test_channel"self.value = "test_value_{id}" def pub(self):for id in xrange(5):msg = self.value.format(id=id)self._conn.publish(self.channel, msg)

其中get_message使用了select IO多工來檢查socket串連是否是否可讀.

1234567891011121314151617181920212223 class Subscriber(object): def __init__(self, host="localhost", port=6379):self._conn = redis.StrictRedis(host=host, port=port)self._pubsub = self._conn.pubsub() # 產生pubsub對象self.channel = "test_channel"self._pubsub.subscribe(self.channel) def sub(self):while True:msg = self._pubsub.get_message()if msg and isinstance(msg.get("data"), basestring):process(msg.get("data")) def close(self):self._pubsub.close() # 輸出結果test_value_1test_value_2test_value_3test_value_4test_value_5
Java Jedis踩過的坑

在Jedis中訂閱者處理是採用同步的方式, 看源碼中PubSub模組的process函數

do-while迴圈中, 會等到當前訊息處理完畢才能夠處理下一條訊息, 這樣會導致當入隊列訊息量過大的時候, redis連結被強制關閉.

解決方案: 將整個處理函數改為非同步方式.

下面關於Redis��文章您也可能喜歡,不妨參考下:

Ubuntu 14.04下Redis安裝及簡單測試

Redis主從複製基本配置

Redis叢集明細文檔

Ubuntu 12.10下安裝Redis(圖文詳解)+ Jedis串連Redis

Redis系列-安裝部署維護篇

CentOS 6.3安裝Redis

Redis安裝部署學習筆記

Redis設定檔redis.conf 詳解

Redis 的詳細介紹:請點這裡
Redis 的:請點這裡

本文永久更新連結地址:

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.