1. 什么是Redis
Redis是一個開源的內存數據庫,它以鍵值對的形式存儲數據。由於數據存儲在內存中,因此Redis的速度很快,但是每次重啟Redis服務時,其中的數據也會丟失,因此,Redis也提供了持久化存儲機制,將數據以某種形式保存在文件中,每次重啟時,可以自動從文件加載數據到內存當中。
Redis的架構包括兩個部分:Redis Client和Redis Server。Redis客戶端負責向服務器端發送請求並接受來自服務器端的響應。服務器端負責處理客戶端請求,例如,存儲數據,修改數據等。
Redis通常用作數據庫,緩存以及消息系統。
2. Redis發布訂閱
2.1 Redis發布訂閱架構
Redis提供了發布訂閱功能,可以用於消息的傳輸,Redis的發布訂閱機制包括三個部分,發布者,訂閱者和Channel。
發布者和訂閱者都是Redis客戶端,Channel則為Redis服務器端,發布者將消息發送到某個的頻道,訂閱了這個頻道的訂閱者就能接收到這條消息。Redis的這種發布訂閱機制與基於主題的發布訂閱類似,Channel相當於主題。
2.2 Redis發布訂閱功能
(1)發送消息
Redis采用PUBLISH命令發送消息,其返回值為接收到該消息的訂閱者的數量。
(2)訂閱某個頻道
Redis采用SUBSCRIBE命令訂閱某個頻道,其返回值包括客戶端訂閱的頻道,目前已訂閱的頻道數量,以及接收到的消息,其中subscribe表示已經成功訂閱了某個頻道。
(3)模式匹配
模式匹配功能允許客戶端訂閱符合某個模式的頻道,Redis采用PSUBSCRIBE訂閱符合某個模式所有頻道,用“”表示模式,“”可以被任意值代替。
假設客戶端同時訂閱了某種模式和符合該模式的某個頻道,那么發送給這個頻道的消息將被客戶端接收到兩次,只不過這兩條消息的類型不同,一個是message類型,一個是pmessage類型,但其內容相同。
(4)取消訂閱
Redis采用UNSUBSCRIBE和PUNSUBSCRIBE命令取消訂閱,其返回值與訂閱類似。
由 於Redis的訂閱操作是阻塞式的,因此一旦客戶端訂閱了某個頻道或模式,就將會一直處於訂閱狀態直到退出。在 SUBSCRIBE,PSUBSCRIBE,UNSUBSCRIBE和PUNSUBSCRIBE命令中,其返回值都包含了該客戶端當前訂閱的頻道和模式的 數量,當這個數量變為0時,該客戶端會自動退出訂閱狀態。
2.3 Redis發布訂閱實現
由於Redis是一個開源的系統,因此我們可以通過其源代碼查看內部的實現細節。
(1)SUBSCRIBE
當 客戶端訂閱某個頻道時,Redis需要將該頻道和該客戶端綁定。首先,在客戶端結構體client中,有一個屬性為pubsub_channels,該屬 性表明了該客戶端訂閱的所有頻道,它是一個字典類型,通過哈希表實現,其中的每個元素都包含了一個鍵值對以及指向下一個元素的指針,每次訂閱都要向其中插 入一個結點,鍵表示訂閱的頻道,值為空。然后,在表示服務器端的結構體redisServer中,也有一個屬性為pubsub_channels,但此處 它表示的是該服務器端中的所有頻道以及訂閱了這個頻道的客戶端,它也是一個字典類型,插入結點時,鍵表示頻道,值則是訂閱了這個頻道的所有客戶端組成的鏈 表。最后Redis通知客戶端其訂閱成功。
(2)PSUBSCRIBE
當 客戶端訂閱某個模式時,Redis同樣需要將該模式和該客戶端綁定。首先,在結構體client中,有一個屬性為pubsub_patterns,該屬性 表示該客戶端訂閱的所有模式,它是一個鏈表類型,每個結點包括了訂閱的模式和指向下一個結點的指針,每次訂閱某個模式時,都要向其中插入一個結點。然后, 在結構體redisServer中,有一個屬性也叫pubsub_patterns,它表示了該服務器端中的所有模式和訂閱了這些模式的客戶端,它也是一 個鏈表類型,插入結點時,每個結點都要包含訂閱的模式,以及訂閱這個模式的客戶端,和指向下一個結點的指針。
(3)PUBLISH
當 客戶端向某個頻道發送消息時,Redis首先在結構體redisServer中的pubsub_channels中找出鍵為該頻道的結點,遍歷該結點的 值,即遍歷訂閱了該頻道的所有客戶端,將消息發送給這些客戶端。然后,遍歷結構體redisServer中的pubsub_patterns,找出包含該 頻道的模式的結點,將消息發送給訂閱了該模式的客戶端。
2.4 Redis發布訂閱在Redis中的應用
Redis的發布訂閱功能與Redis中的數據存儲時無關的,它不會影響Redis的key space,即不會影響Redis中存儲的數據,但通過發布訂閱機制,Redis還提供了另一個功能,即Keyspace Notification,允許客戶端通過訂閱特定的頻道,從而得知是否有改變Redis中的數據的事件。例如,有一個客戶端刪除了Redis中鍵為 mykey的數據,該操作會觸發兩條消息,mykey del和del mykey,前者屬於頻道keysapce,表示keyspace發生的變化,后者屬於頻道keyevent,表示執行的操作。
2.5 Redis發布訂閱與ActiveMQ的比較
(1)ActiveMQ支持多種消息協議,包括AMQP,MQTT,Stomp等,並且支持JMS規范,但Redis沒有提供對這些協議的支持;
(2)ActiveMQ提供持久化功能,但Redis無法對消息持久化存儲,一旦消息被發送,如果沒有訂閱者接收,那么消息就會丟失;
(3)ActiveMQ提供了消息傳輸保障,當客戶端連接超時或事務回滾等情況發生時,消息會被重新發送給客戶端,Redis沒有提供消息傳輸保障。
總 之,ActiveMQ所提供的功能遠比Redis發布訂閱要復雜,畢竟Redis不是專門做發布訂閱的,但是如果系統中已經有了Redis,並且需要基本 的發布訂閱功能,就沒有必要再安裝ActiveMQ了,因為可能ActiveMQ提供的功能大部分都用不到,而Redis的發布訂閱機制就能滿足需求。