1. 程式人生 > >KV型內存數據庫Redis

KV型內存數據庫Redis

integer redis-cli messages 加法 相等 BE amp key-value 出現

Redis是開源的高性能內存Key-Value數據庫, 可以提供事務和持久化支持, 並提供了TTL(time to life)服務。

Redis采用單線程數據操作+非阻塞IO的模型,非阻塞IO提供了較高的IO性能,單線程操作保證了單條指令的原子性。

Redis使用簡單靈活性能優異,常被用作緩存,分布式鎖或者消息隊列。

非特殊說明, 本文以Redis 3.0為標準進行介紹。

  • Redis數據結構
    • string
      • SET
      • GET
      • MGET
      • MSET
      • MSETNX
      • TYPE
      • INCR,DECR
      • INCRBY,DECRBY
      • INCRBYFLOAT
    • key
      • DEL
      • KEYS
      • EXISTS
      • RENAME
      • RENAMENX
      • EXPIRE
      • EXPIREAT
      • TTL
      • PERSIST
    • list
      • LPUSH
      • RPUSH
      • LLEN
      • LRANGE
      • LINDEX
      • LINSERT
      • LREM
      • LTRIM
      • LSET
      • LPOP, RPOP
    • set
      • SADD
      • SSCARD
      • SMEMBERS
      • SISMEMBER
      • SREM
      • SINTER, SUNION, SDIFF
      • SINTERSTORE, SUNIONSTORE, SDIFFSTORE
      • SPOP
      • SRANDMEMBER
    • hash
      • HSET
      • HSETNX
      • HGET
      • HMSET
      • HMGET
      • HDEL
      • HLEN
      • HEXISTS
      • HKEYS
      • HVALS
      • HGETALL
      • HINCRBY, HINCRBYFLOAT
    • zset
      • ZADD
      • ZREM
      • ZCARD
      • ZCOUNT
      • ZRANGE, ZREVRANGE
      • ZRANGEBYSCORE, ZREVRANGEBYSCORE
      • ZRANK, ZREVRANK
      • ZINCRBY
  • Redis應用進階
    • 事務
    • pipeline
    • 發布訂閱
    • SCAN
    • HyperLogLog

Ubuntu系統可以用包管理器安裝Redis服務:

sudo apt-get install redis-server

並安裝客戶端:

sudo apt-get install redis-tools

進入Redis客戶端

redis-cli

登錄遠程Redis服務

redis-cli -h host -p port -a password

Redis數據結構

通常情況下,在Redis中若key或field不存在則會作為空集合處理(寫操作會將先初始化為空集合)不會拋出錯誤,若key指向了其它類型則會出現錯誤。

Redis中的線性集合(list和zset)的下標以0為底,且支持負數下標。即0指向第一個元素,1指向第二個元素,-1指向最後一個元素,-2指向倒數第二個元素。

線性集合通常用start和stop參數表示一個子序列,序列為閉區間即包含start和stop指向的元素(這點與很多編程語言不同)。

string

string是Redis中的基本類型。 除了增刪改查之外,Redis提供了STRLEN,APPEND等簡單字符串操作。

Redis沒有專用的整數類型,所以key內儲存的string可以被解釋為十進制64位有符號整數進行計算。

字符串也可以解釋為雙精度浮點數,在作為浮點數時計算結果時最大保留17位小數,自動去除小數部分尾隨的0,必要時還會將浮點數改為整數(比如3.0會被保存成3)。 浮點數可以使用像2.0e73e590e-2這樣的指數符號來表示。

string的算術操作可以讓我們方便的實現鎖和計數器等功能。

SET

SET key value [EX seconds] [PX milliseconds] [NX|XX]
SET one 1
SET one 1 XX
SET two 2 NX

將key指向字符串值value,若不存在key則新建鍵值對,若key存在默認情況下會覆蓋舊值,無視舊值的類型。

SET設置成功會返回OK, 失敗會返回nil。

SET key value NX只有在key不存在時才會設置,若key已存在則不進行任何操作。

SET key value XX只有key存在時才會設置, 若key不存在則不進行任何操作。

SET key value EX second: 設置鍵的過期時間為 second 秒。

SET key value PX millisecond: 設置鍵的過期時間為 millisecond 毫秒。

