PubSub & Stream
PubSub
簡單隊列
在Pub成功後進行Sub有時得不到消息,需要延遲以下
在沒有消息時Sub直接返回空而不會阻塞,也有阻塞的方法
要先啓動Sub,否則啓動前的Pub發的信息收不到,另外如果Sub掛了Redis是不會補推的
Redis重啓時所有消息都會丟失,畢竟這時Redis認爲所有Sub都沒了
模式訂閱
這個和RabbitMQ的TopicExchange類似,通過*來做匹配
Stream
Stream相對於PubSub的兩點,一個是重啓不會丟失數據,另外一個是有了Consumer Group(通過xgroup create顯式創建,創建時需指定從哪個消息開始消費)
消費者內部會有一個狀態變量pending_ids,它記錄了當前已經被客戶端讀取,但是還沒有ack的消息.如果客戶端沒有ack,這個變量裏面的消息ID就會越來越多,一旦某個消息被ack,它就開始減少.這個pending_ids變量在Redis官方被稱爲PEL,也就是Pending Entries List,這是一個核心的數據結構,它用來確保客戶端至少消費了消息一次,而不會在網絡傳輸的中途丟失了而沒被處理.
id
消息ID的形式是timestampInMillis-sequence
id也可以通過xadd手工指定,但是必須比前面的id大,否則報錯,這也意味着如果使用了手工,就不能再自動了.按照官方說明,這個一般用來一些小衆場景,例如要和DB的id保持一致
隊列指令
xadd
向Stream追加消息,語法如下,其中*表示id自動產生
XADD mystream * field1 value1 field2 value2 field3 value3
maxlen
可以通過這個參數控制消息隊列長度,示例如下
xadd codehole maxlen 3 * name xiaorui age 1
上面指令執行後,長度不會超過3
xdel
按照官網說法給消息設置標誌位,不影響消息總長度.真正的刪除發生在整個macro-node裏所有entry都被標記
官網給出的這一指令的用處:
This may be useful, for instance, in order to comply with certain privacy policies.
xrange
這裏使用的是closed interval,不會包括刪除消息(這不是顯然麼),使用下面語法返回所有
XRANGE somestream - +
另外如果參數有自動補全功能,官方說明如下
XRANGE will auto-complete the start interval with -0 and end interval with -18446744073709551615, in order to return all the entries that were generated between a given millisecond and the end of the other specified millisecond.
count
可以通過count來指定數量,官網例子如下:
XRANGE somestream 1526985054069-0 + COUNT 1
1) 1) 1526985054069-0
2) 1) "duration"
2) "72"
3) "event-id"
4) "9"
5) "user-id"
6) "839248"
xlen
這裏有一個坑,就是如果隊列不存在會返回0,所以還需要進一步使用type或者exists來明確是空隊列還是不存在,另外根據我的測試,當xdel後長度會減少
消費指令
無組
xread
這個命令把Stream當做一個list看待,從一個指定的地方向後讀取
完整語法如下
XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key …] id [id …]
count
指出需要消費多少消息
block
阻塞多少毫秒,0表示一直阻塞
xgroup
完整語法如下
XGROUP [CREATE key groupname id-or-] [DESTROY key groupname] [DELCONSUMER key groupname consumername]
create
一般用0-0表示從頭消費,而**$**表示結尾
xreadgroup
和xread類似,只是有了讀組內消息
xinfo
可以使用xinfo groups key來查看group消息,也可以通過xinfo consumers key consumer來讀取消費者信息,其中consumer來自於前一個指令
高可用
不過鑑於Redis的指令複製是異步的,在failover發生時,Redis可能會丟失極小部分數據,這一點Redis的的其他數據結構也是一樣的