事務中的 BLPOP
BLPOP可以用于流水線(pipeline,發送多個指令并且批量讀取回複),特别是當它是流水線裡的最後一個指令的時候,這種設定更加有意義。
在一個 [MULTI]/ [EXEC]塊裡面使用 [BLPOP]沒有很大意義,因為它要求整個伺服器被阻塞以保證塊執行時的原子性,這就阻止了其他用戶端執行一個 push 操作。 是以,事務裡的 [BLPOP]會在 list 為空的時候傳回一個 nil 值,這跟逾時(timeout)的時候發生的一樣。
如果你喜歡科幻小說,那麼想象一下時間是以無限的速度在 MULTI / EXEC 塊中流逝……
傳回值
多批量回複(multi-bulk-reply): 具體來說:
- 當沒有元素的時候會彈出一個 nil 的多批量值,并且 timeout 過期。
- 當有元素彈出時會傳回一個雙元素的多批量值,其中第一個元素是彈出元素的 key,第二個元素是 value。
例子
redis> DEL list1 list2
(integer) 0
redis> RPUSH list1 a b c
(integer) 3
redis> BLPOP list1 list2 0
1) "list1"
2) "a"
可靠的隊列
當 [BLPOP]傳回一個元素給用戶端的時候,它也從 list 中把該元素移除。這意味着該元素就隻存在于用戶端的上下文中:如果用戶端在處理這個傳回元素的過程崩潰了,那麼這個元素就永遠丢失了。
在一些我們希望是更可靠的消息傳遞系統中的應用上,這可能會導緻一些問題。在這種時候,請檢視 [BRPOPLPUSH]指令,這是 [BLPOP] 的一個變形,它會在把傳回元素傳給用戶端之前先把該元素加入到一個目标 list 中。
模式:事件提醒
用來阻塞 list 的操作有可能是不同的阻塞原語。 比如在某些應用裡,你也許會為了等待新元素進入 Redis Set 而阻塞隊列,直到有個新元素加入到 Set 中,這樣就可以在不輪詢的情況下獲得元素。 這就要求要有一個 SPOP 的阻塞版本,而這事實上并不可用。但是我們可以通過阻塞 list 操作輕易完成這個任務。
消費者會做的:
LOOP forever
WHILE SPOP(key) returns elements
... process elements ...
END
BRPOP helper_key
END
而在生産者這角度我們可以這樣簡單地使用:
MULTI
SADD key element
LPUSH helper_key x
EXEC
5 set結構
适用于無序的集合
點贊點踩,抽獎,已讀,共同好友
1. sadd key member [member …]
**時間複雜度:**O(N)
添加一個或多個指定的member元素到集合的 key中.指定的一個或者多個元素member 如果已經在集合key中存在則忽略.
如果集合key 不存在,則建立集合key,并添加member元素到集合key中.
##2. scard
**時間複雜度:**O(1)
傳回集合存儲的key的基數 (集合元素的數量)
如果key不存在,則傳回 0
##3. smembers key
傳回key集合所有的元素.
該指令的作用與使用一個參數的SINTER 指令作用相同.
4. sdiff key [key …]
傳回一個集合與給定集合的差集的元素
不存在的key認為是空集.
##5. sinner key [key …]
**時間複雜度:**O(N*M)
傳回指定所有的集合的成員的交集.
###傳回值
array-reply: 結果內建員的清單.
##6. sunion key [key …]
**時間複雜度:**O(N) where N is the total number of elements in all given sets.
傳回給定的多個集合的并集中的所有成員.
不存在的key可以認為是空的集合.
array-reply:并集的成員清單
##7. srandmember key [count]
**時間複雜度:**Without the count argument O(1), otherwise O(N) where N is the absolute value of the passed count
僅提供key參數,那麼随機傳回key集合中的一個元素.
Redis 2.6開始, 可以接受 count 參數,如果count是整數且小于元素的個數,傳回含有 count 個不同的元素的數組,如果count是個整數且大于集合中元素的個數時,僅傳回整個集合的所有元素,當count是負數,則會傳回一個包含count的絕對值的個數元素的數組,如果count的絕對值大于元素的個數,則傳回的結果集裡會出現一個元素出現多次的情況.
僅提供key參數時,該指令作用類似于SPOP指令, 不同的是SPOP指令會将被選擇的随機元素從集合中移除, 而SRANDMEMBER僅僅是傳回該随記元素,而不做任何操作.
bulk-string-reply: 不使用count 參數的情況下該指令傳回随機的元素,如果key不存在則傳回nil.
array-reply: 使用count參數,則傳回一個随機的元素數組,如果key不存在則傳回一個空的數組.
8. sismember key member
傳回成員 member 是否是存儲的集合 key的成員.
integer-reply,詳細說明
是則傳回1
不是或者key不存在,則傳回0
##9. srem key member [member …]
在key集合中移除指定的元素.
不是key集合中的元素則忽略
如果key集合不存在則被視為一個空的集合,該指令傳回0.
如果key的類型不是一個集合,則傳回錯誤.
integer-reply:從集合中移除元素的個數,不包括不存在的成員
##10. spop key [count]
時間複雜度:O(1)
從鍵的set值存儲中移除并傳回count個随機元素
sorted set
1. zadd key [NX|XX] [CH] [INCR] score member [score member …]
将所有指定成員添加到鍵為key有序集合(sorted set)裡
2. zcard key
傳回key的有序集元素個數
integer-reply: key存在的時候,傳回有序集的元素個數,否則傳回0
3. zscoer key member
傳回有序集key中,成員member的score值。
如果member元素不是有序集key的成員,或key不存在,傳回nil。
bulk-string-reply
: member成員的score值(double型浮點數),以字元串形式表示
4. zcount key min max
**時間複雜度:**O(log(N)) with N being the number of elements in the sorted set.
傳回有序集key中,score值在min和max之間(預設包括score值等于min或max)的成員。
integer-reply: 指定分數範圍的元素個數
5. zrank key member
**時間複雜度:**O(log(N))
傳回有序集key中成員member的排名。其中有序內建員按score值遞增(從小到大)順序排列。排名以0為底,也就是說,score值最小的成員排名為0。
使用ZREVRANK指令可以獲得成員按score值遞減(從大到小)排列的排名。
6. zincrby key increment member
**時間複雜度:**O(log(N)) where N is the number of elements in the sorted set.
為有序集key的成員member的score值加上增量increment。如果key中不存在member,就在key中添加一個member,score是increment(就好像它之前的score是0.0)。如果key不存在,就建立一個隻含有指定member成員的有序集合。
當key不是有序集類型時,傳回一個錯誤。
score值必須是字元串表示的整數值或雙精度浮點數,并且能接受double精度的浮點數。也有可能給一個負數來減少score的值。
[Bulk string reply](http://www.redis.cn/topics/protocol#Bulk string reply): member成員的新score值,以字元串形式表示
7. zrange key start stop [WITHSCORES]
8. ZREVRANGE
ZREVRANGE key start stop [WITHSCORES]
傳回sorted set key中,指定區間内的成員。其中成員的位置按score值遞減(從大到小)來排列。具有相同score值的成員按字典序的反序排列。 除了成員按score值遞減的次序排列這一點外,[ZREVRANGE]指令的其他方面和[ZRANGE]指令一樣。
例:
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZREVRANGE myzset 0 -1
1) "three"
2) "two"
3) "one"
redis> ZREVRANGE myzset 2 3
1) "one"
redis> ZREVRANGE myzset -2 -1
1) "two"
2) "one"
redis>
monitor
調試指令,傳回伺服器處理的每一個指令,能幫助了解在資料庫上發生了什麼操作,可通過redis-cli和telnet指令使用。
Stream
XADD
插入消息,保證有序,可以自動生成全局唯一ID
XREAD
讀取消息,可以按ID讀取資料
XREADGROUP
按消費組形式讀取消息
XPENDING和XACK
- XPENDING指令可以用來查詢每個消費組内所有消費者已讀取但尚未确認的消息
- XACK指令用于向消息隊列确認消息處理已完成
6 Redis 複制
PSYNC
2.8.0 起可用。
從主機啟動複制流。
PSYNC 指令由 Redis 從節點調用,用于從主副本啟動複制流。
wait
此指令阻塞目前用戶端,直到所有以前的寫指令都成功的傳輸和指定的slaves确認。如果逾時,指定以毫秒為機關,即使指定的slaves還沒有到達,指令任然傳回。
指令始終傳回之前寫指令發送的slaves的數量,無論是在指定slaves的情況還是達到逾時。
注意點:
當’WAIT’傳回時,所有之前的寫指令保證接收由WAIT傳回的slaves的數量。
如果指令呗當做事務的一部分發送,該指令不阻塞,而是隻盡快傳回先前寫指令的slaves的數量。
如果timeout是0那意味着永遠阻塞。
由于WAIT傳回的是在失敗和成功的情況下的slaves的數量。用戶端應該檢查傳回的slaves的數量是等于或更大的複制水準。
一緻性(Consistency and WAIT)
WAIT 不能保證Redis強一緻:盡管同步複制是複制狀态機的一個部分,但是還需要其他條件。不過,在sentinel和Redis群集故障轉移中,WAIT 能夠增強資料的安全性。
如果寫操作已經被傳送給一個或多個slave節點,當master發生故障我們極大機率(不保證100%)提升一個受到寫指令的slave節點為master:不管是Sentinel還是Redis Cluster 都會嘗試選slave節點中最優(日志最新)的節點,提升為master。
盡管是選擇最優節點,但是仍然會有丢失一個同步寫操作可能行。
實作細節
因為引入了部分同步,Redis slave節點在ping主節點時會攜帶已經處理的複制偏移量。 這被用在多個地方:
- 檢測逾時的slaves
- 斷開連接配接後的部分複制
- 實作WAIT
- 在WAIT實作的案例中,當用戶端執行完一個寫指令後,針對每一個複制用戶端,Redis會為其記錄寫指令産生的複制偏移量。當執行指令WAIT時,Redis會檢測 slaves節點是否已确認完成該操作或更新的操作。
integer-reply: 目前連接配接的寫操作會産生日志偏移,該指令會傳回已處理至該偏移量的slaves的個數。
> SET foo bar
OK
> WAIT 1 0
(integer) 1
> WAIT 2 1000
(integer) 1
在例子中,第一次調用WAIT并沒有使用逾時設定,并且設定寫指令傳輸到一個slave節點,傳回成功。第二次使用時,我們設定了逾時值并要求寫指令傳輸到兩個節點。 因為隻有一個slave節點有效,1秒後WAIT解除阻塞并傳回1–傳輸成功的slave節點數。