因為SET命令可以通過參數來實現SETNX、SETEX和PSETEX三個命令的效果,Redis官方稱可能在將來的版本中廢棄並最終移除SETNX、SETEX和PSETEX這三個命令。

GET

GET key
GET one

返回key所關聯的字符串值,若key不存在返回nil, 若key指向其它數據類型則會返回一個錯誤信息。

MGET

MGET key [key key ...]

返回所有(一個或多個)給定key的值。若其中有某個key不存在或指向其它類型,那麽這個key返回nil。

MSET

MSET key value [key value ...]
MSET one 1 two 2

同時設置一個或多個key-value對, 如果某個給定key已經存在,那麽MSET會用新值覆蓋原來的舊值。該命令不會返回錯誤信息,總是返回OK。

和其它指令一樣,該操作是原子性的。

MSETNX

MSETNX key value [key value ...]
MSET one 1 two 2

同時設置一個或多個key-value對, 如果某個給定key已經存在,那麽MSETNX不會設置任何一個key-value。

該操作是原子性的,要麽全部設置要麽全不被設置。

TYPE

TYPE key

返回key指向的類型:

  • none: key不存在
  • string: 字符串
  • list: 列表
  • set: 集合
  • zset: 有序集
  • hash: 哈希表

INCR,DECR

INCR key
DECR key

INCR命令將key中儲存的數字值增1, 若key不存在則先被初始化為0,然後再執行操作。 返回操作後key指向的值。

若值包含錯誤的類型,或字符串類型的值不能表示為數字,那麽返回一個錯誤。

類似地有DECR命令,用於將存儲的數字減1。

INCRBY,DECRBY

INCRBY key value
INCRBY count 2
DECRBY count 3

將key所儲存的值加上增量value, 返回操作後的值。value可以為0或負值。

若值包含錯誤的類型,或字符串類型的值不能表示為整數,那麽返回一個錯誤。

類似地有DECRBY用於將存儲的數字減去給定值。

INCRBYFLOAT

INCRBYFLOAT key value
INCRBYFLOAT one 1.23

將key所儲存的值加上浮點增量value, 返回操作後的值。value可以為0或負值。

若值包含錯誤的類型,或字符串類型的值不能表示為數字,那麽返回一個錯誤。

目前版本的Redis中沒有DECRBYFLOAT指令,可以使用加負數進行減運算。

key

本節介紹對key通用的操作。

DEL

DEL key [key ...]
DEL one two

刪除給定的一個或多個key, 不存在的key將會忽略返回被刪除的key的數量。

KEYS

KEYS pattern
KEYS *

查找所有符合給定模式pattern的key:

  • KEYS *: 匹配數據庫中所有key 。
  • KEYS h?llo: 匹配hello,hallo 和 hxllo 等。
  • KEYS h*llo: 匹配 hllo 和 heeeeello 等。
  • KEYS h[ae]llo: 匹配 hello 和 hallo,但不匹配 hillo 。

EXISTS

EXISTS key
EXISTS one

檢查給定key是否存在, 若存在返回 1,否則返回 0。

RENAME

RENAME key newkey
RENAME one ONE

將key改名為newkey, 當newkey已經存在時,RENAME命令將覆蓋舊值。成功時返回OK,失敗時返回一個錯誤。

當key和newkey相同,或者key不存在時,返回一個錯誤。

RENAMENX

RENAMENX key newkey
RENAMENX one ONE

當newkey不存在時, 將key改名為newkey。成功時返回1,若newkey已存在返回0。

EXPIRE

EXPIRE key seconds
EXPIRE one 1000

為給定key設置生存時間(TTL),當key過期時(生存時間為0),它會被自動刪除。

使用SET命令等覆蓋一個鍵值對將會移除TTL, 但是INCR,LPUSH, HSET等命令不會修改生存時間。

RENAME命令不會修改生存時間,若RENAME key key2命令使得key覆蓋了帶有TTL的key2, 那麽新的key2的生存時間設置和原來的key相同。

PEXPIRE命令和EXPIRE命令的作用類似,但是它以毫秒為單位設置key的生存時間。

EXPIREAT

EXPIREAT key timestamp

