一损肛、Redis的發(fā)布和訂閱
- Redis 發(fā)布訂閱(pub/sub)是一種消息通信模式:發(fā)送者(pub)發(fā)送消息嚷缭,訂閱者(sub)接收消息
- Redis 客戶端可以訂閱任意數(shù)量的頻道
- Redis的發(fā)布訂閱機(jī)制包括三個(gè)部分鲜棠,發(fā)布者猫态,訂閱者和Channel
發(fā)布者和訂閱者都是Redis客戶端望薄,Channel則為Redis服務(wù)器端槽驶,發(fā)布者將消息發(fā)送到某個(gè)的頻道握侧,訂閱了這個(gè)頻道的訂閱者就能接收到這條消息蚯瞧。Redis的這種發(fā)布訂閱機(jī)制與基于主題的發(fā)布訂閱類似,Channel相當(dāng)于主題品擎。
示例
以下實(shí)例演示了發(fā)布訂閱是如何工作的埋合。在我們實(shí)例中我們創(chuàng)建了訂閱頻道名為 redisChat:
127.0.0.1:6379> subscribe redisChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1
重新開(kāi)啟個(gè) redis 客戶端,然后在同一個(gè)頻道 redisChat 發(fā)布兩次消息
127.0.0.1:6379> publish redisChat "redis is a caching teching"
(integer) 1
127.0.0.1:6379> publish redisChat "hello"
(integer) 1
訂閱者就能接收到消息
127.0.0.1:6379> subscribe redisChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1
1) "message"
2) "redisChat"
3) "redis is a caching teching"
1) "message"
2) "redisChat"
3) "hello"
命令
下面列出了Redis 發(fā)布訂閱的常用命令:
序號(hào) | 命令 | 描述 |
---|---|---|
1 | PSUBSCRIBE pattern [pattern ...] | 訂閱一個(gè)或多個(gè)符合給定模式的頻道 |
2 | PUBSUB subcommand [argument [argument ...]] | 查看訂閱與發(fā)布系統(tǒng)狀態(tài) |
3 | PUBLISH channel message | 將信息發(fā)送到指定的頻道 |
4 | PUNSUBSCRIBE [pattern [pattern ...]] | 退訂所有給定模式的頻道 |
5 | SUBSCRIBE channel [channel ...] | 訂閱給定的一個(gè)或多個(gè)頻道的信息 |
6 | UNSUBSCRIBE [channel [channel ...]] | 指退訂給定的頻道 |
Redis發(fā)布訂閱與ActiveMQ的比較
- ActiveMQ支持多種消息協(xié)議萄传,包括AMQP甚颂,MQTT蜜猾,Stomp等,并且支持JMS規(guī)范振诬,但Redis沒(méi)有提供對(duì)這些協(xié)議的支持蹭睡;
- ActiveMQ提供持久化功能,但Redis無(wú)法對(duì)消息持久化存儲(chǔ)赶么,一旦消息被發(fā)送肩豁,如果沒(méi)有訂閱者接收,那么消息就會(huì)丟失辫呻;
- ActiveMQ提供了消息傳輸保障清钥,當(dāng)客戶端連接超時(shí)或事務(wù)回滾等情況發(fā)生時(shí),消息會(huì)被重新發(fā)送給客戶端放闺,Redis沒(méi)有提供消息傳輸保障祟昭。
總之,ActiveMQ所提供的功能遠(yuǎn)比Redis發(fā)布訂閱要復(fù)雜怖侦,畢竟Redis不是專門(mén)做發(fā)布訂閱的篡悟,但是如果系統(tǒng)中已經(jīng)有了Redis,并且需要基本的發(fā)布訂閱功能匾寝,就沒(méi)有必要再安裝ActiveMQ了恰力,因?yàn)榭赡蹵ctiveMQ提供的功能大部分都用不到,而Redis的發(fā)布訂閱機(jī)制就能滿足需求旗吁。
二踩萎、Redis 事務(wù)
Redis 通過(guò) MULTI 、 DISCARD 很钓、 EXEC 和 WATCH 四個(gè)命令來(lái)實(shí)現(xiàn)事務(wù)功能香府。事務(wù)提供了一種 將多個(gè)命令打包, 然后一次性码倦、按順序地執(zhí)行 的機(jī)制企孩, 并且事務(wù)在執(zhí)行的期間不會(huì)主動(dòng)中斷 —— 服務(wù)器在執(zhí)行完事務(wù)中的所有命令之后, 才會(huì)繼續(xù)處理其他客戶端的其他命令袁稽。
一個(gè)事務(wù)從開(kāi)始到執(zhí)行會(huì)經(jīng)歷以下三個(gè)階段:
- 開(kāi)始事務(wù)勿璃。
- 命令入隊(duì)。
- 執(zhí)行事務(wù)推汽。
示例
以下是一個(gè)事務(wù)的例子补疑, 它先以 MULTI 開(kāi)始一個(gè)事務(wù), 然后將多個(gè)命令入隊(duì)到事務(wù)中歹撒, 最后由 EXEC 命令觸發(fā)事務(wù)莲组, 一并執(zhí)行事務(wù)中的所有命令:
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set book "c++"
QUEUED
127.0.0.1:6379> get book
QUEUED
127.0.0.1:6379> exec
1) OK
2) "c++"
注意
- 單個(gè) Redis 命令的執(zhí)行是原子性的,但 Redis 沒(méi)有在事務(wù)上增加任何維持原子性的機(jī)制暖夭,所以 Redis 事務(wù)的執(zhí)行并不是原子性的
- 事務(wù)可以理解為一個(gè)打包的批量執(zhí)行腳本锹杈,但批量指令并非原子化的操作撵孤,中間某條指令的失敗不會(huì)導(dǎo)致前面已做指令的回滾,也不會(huì)造成后續(xù)的指令不做
命令
下表列出了 redis 事務(wù)的相關(guān)命令:
序號(hào) | 命令 | 描述 |
---|---|---|
1 | DISCARD | 取消事務(wù)竭望,放棄執(zhí)行事務(wù)塊內(nèi)的所有命令 |
2 | EXEC | 執(zhí)行所有事務(wù)塊內(nèi)的命令 |
3 | MULTI | 標(biāo)記一個(gè)事務(wù)塊的開(kāi)始 |
4 | UNWATCH | 取消 WATCH 命令對(duì)所有 key 的監(jiān)視 |
5 | WATCH key [key ...] | 監(jiān)視一個(gè)(或多個(gè)) key 邪码,如果在事務(wù)執(zhí)行之前這個(gè)(或這些) key 被其他命令所改動(dòng),那么事務(wù)將被打斷 |
為什么redis事務(wù)不支持回滾
以下是這種做法的優(yōu)點(diǎn):
- Redis 命令只會(huì)因?yàn)殄e(cuò)誤的語(yǔ)法而失斠濉(并且這些問(wèn)題不能在入隊(duì)時(shí)發(fā)現(xiàn))闭专,或是命令用在了錯(cuò)誤類型的鍵上面:這也就是說(shuō),從實(shí)用性的角度來(lái)說(shuō)枫振,失敗的命令是由編程錯(cuò)誤造成的喻圃,而這些錯(cuò)誤應(yīng)該在開(kāi)發(fā)的過(guò)程中被發(fā)現(xiàn)萤彩,而不應(yīng)該出現(xiàn)在生產(chǎn)環(huán)境中
- 因?yàn)椴恍枰獙?duì)回滾進(jìn)行支持粪滤,所以 Redis 的內(nèi)部可以保持簡(jiǎn)單且快速
有種觀點(diǎn)認(rèn)為 Redis 處理事務(wù)的做法會(huì)產(chǎn)生 bug , 然而需要注意的是雀扶, 在通常情況下杖小, 回滾并不能解決編程錯(cuò)誤帶來(lái)的問(wèn)題。 舉個(gè)例子愚墓, 如果你本來(lái)想通過(guò) INCR 命令將鍵的值加上 1 予权, 卻不小心加上了 2 , 又或者對(duì)錯(cuò)誤類型的鍵執(zhí)行了 INCR 浪册, 回滾是沒(méi)有辦法處理這些情況的扫腺。
鑒于沒(méi)有任何機(jī)制能避免程序員自己造成的錯(cuò)誤, 并且這類錯(cuò)誤通常不會(huì)在生產(chǎn)環(huán)境中出現(xiàn)村象, 所以 Redis 選擇了更簡(jiǎn)單笆环、更快速的無(wú)回滾方式來(lái)處理事務(wù)。