Redis 發佈訂閱(pub/sub)是一種消息通訊模式:發送者(pub)發送消息,訂閱者(sub)接收消息。redis
Redis 客戶端能夠訂閱任意數量的頻道。數組
下圖展現了頻道 channel1 , 以及訂閱這個頻道的三個客戶端 —— client2 、 client5 和 client1 之間的關係:緩存
當有新消息經過 PUBLISH 命令發送給頻道 channel1 時, 這個消息就會被髮送給訂閱它的三個客戶端:ide
實例函數
如下實例演示了發佈訂閱是如何工做的。在實例中建立了訂閱頻道名爲 redisChat:ui
redis 127.0.0.1:6379> SUBSCRIBE redisChat Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "redisChat" 3) (integer) 1
如今,從新開啓個 redis 客戶端,而後在同一個頻道 redisChat 發佈兩次消息,訂閱者就能接收到消息。spa
redis 127.0.0.1:6379> PUBLISH redisChat "Redis is a great caching technique" (integer) 1 redis 127.0.0.1:6379> PUBLISH redisChat "Learn redis by runoob.com" (integer) 1 # 訂閱者的客戶端會顯示以下消息 1) "message" 2) "redisChat" 3) "Redis is a great caching technique" 1) "message" 2) "redisChat" 3) "Learn redis by runoob.com"
# 1. 訂閱一個或多個符合給定模式的頻道。 PSUBSCRIBE pattern [pattern ...] ''' 返回值:接收到的信息。 redis 127.0.0.1:6379> PSUBSCRIBE mychannel Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "mychannel" 3) (integer) 1 ''' # 2.查看訂閱與發佈系統狀態。 PUBSUB subcommand [argument [argument ...]] ''' 返回值:由活躍頻道組成的列表。 redis 127.0.0.1:6379> PUBSUB CHANNELS (empty list or set) ''' # 3.將信息發送到指定的頻道。 PUBLISH channel message ''' 返回值:接收到信息的訂閱者數量。 redis 127.0.0.1:6379> PUBLISH mychannel "hello, i m here" (integer) 1 ''' # 4.退訂全部給定模式的頻道。 PUNSUBSCRIBE [pattern [pattern ...]] ''' 返回值:這個命令在不一樣的客戶端中有不一樣的表現。 redis 127.0.0.1:6379> PUNSUBSCRIBE mychannel 1) "punsubscribe" 2) "a" 3) (integer) 1 ''' # 5.訂閱給定的一個或多個頻道的信息。 SUBSCRIBE channel [channel ...] ''' 返回值:接收到的信息 redis 127.0.0.1:6379> SUBSCRIBE mychannel Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "mychannel" 3) (integer) 1 1) "message" 2) "mychannel" 3) "a" ''' # 6.指退訂給定的頻道。 UNSUBSCRIBE [channel [channel ...]] ''' 返回值:這個命令在不一樣的客戶端中有不一樣的表現。 redis 127.0.0.1:6379> UNSUBSCRIBE mychannel 1) "unsubscribe" 2) "a" 3) (integer) 0 '''
Redis 事務能夠一次執行多個命令, 而且帶有如下兩個重要的保證:3d
一個事務從開始到執行會經歷如下三個階段:code
實例blog
如下是一個事務的例子, 它先以 MULTI 開始一個事務, 而後將多個命令入隊到事務中, 最後由 EXEC 命令觸發事務, 一併執行事務中的全部命令:
redis 127.0.0.1:6379> MULTI OK redis 127.0.0.1:6379> SET book-name "Mastering C++ in 21 days" QUEUED redis 127.0.0.1:6379> GET book-name QUEUED redis 127.0.0.1:6379> SADD tag "C++" "Programming" "Mastering Series" QUEUED redis 127.0.0.1:6379> SMEMBERS tag QUEUED redis 127.0.0.1:6379> EXEC 1) OK 2) "Mastering C++ in 21 days" 3) (integer) 3 4) 1) "Mastering Series" 2) "C++" 3) "Programming"
單個 Redis 命令的執行是原子性的,但 Redis 沒有在事務上增長任何維持原子性的機制,因此 Redis 事務的執行並非原子性的。
事務能夠理解爲一個打包的批量執行腳本,但批量指令並不是原子化的操做,中間某條指令的失敗不會致使前面已作指令的回滾,也不會形成後續的指令不作。
這是官網上的說明 From redis docs on transactions:
It's important to note that even when a command fails, all the other commands in the queue are processed – Redis will not stop the processing of commands.
好比:
redis 127.0.0.1:7000> multi OK redis 127.0.0.1:7000> set a aaa QUEUED redis 127.0.0.1:7000> set b bbb QUEUED redis 127.0.0.1:7000> set c ccc QUEUED redis 127.0.0.1:7000> exec 1) OK 2) OK 3) OK
若是在 set b bbb 處失敗,set a 已成功不會回滾,set c 還會繼續執行。
# 1.取消事務,放棄執行事務塊內的全部命令。 DISCARD ''' 返回值 老是返回 OK 。 redis 127.0.0.1:6379> MULTI OK redis 127.0.0.1:6379> PING QUEUED redis 127.0.0.1:6379> SET greeting "hello" QUEUED redis 127.0.0.1:6379> DISCARD OK ''' # 2.執行全部事務塊內的命令。 EXEC ''' 返回值:事務塊內全部命令的返回值,按命令執行的前後順序排列。 當操做被打斷時,返回空值 nil 。 # 事務被成功執行 redis 127.0.0.1:6379> MULTI OK redis 127.0.0.1:6379> INCR user_id QUEUED redis 127.0.0.1:6379> INCR user_id QUEUED redis 127.0.0.1:6379> INCR user_id QUEUED redis 127.0.0.1:6379> PING QUEUED redis 127.0.0.1:6379> EXEC 1) (integer) 1 2) (integer) 2 3) (integer) 3 4) PONG # 監視 key ,且事務成功執行 redis 127.0.0.1:6379> WATCH lock lock_times OK redis 127.0.0.1:6379> MULTI OK redis 127.0.0.1:6379> SET lock "huangz" QUEUED redis 127.0.0.1:6379> INCR lock_times QUEUED redis 127.0.0.1:6379> EXEC 1) OK 2) (integer) 1 # 監視 key ,且事務被打斷 redis 127.0.0.1:6379> WATCH lock lock_times OK redis 127.0.0.1:6379> MULTI OK redis 127.0.0.1:6379> SET lock "joe" # 就在這時,另外一個客戶端修改了 lock_times 的值 QUEUED redis 127.0.0.1:6379> INCR lock_times QUEUED redis 127.0.0.1:6379> EXEC # 由於 lock_times 被修改, joe 的事務執行失敗 (nil) ''' # 3.標記一個事務塊的開始。 MULTI ''' 返回值:老是返回 OK 。 redis 127.0.0.1:6379> MULTI # 標記事務開始 OK redis 127.0.0.1:6379> INCR user_id # 多條命令按順序入隊 QUEUED redis 127.0.0.1:6379> INCR user_id QUEUED redis 127.0.0.1:6379> INCR user_id QUEUED redis 127.0.0.1:6379> PING QUEUED redis 127.0.0.1:6379> EXEC # 執行 1) (integer) 1 2) (integer) 2 3) (integer) 3 4) PONG ''' # 4.取消 WATCH 命令對全部 key 的監視。 UNWATCH ''' 返回值: 老是返回 OK 。 redis 127.0.0.1:6379> WATCH lock lock_times OK redis 127.0.0.1:6379> UNWATCH OK ''' # 5.監視一個(或多個) key ,若是在事務執行以前這個(或這些) key 被其餘命令所改動,那麼事務將被打斷。 WATCH key [key ...] ''' 返回值:老是返回 OK 。 redis> WATCH lock lock_times OK '''
Redis 腳本使用 Lua 解釋器來執行腳本。 Redis 2.6 版本經過內嵌支持 Lua 環境。執行腳本的經常使用命令爲 EVAL。
Eval 命令的基本語法以下:
redis 127.0.0.1:6379> EVAL script numkeys key [key ...] arg [arg ...]
實例
如下實例演示了 redis 腳本工做過程
redis 127.0.0.1:6379> EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second 1) "key1" 2) "key2" 3) "first" 4) "second"
# 1.執行 Lua 腳本。 EVAL script numkeys key [key ...] arg [arg ...] ''' 參數說明: script: 參數是一段 Lua 5.1 腳本程序。腳本沒必要(也不該該)定義爲一個 Lua 函數。 numkeys: 用於指定鍵名參數的個數。 key [key ...]: 從 EVAL 的第三個參數開始算起,表示在腳本中所用到的那些 Redis 鍵(key),這些鍵名參數能夠在 Lua 中經過全局變量 KEYS 數組,用 1 爲基址的形式訪問( KEYS[1] , KEYS[2] ,以此類推)。 arg [arg ...]: 附加參數,在 Lua 中經過全局變量 ARGV 數組訪問,訪問的形式和 KEYS 變量相似( ARGV[1] 、 ARGV[2] ,諸如此類)。 redis 127.0.0.1:6379> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second 1) "key1" 2) "key2" 3) "first" 4) "second" ''' # 2.執行 Lua 腳本。 EVALSHA sha1 numkeys key [key ...] arg [arg ...] ''' 參數說明: sha1 : 經過 SCRIPT LOAD 生成的 sha1 校驗碼。 numkeys: 用於指定鍵名參數的個數。 key [key ...]: 從 EVAL 的第三個參數開始算起,表示在腳本中所用到的那些 Redis 鍵(key),這些鍵名參數能夠在 Lua 中經過全局變量 KEYS 數組,用 1 爲基址的形式訪問( KEYS[1] , KEYS[2] ,以此類推)。 arg [arg ...]: 附加參數,在 Lua 中經過全局變量 ARGV 數組訪問,訪問的形式和 KEYS 變量相似( ARGV[1] 、 ARGV[2] ,諸如此類)。 redis 127.0.0.1:6379> SCRIPT LOAD "return 'hello moto'" "232fd51614574cf0867b83d384a5e898cfd24e5a" redis 127.0.0.1:6379> EVALSHA "232fd51614574cf0867b83d384a5e898cfd24e5a" 0 "hello moto" ''' # 3.查看指定的腳本是否已經被保存在緩存當中。 SCRIPT EXISTS script [script ...] ''' 返回值:一個列表,包含 0 和 1 ,前者表示腳本不存在於緩存,後者表示腳本已經在緩存裏面了。 列表中的元素和給定的 SHA1 校驗和保持對應關係,好比列表的第三個元素的值就表示第三個 SHA1 校驗和所指定的腳本在緩存中的狀態。 redis 127.0.0.1:6379> SCRIPT LOAD "return 'hello moto'" # 載入一個腳本 "232fd51614574cf0867b83d384a5e898cfd24e5a" redis 127.0.0.1:6379> SCRIPT EXISTS 232fd51614574cf0867b83d384a5e898cfd24e5a 1) (integer) 1 redis 127.0.0.1:6379> SCRIPT FLUSH # 清空緩存 OK redis 127.0.0.1:6379> SCRIPT EXISTS 232fd51614574cf0867b83d384a5e898cfd24e5a 1) (integer) 0 ''' # 4.從腳本緩存中移除全部腳本。 SCRIPT FLUSH ''' 返回值:OK redis 127.0.0.1:6379> SCRIPT FLUSH OK ''' # 5.殺死當前正在運行的 Lua 腳本。 SCRIPT KILL ''' 返回值:OK redis 127.0.0.1:6379> SCRIPT KILL OK ''' # 6.將腳本 script 添加到腳本緩存中,但並不當即執行這個腳本。 SCRIPT LOAD script ''' 返回值:給定腳本的 SHA1 校驗和 redis 127.0.0.1:6379> SCRIPT LOAD "return 1" "e0e1f9fabfc9d4800c877a703b823ac0578ff8db" '''