EXPIREAT的作用和EXPIRE類似,都用於為key設置生存時間。

不同在於EXPIREAT命令接受的時間參數是UNIX時間戳。

PEXPIREAT和EXPIREAT命令類似,但它的參數是以毫秒為單位的unix時間戳。

TTL

TTL key

以秒為單位,返回給定 key 的剩余生存時間,當key不存在時,返回-2, 當key存在但沒有設置剩余生存時間時,返回-1。

PTTL命令類似於TTL命令,但它以毫秒為單位返回key的剩余生存時間。

PERSIST

PERSIST key

移除給定key的生存時間設置,使其成為永久的key。

當生存時間移除成功時,返回1。如果key不存在或key沒有設置生存時間,返回0。

list

列表(list)是一個線性容器,可以根據下標訪問元素。

Redis中list的元素只能是字符串,不支持其它類型。

LPUSH

LPUSH key value1 value2 
LPUSH arr a b c

將一個或多個值value插入到列表key的頭部(左側),返回操作後列表的長度。

如果key不存在,將會創建一個空列表並執行LPUSH操作,當key存在但不是列表類型時,返回一個錯誤。

對空列表arr執行LPUSH arr a b c指令後,arr的內容為c b a。相當於原子性的執行了LPUSH arr a, LPUSH arr b, LPUSH arr c三條指令。

RPUSH

RPUSH key value1 value2
RPUSH arr a b c

將一個或多個值value插入到列表key的尾部(左側),返回操作後列表的長度。

如果key不存在,將會創建一個空列表並執行RPUSH操作,當key存在但不是列表類型時,返回一個錯誤。

對空列表arr執行RPUSH arr a b c指令後,arr的內容為a b c。相當於原子性的執行了RPUSH arr a, RPUSH arr b, RPUSH arr c三條指令。

LLEN

LLEN key

返回列表的長度,若key不存在返回0, 若key指向其它類型則返回一個錯誤。

LRANGE

LRANGE key start stop
LRANGE arr 0 -1

返回列表key中指定區間內的元素,區間以偏移量start和stop指定。

下標以0為底,即0表示列表中的第一個元素, 1表示第二個元素。也可以使用負數下標,-1表示最後一個元素, -2表示倒數第二個元素。

stop下標也在LRANGE命令的取值範圍之內(閉區間),LRANGE arr 0 2會返回下標為0,1,2的三個元素。

超出範圍的下標值不會引起錯誤,如果start比列表的最大下標還要大那麽返回一個空列表,如果stop下標比最大下標還要大,stop的值將被設為最大下標。

LINDEX

LINDEX key index

返回列表key中,下標為index的元素。若index超出範圍或者key指向空列表(key不存在)則會返回nil, 若key指向其它類型則返回錯誤。

下標以0為底,即0表示列表中的第一個元素, 1表示第二個元素。也可以使用負數下標,-1表示最後一個元素, -2表示倒數第二個元素。

LINSERT

LINSERT key BEFORE|AFTER pivot value
RPUSH arr "World"
LINSERT arr BEFORE "World" "HELLO"

將值value插入到列表key中,位於值pivot之前或之後。當pivot不存在於列表key時,不執行任何操作。當key不存在時,key被視為空列表,不執行任何操作。

如果命令執行成功,返回插入操作完成之後列表的長度。如果沒有找到pivot返回-1,如果key不存在或為空列表,返回0。

LREM

LREM key count value

根據參數count的值,移除列表中與參數value相等的元素,返回被移除元素的數量。

count的值可以是以下幾種:

  • count > 0: 從表頭開始向表尾搜索,移除與value相等的元素,數量為count。
  • count < 0: 從表尾開始向表頭搜索,移除與value相等的元素,數量為count的絕對值。
  • count = 0: 移除表中所有與value相等的值。

LTRIM

LTRIM key start stop

讓列表只保留指定區間內的元素,不在指定區間之內的元素都將被刪除, start和stop指定區間的規則與LRANGE相同。

若刪除成功或key不存在則返回OK,若key指向其它類型則返回錯誤。

LSET

LSET key index value

將列表key中下標為index的元素的值設置為value,下標以0為底,可以使用負數下標。

當index參數超出範圍,或對一個空列表(key不存在或指向其它類型)進行LSET時,返回一個錯誤。

LPOP, RPOP

LPOP key

移除並返回列表key的頭元素, key不存在時返回nil。key指向其它類型時返回錯誤。

類似地有RPOP命令,移除並返回列表key的尾元素。

set

集合(set)是一種無序容器,不存在重復元素,可以用於判斷元素是否存在或者進行交並差運算。

Redis中集合的元素類型只能是字符串,不支持其它類型。

SADD

SADD key member [member ...]

將一個或多個member元素加入到集合key當中,返回添加到集合中新元素的數量,已經存在於集合的元素將被忽略。

若key不存在先初始化一個空集合然後添加成員,若key指向了非集合類型則會產生錯誤。

SSCARD

SSCARD key

返回集合中元素的數量,key不存在時返回0,key指向其它類型時返回一個錯誤。

SMEMBERS

SMEMBERS key

返回key指向的集合中的所有成員,若key不存在返回空集,若key指向其它類型則返回一個錯誤。

SISMEMBER

SISMEMBER key member

判斷member元素是否集合key的成員, 若元素是集合的成員返回1,若元素不是集合的成員或者集合不存在則返回0。

若key指向其它類型則返回一個錯誤。

SREM

SREM key member [member ...]

移除集合中的一個或多個元素,不存在的元素會被忽略,返回被成功移除的元素的個數。

若key不存在則作為空集處理,返回0。若key指向其它類型則返回一個錯誤。

SINTER, SUNION, SDIFF

SINTER key [key ...]
SUNION key [key ...]
SDIFF key [key ...]

返回給定集合的交集(SINTER),並集(SUNION)和差集(SDIFF),若key不存在則作為空集處理,若key指向其它類型則返回一個錯誤。

SINTERSTORE, SUNIONSTORE, SDIFFSTORE

SINTER dest key [key ...]
SUNION dest key [key ...]
SDIFF dest key [key ...]

計算給定集合的交集(SINTERSTORE),並集(SUNIONSTORE)和差集(SDIFFSTORE),並將結果存入dest集合,若dest集合已存在則將其覆蓋。

若key不存在則作為空集處理,若key指向其它類型則返回一個錯誤。

dest可以是某個參與計算的key,dest可以指向其它類型,計算結束後dest中的值會被覆蓋。

SPOP

SPOP key

SPOP移除並返回集合中的一個隨機元素,當key不存在或key是空集時返回nil,若key指向其它類型則返回一個錯誤。

SRANDMEMBER

SRANDMEMBER key [count]

若只提供了key參數,那麽返回集合中的一個隨機元素。

當key不存在或key是空集時返回nil,若key指向其它類型則返回一個錯誤。

若提供了count參數:

  • 若count 為正數,且小於集合基數,那麽返回一個包含count個元素的數組,數組中的元素各不相同。
  • 若count 大於等於集合中元素數,那麽返回整個集合。
  • 若count為負數,那麽命令返回一個數組,數組中的元素可能會重復出現多次,而數組的長度為count的絕對值。

hash

哈希表(hash)是key-value結構, key和value的類型為字符串。

HSET

HSET key field value

將哈希表key中的域field的值設為value。

如果key不存在, 將創建一個新的哈希表並進行HSET操作。如果域field已經存在於哈希表中,舊值將被覆蓋。

HSET設置了一個新域則返回1,若覆蓋了一個已有的域則返回0。

HSETNX

HSETNX key field value

將哈希表key中的域field的值設為value。

如果key不存在, 將創建一個新的哈希表並進行HSET操作。如果域field已經存在於哈希表中,則不進行任何操作。

HSETNX設置了一個新域則返回1,若域已經存在則返回0。

HGET

HGET key field

返回哈希表key中指定域field的值,若哈希表key不存在或其域field不存在則返回nil。

HMSET

HMSET key field value [field value ...]

同時將多個field-value(域-值)對設置到哈希表key中。若field已存在則會被覆蓋。

若key不存在,則創建一個空哈希表並執行HMSET操作

HMGET

HMGET key field [field ...]

返回哈希表key中一個或多個給定域的值,若field不存在則返回nil。

若key不存在則作為空哈希表處理,每個field都會返回一個nil值。

HDEL

HDEL key field [field ...]

刪除哈希表key中一個或多個指定域,不存在的域將被忽略,返回實際被刪除域的數目。

HLEN

HLEN key

返回哈希表key中域的數量,若key不存在則返回0。

HEXISTS

HEXISTS key field 

判斷哈希表key中域field是否存在,若存在返回1。若哈希表key不存在或其中不存在域field則返回0。

HKEYS

HKEYS key

以列表的形式返回哈希表key中所有域的名稱。

HVALS

HVALS key

返回哈希表key中所有域的值。

HGETALL

HGETALL key

以列表的形式返回哈希表key中所有的鍵和值,前一個元素為鍵其後的元素為它的值。

> HMSET hash a 1 b 2
OK
> HGETALL hash
1) "a"
2) "1"
3) "b"
4) "2"

HINCRBY, HINCRBYFLOAT

HINCRBY key field increment

為哈希表key中的域field的值加上增量increment, 增量可以為負數進行減法操作。

若哈希表中不存在域field則現將該域初始化為0,然後進行加法操作。

若哈希表key不存在,則將創建一個空哈希表,然後按上一條規則執行。

若key指向其它類型或域的值不能解釋為整數則返回一個錯誤。

類似地,HINCRBYFLOAT可以進行浮點數運算。

zset

有序集合(SortedSet, zset)是一種特殊的集合類型,它不允許重復元素,可以根據每個元素的score進行排序。

ZADD

ZADD key [NX|XX] [FH] [INCR] score member [[score member] [score member] ...]

將一個或多個member元素及其score值加入到有序集key當中, 若元素已經在集合中則更新它的score,score值可以是整數值或浮點數。

返回新添加的元素的數量,不包括被更新的元素的數量。

當key存在但不是有序集類型時,返回一個錯誤。

ZADD命令支持一些選項:

  • NX: 不更新存在的成員,僅添加新成員

  • XX: 不添加新成員,僅更新存在的成員

  • CH: 修改返回值為發生變化的成員總數,原始是返回新添加成員的總數(CH=changed)

  • INCR: 對成員的值進行增加操作而不是設置操作,等同於ZINCRBY命令

ZREM

ZREM key member [member ...]

移除有序集 key 中的一個或多個成員,不存在的成員將被忽略, 返回實際被移除的元素數量。

當 key 存在但不是有序集類型時,返回一個錯誤。

ZCARD

ZCARD key

返回有序集key中元素的數目,若key不存在則返回0,若key指向其它類型則返回一個錯誤。

ZCOUNT

ZCOUNT key min max

返回有序集key中,score值在min和max之間(包括等於min或max)的元素數量。

ZRANGE, ZREVRANGE

ZRANGE key start stop [WITHSCORES]

返回有序集key中,指定區間內的成員。start和stop用於指定元素的排名,它們以0為底且支持負下標,指定的是閉區間。

即0代表集合中score最小的元素,-1代表最大的元素。

其中成員的位置按score值遞增(從小到大)來排序, 具有相同score值的成員按字典序來排列。

ZRANGE key 0 -1可以返回集合中所有元素遞增排列的序列。

若start的值大於集合中元素的個數 或者 start大於stop值 則返回一個空列表;若stop大於集合中元素的個數則當做該集合的最大下標處理。

默認情況下ZRANGE命令僅返回元素,若添加了WITHSCORES選項則會將score一並返回。返回列表中元素和score成對出現,前一個為元素後一個為score。

> zrange z 0 -1
1) "a"
2) "b"
3) "c"
> zrange z 0 -1 WITHSCORES
1) "a"
2) "1"
3) "b"
4) "2"
5) "c"
6) "5"

類似地,ZREVRANGE指令按照score遞減排序(從大到小)。

ZRANGEBYSCORE, ZREVRANGEBYSCORE

ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

返回有序集key中score在min和max(包括等於min和max)之間的的元素,按照score值遞增排列。

默認情況下ZRANGEBYSCORE命令僅返回元素,若添加了WITHSCORES選項則會將score一並返回。返回列表中元素和score成對出現,前一個為元素後一個為score。

可選的LIMIT參數指定返回結果的數量及區間,類似於SQL中的SELECT offset, count,offset為跳過元素的數量,count為返回元素的最大數量。

類似地,ZREVRANGEBYSCORE命令可以按照score值遞減排列。

ZRANK, ZREVRANK

ZRANK key member

返回有序集key中成員member的排名。其中有序集成員按score值遞增(從小到大)順序排列。

排名以0為底,score值最小的成員排名為0。

使用 ZREVRANK 命令可以獲得成員按 score 值遞減(從大到小)排列的排名。

ZINCRBY

ZINCRBY key increment member

為有序集key的成員member的score值加上增量increment,increment可以為負值,可以為整數或者浮點數。

當key不存在,或 member不是key的成員時,ZINCRBY會初始化空集合,或者將成員初始化為0。

當key指向其它類型時,則會返回一個錯誤。

Redis應用進階

事務

127.0.0.1:6379> RPUSH a 1 2 3
QUEUED
127.0.0.1:6379> LRANGE a 0 -1
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 3
2) 1) "1"
   2) "2"
   3) "3"

Redis提供了事務機制,支持原子性地執行多條指令。

MULTI命令進入事務模式,其後的命令進入隊列緩存,直到EXEC命令執行隊列中的命令,或者DISCARD命令放棄事務執行。

EXEC命令會以列表的形式返回事務中所有命令的返回值。

若事務的指令隊列中存在語法錯誤則整個事務都會放棄執行。若隊列中某條指令出現了運行時錯誤(如哈希指令操作了列表), Redis會繼續執行事務中的後續指令。

Redis保證在事務的原子性,事務執行期間不會有其它客戶端的指令插入。

Redis事務不支持回滾必須由使用者保證一致性。

因為Redis是單線程執行的,總是能保證事務的隔離性。Redis事務不提供額外的持久化機制,持久性由持久化配置決定。

WATCH命令應在事務開始前執行,用於監視某個鍵的值是否改變。 若在執行WATCHEXEC指令中間,任意一個被監視的鍵發生改變或被刪除那麽事務將中止執行,EXEC命令會返回nil。

127.0.0.1:6379> WATCH lock
OK
# 若此時其它客戶端修改了lock的值,那麽事務不會開始執行。
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET b 1
QUEUED
127.0.0.1:6379> GET b
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) "1"

WATCH的監視到EXEC開始執行事務為止,因此WATCH不會阻止在事務中修改被監視的鍵。

127.0.0.1:6379> WATCH lock
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET lock 1
QUEUED
127.0.0.1:6379> GET lock
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) "1"

WATCH命令主要用於保證事務開始執行時的狀態正確,典型的"秒殺"應用中,多個客戶端首先使用WATCH命令監視鎖,隨後執行購買事務。

WATCH命令和事務執行之間若有其它客戶端成功執行事務,使得鎖發生變化則當前客戶端無法執行事務,即搶購失敗。

示例(偽代碼):

> SET remains 100
> SET empty 0
> WATCH empty
# 此時可能已有其它客戶端搶先執行事務
> MULTI
> DECR remains
> if (remains == 0): SET empty 1 # 修改鎖,阻止其它客戶端搶購  
# 此處還應有寫購買記錄和修改余額等操作
> EXEC

UNWATCH命令用於取消WATCH命令對所有key的監視。

pipeline

Redis采用請求/響應式協議進行與服務端的交互,通常情況下一次請求只包含一條指令。

pipeline模式可以一次請求執行多條指令,減少IO的開銷。

這裏給出一個python客戶端使用pipeline的示例:

>>> connect = redis.Redis(host=‘127.0.0.1‘, port=6379)
>>> pipe = connect.pipeline(transaction=False)
>>> pipe.set("x", "1")
Pipeline<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>
>>> pipe.set("y", "2")
Pipeline<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>
>>> pipe.execute()
[True, True]

pipeline不是原子性的,執行過程中可能會有來自其他客戶端的指令執行。不要使用pipeline發送多條SET/GET指令代替MSET/MGET。

pipeline會占據整個連接,在完成前無法執行其它指令。客戶端應配置好連接池防止被pipeline阻塞。

發布訂閱

Redis的發布訂閱模式允許客戶端監聽某些頻道,發布者在該頻道上發布消息後,消息會被推送到訂閱了該頻道的客戶端。

發布訂閱模式允許服務端主動通知客戶端,無需客戶端輪詢狀態變化,因此Redis可以實現消息隊列的功能。

首先打開一個客戶端訂閱chat頻道:

SUBSCRIBE chat

打開另一個客戶端發布一條消息:

127.0.0.1:6379> PUBLISH chat "Hi there"
(integer) 1

PUBLISH命令的返回值是接收到該消息的訂閱者的數量。

訂閱了該頻道的客戶端會受到消息推送:

127.0.0.1:6379> SUBSCRIBE chat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "chat"
3) (integer) 1

1) "message"
2) "chat"
3) "Hi there"

UNSUBSCRIBE命令用於取消訂閱的頻道:

UNSUBSCRIBE [channel [channel ...]]

PSUBSCRIBE和PUNSUBSCRIBE可以使用模式匹配來訂閱和取消訂閱頻道。

PSUBSCRIBE pattern [pattern ...]
PUNSUBSCRIBE [pattern [pattern ...]]

SCAN

KEYS命令處理大數據庫或者SMEMBERS命令處理大集合時可能阻塞數據庫數秒之久,這在生產環境下是無法介紹的。

SCANSSCAN命令可用分頁叠代的方式遍歷大數據集,每次叠代僅返回少量數據不會阻塞服務器:

SCAN cursor [MATCH pattern] [COUNT count]
127.0.0.1:6379> SCAN 0
1) "20"
2)  1) "1125677473485562817"
    2) "5537448729649573447"
    3) "2854796168938416843"
    4) "7439346733403784473"
    5) "-6333572342266574627"
    6) "-9080851294203022766"
    7) "1125677473485562817"
    8) "820904952218043889"
    9) "1125677473485562827"
   10) "1125677473485562837"
127.0.0.1:6379> SCAN 20
1) "0"
2)  1) "1125677473485562817"
    2) "-1053519331922297522"
    3) "7439346733403784473"
    4) "-2594669955628668552"
    5) "-4053026386633294784"
    6) "7439346733403784473"
    7) "-1053519331922297522"
    8) "2649406091729268560"
    9) "7439346733403784473"
   10) "1053519331903186673"

SCAN命令的返回值包含兩部分,第一部分為下次叠代的遊標,第二部分為本次叠代取得的鍵。

SCAN cursor MATCH pattern可以像KEYS命令一樣使用通配符篩選需要叠代的鍵。SCAN cursor COUNT count可以設置每次叠代返回鍵的數量。

使用0作為遊標表示開始一次新的叠代,當SCAN命令返回的遊標為0時表示本次叠代已經結束。

SCAN命令保證在整個叠代期間一直存在於數據庫中的鍵一定會被返回。如果一個元素是在叠代過程中被添加到數據集的, 又或者是在叠代過程中從數據集中被刪除的, 那麽這個元素可能會被返回, 也可能不會, 這是未定義的。

SCAN命令可能會將一個鍵返回多次,由應用程序處理重復的元素。

Redis中提供了幾個類似的命令用於遍歷大集合:

  • SSCAN: 遍歷集合(set)
  • HSCAN: 遍歷哈希表(hash)
  • ZSCAN: 遍歷有序集合(zset), 包括元素成員和元素分值
127.0.0.1:6379> zadd z 1 a 2 b 3 c
(integer) 0
127.0.0.1:6379> zscan z 0
1) "0"
2) 1) "a"
   2) "1"
   3) "b"
   4) "2"
   5) "c"
   6) "3"

HyperLogLog

一個集合中不重復元素的個數稱為集合的基數,如集合{a, b, c}的基數為3。

HyperLogLog是一種估計大集合基數的算法,Redis封裝了該算法:

PFADD命令將元素添加到HyperLogLog中:

PFADD key element [element ...] 

PFCOUNT命令返回基數估計值,當給定了多個key時則返回它們基數之和(不是並集的基數):

PFCOUNT key [key ...]

PFMERGE命令將多個HyperLogLog合並,destKey的基數即為sourceKey並集的基數:

PFMERGE destkey sourcekey [sourcekey ...]

KV型內存數據庫Redis