Redis 五種數據類型的簡單介紹和使用

1.Redis 特性

  1. 速度快

    正常情況下,Redis 讀寫性能可以達到 10 萬/秒 ;Redis 所有數據是存放在內存中的、Redis 是用 C 語言實現的、Redis 使用了單線程架構。

  2. 基於鍵值對的數據結構

    Redis 的全稱是 REmote Dictionary Server,主要提供了 5 種數據結構:字符串(String)哈希(Hash)列表(List)集合(Set)有序集合(ZSet)

    在字符串的基礎上演變出了位圖(Bitmaps)HyperLogLog兩種數據機構,在 Redis3.2 版本中加入有關GEO(地理信息定位)的功能。

  3. 豐富的功能

    • 提供了鍵過期功能,可以用來實現緩存
    • 提供了發佈訂閱功能,可以用來實現消息系統
    • 支持Lua腳本功能,可以利用Lua創造出新的Redis命令
    • 提供了簡單的事務功能,能在一定程度上保證事務特性
    • 提供了(Pipeline)功能,這樣客戶點能將一批命令一次性傳到 Redis ,減少了網絡的開銷
  4. 簡單穩定

  5. 客戶端語言多

  6. 持久化

    將數據放在內存中是不安全的,一旦發生斷電或者機器故障,重要的數據可能就會丟失,因此,Redis 提供了兩種持久化方式:RDBAOF,即可以用兩種策略將內存的數據保存到硬盤中。

  7. 主從複製

    Redis 提供了複製功能,實現了多個相同數據的 Redis 副本。

  8. 高可用和分佈式

    Redis 從2.8版本正式提供了高可用實現 Redis Sentinel,它能夠保證 Redis 節點的故障發現和故障自動轉移。Redis 從3.0版本正式提供了分佈式實現 Redis Cluster,它是 Redis 真正的分佈式實現,提供了高可用、讀寫和容量的擴展性。

2.Redis API的理解與使用

1.全局命令

  • 查看所有鍵

    keys * 會將所有的鍵輸出

  • 鍵總數

    dbsize 返回當前數據庫中鍵的總數。 dbsize 命令在計算鍵總數時不會遍歷所有鍵,而是直接獲取Redis 內置的鍵總數變量,所以dbsize命令的時間複雜度是o(1)。而keys命令會遍歷所有鍵,所以它的時間複雜度是o(n),當Redis中保存了大量鍵時,線上環境禁止使用

  • 檢查鍵是否存在

    exists key 如果存在則返回1,不存在則返回0。

  • 刪除鍵

    del key [key ...] 返回結果爲成功刪除鍵的個數,假設刪除一個不存在的鍵,就會返回0

  • 鍵過期

    expire key seconds Redis 支持對鍵添加過期時間,當超過期時間後,會自動刪除鍵。

    ttl key 返回鍵的剩餘過期時間,有3中返回值

    • 大於等於0的整數:鍵剩餘的過期時間
    • -1:鍵沒設置過期時間
    • -2:鍵不存在
  • 鍵的數據結構類型

    type key 例如鍵是字符串類型,返回結果爲string,鍵是列表類型,返回結果爲list,如果鍵不存在,返回 none

2.數據結構和內部編碼

type 命令實際返回的是當前鍵的數據結構類型(5種數據類型),但這些只是Redis對外的數據結構。

實際上每種數據結構都有自己底層的內部編碼實現,而且是多種實現,這樣Redis會在合適的場景選擇合適的內部編碼

我們可以通過object encoding key查詢內部編碼。

Redis 這樣設計有2個好處:

  • 可以改進內部編碼,而對外的數據結構和命令沒有影響,這樣一旦開發出更優秀的內部編碼,無需改動外部數據結構和命令
  • 多種內部編碼實現可以不同場景下發揮各自的優勢,例如ziplist比較節省內存,但是在列表元素比較多的情況下,性能會有所下降,這時候Redis會根據配置選項將列表類型的內部實現轉換爲linkedlist

1.字符串

字符串類型是Redis最基礎的數據結構。字符串的值最大不能超過512MB

命令

  • 設置值

    set key value [ex seconds] [px milliseconds] [nx|xx]

    • ex seconds:爲鍵設置秒級過期時間
    • px milliseconds:爲鍵設置毫秒級過期時間
    • nx:鍵必須不存在,纔可以設置成功,用於添加
    • xx:與nx相反,鍵必須存在,纔可以設置成功,用於更新

    除了 set 選項,Redis 還提供了 setexsetnx 兩個命令,它們的作用和 ex 和 nx 選項是一樣的:

    • setex key seconds value
    • setnx key value
  • 獲取值

    get key 如果獲取的鍵不存在,則返回nil(空)

  • 批量設置值

    mset key value [key value ...]

  • 批量獲取值

    mget key [key ...] 如果有些鍵不存在,那麼它的值爲nil(空),結果是按照傳入鍵的順序返回

  • 計數

    incr key incr命令用於對值做自增的操作,返回結果分爲3種情況:

    • 值不是整數,返回錯誤
    • 值是整數,返回自增後的結果
    • 鍵不存在,按照值爲0自增,返回結果爲1

    除了incr命令,Redis提供了decr(自減)incrby(自增指定數字)decrby(自減指定數字)incrbyfloat(自增浮點數)

    • decr key
    • incrby key increment
    • decrby key decrement
    • incrbyfloat key increment
  • 追加值

    append key value append可以向字符串尾部追加值

  • 字符串長度

    strlen key eg:當前值爲redisworld,所以返回值爲10,當前值爲世界,返回值爲6(每個中文佔用3個字節)

  • 設置並返回原值

    getset key value getset和set一樣會設置值,但是不同的是,它同時會返回鍵原來的值

  • 設置指定位置的字符

    setrange key offset value

    • 下面操作將值由pest變爲了best

      127.0.0.1:6379> set redis pest
      OK
      127.0.0.1:6379> setrange redis 0 b
      (integer) 4
      127.0.0.1:6379> get redis
      "best"
      127.0.0.1:6379> setrange redis 2  a
      (integer) 4
      127.0.0.1:6379> get redis
      "beat"
      127.0.0.1:6379> setrange redis 6  c
      (integer) 7
      127.0.0.1:6379> get redis
      "beat\x00\x00c"
      127.0.0.1:6379> 
      
  • 獲取部分字符串

    getrange key start end

    start 和 end 分別是開始和結束的偏移量,偏移量從0開始計算

    127.0.0.1:6379> getrange redis 0 1
    "be"
    127.0.0.1:6379> getrange redis 9 10
    ""
    127.0.0.1:6379> getrange redis 4 10
    "\x00\x00c"
    127.0.0.1:6379> getrange redis 3 10
    "t\x00\x00c"
    127.0.0.1:6379> 
    
    命令 時間複雜度
    set key value o(1)
    get key o(1)
    del key [key …] o(k),k是鍵的個數
    mset key value [key value …] o(k),k是鍵的個數
    mget key [key …] o(k),k是鍵的個數
    incr key o(1)
    decr key o(1)
    incrby key increment o(1)
    decrby key increment o(1)
    incrbyfloat key increment o(1)
    append key value o(1)
    strlen key o(1)
    setrange key offset value o(1)
    getrange key start end o(n),n是字符串長度,由於獲取字符串非常快,所以如果字符串不是很長,可以視同爲o(1)

2.哈希

在 Redis 中,哈希類型是指鍵值本身又是一個鍵值對結構。

命令

  • 設置值

    hset key field value

    下面爲user:1 添加一對 field-value

    127.0.0.1:6379> hset user:1 name tom
    (integer) 1
    

    如果field已經存在,執行上述命令返回 0,但實際的值發生改變

    127.0.0.1:6379> hset user:1 name ddddd
    (integer) 0
    

    此外,Redis 提供了hsetnx 命令,它們的關係就像set和setnx命令一樣,只不過作用域由鍵變爲field

  • 獲取值

    hget key field

    下面的操作獲取user:1的name域(屬性)對應的值,如果鍵或field不存在,會返回nil

    127.0.0.1:6379> hget user:1  name
    "tom"
    127.0.0.1:6379> hget user:1  namea
    (nil)
    
  • 刪除field

    hdel key field [field ...]

    hedl 會刪除一個或多個field,返回結果爲成功刪除field的個數

  • 計算field個數

    hlen key

    例如:user:1 有3個field

    127.0.0.1:6379> hset user:1 name gy
    (integer) 1
    127.0.0.1:6379> hset user:1 age 26
    (integer) 1
    127.0.0.1:6379> hset user:1 city hz
    (integer) 1
    127.0.0.1:6379> hlen user1:1
    (integer) 0  #key不存在返回值
    127.0.0.1:6379> hlen user:1
    (integer) 3
    
  • 批量設置或獲取field-value

    hmset key field value [field value ...]

    hmget key field [field...]

    hmset和hmget分別是設置和獲取field-value,hmset需要的參數是key和多對field-value,hmget需要的參數是key和多個field。

    127.0.0.1:6379> HMSET user:1 name huang age 12 city xian
    OK
    127.0.0.1:6379> hmget user:1 name age citu city aa
    1) "huang"
    2) "12"
    3) (nil) #field不存在
    4) "xian"
    5) (nil) #field不存在
    
  • 判斷field是否存在

    hexists key field

    例如,user:1包含name域,所以返回結果爲1,不包含時返回0

    127.0.0.1:6379> HEXISTS user:1 name
    (integer) 1
    127.0.0.1:6379> HEXISTS user:1 name22
    (integer) 0
    127.0.0.1:6379> 
    
  • 獲取所有field

    hkeys key

    hkeys命令應該叫hfields更爲恰當,他返回指定哈希鍵所有的field,例如

    127.0.0.1:6379> hkeys user:1
    1) "name"
    2) "age"
    3) "city"
    127.0.0.1:6379> hkeys user:11  #鍵不存在
    (empty list or set)
    127.0.0.1:6379> 
    
    
  • 獲取所有value

    hvals key

    獲取 user:1全部value

    127.0.0.1:6379> hvals user:1
    1) "huang"
    2) "12"
    3) "xian"
    127.0.0.1:6379> hvals user:12
    (empty list or set)
    
  • 獲取所有的field-value

    hgetall key

    獲取user:1所有的field-value

    127.0.0.1:6379> hgetall uset:1 #key不存在的情況
    (empty list or set)
    127.0.0.1:6379> hgetall user:1
    1) "name"
    2) "huang"
    3) "age"
    4) "12"
    5) "city"
    6) "xian"
    127.0.0.1:6379> 
    
    

    在使用 hgetall時,如果哈希元素個數比較多,會存在阻塞 Redis 的可能。如果開發人員只需要獲取部分field,可以使用hmget,如果一定要獲取全部field-value,可以使用hscan命令,該命令會漸進式遍歷哈希類型

  • hincrby hincrbyfloat

    hincrby key field

    hincrbyfloat key field

    就像incrby、incrbyfloat命令一樣,但是它們的作用域是field

  • 計算value的字符串長度(需要Redis 3.2以上)

    hstrlen key field

    例如:hget user:1 name 的 value 是 tom,那麼hstrlen 的返回結果就是3

    命令 時間複雜度
    hset key field value o(1)
    hget key field o(1)
    hdel key field [field …] o(k),k是field個數
    hlen key o(1)
    hgetall key o(n),n是field總數
    hmget field [field …] o(k),k是field的個數
    hmset field value [field value] o(k),k是field的個數
    hexists key field o(1)
    hkeys key o(n),n是field總數
    hvals key o(n),n是field總數
    hsetnx key field value o(1)
    hincrby key field increment o(1)
    hincrbyfloat key field increment o(1)
    hstrlen key field o(1)

3.列表

列表(list)類型是用來存儲多個有序的字符串。列表的每個字符串稱爲元素(element),一個列表最多可以存儲2^32-1個元素。

在 Redis 中,可以對列表兩端插入(push)和彈出(pop),還可以獲取指定範圍的元素列表、獲取指定索引下標的元素等。

列表的四種操作類型

操作類型 操作
添加 rpush lpush linsert
查詢 lrange lindex llen
刪除 lpop rpop lrem ltrim
修改 lset
阻塞操作 bloop brpop
  • 添加操作

    • 從右邊插入元素

      rpush key value [value ...]

      下面代碼從右向左插入元素c、b、a:

      127.0.0.1:6379> rpush listkey c b a
      (integer) 3
      

      lrange 0 -1命令可以從左到右獲取列表所有元素

      127.0.0.1:6379> rpush listkey c b a 
      (integer) 3
      127.0.0.1:6379> lpush listkey e f g #左邊插入
      (integer) 6
      127.0.0.1:6379> lrange listkey 0 -1
      1) "g"
      2) "f"
      3) "e"
      4) "c"
      5) "b"
      6) "a"
      127.0.0.1:6379> rrange listkey 0 -1
      (error) ERR unknown command `rrange`, with args beginning with: `listkey`, `0`, `-1`, 
      
    • 從左邊插入元素

      lpush key value [value ...]

      使用方法和 rpush 相同,只不過從左側插入

    • 向某個元素前或者後插入元素

      linsert key before|after pivot value

      linsert 命令會從列表中找到等於 pivot(中樞) 的元素,在其前(before)或者後(after)插入一個 新的元素value。

      下面操作將會在列表的元素b前插入java,返回結果爲4,代表當前命令的長度

      127.0.0.1:6379> rpush mylist c b a
      (integer) 3
      127.0.0.1:6379> LRANGE mylist 0 -1
      1) "c"
      2) "b"
      3) "a"
      127.0.0.1:6379> linser mylist before b java
      (error) ERR unknown command `linser`, with args beginning with: `mylist`, `before`, `b`, `java`, 
      127.0.0.1:6379> linsert mylist before b java
      (integer) 4
      127.0.0.1:6379> LRANGE mylist 0 -1
      1) "c"
      2) "java"
      3) "b"
      4) "a"
      
  • 查找

    • 獲取指定範圍內的元素列表

      lrange key start end

      lrange 操作會獲取列表指定索引範圍所有的元素。索引下標有兩個特點:

      • 索引下標從左到右分別是0到N-1,但是從右到左分別是-1到-N

      • lrange中的 end 選項包含了自身,這個和很多編程語言不包含 end 不太相同,例如像獲取列表的第 2 到 第 4 個元素,可以執行如下操作:

        127.0.0.1:6379> lrange mylist 1 3
        1) "java"
        2) "b"
        3) "a"
        127.0.0.1:6379> 
        
        127.0.0.1:6379> lrange mylist 0 1
        1) "c"
        2) "java"
        127.0.0.1:6379> lrange mylist 0 7
        1) "c"
        2) "java"
        3) "b"
        4) "a"
        127.0.0.1:6379> lrange mylist -1 -3
        (empty list or set)
        127.0.0.1:6379> lrange mylist -4 -1
        1) "c"
        2) "java"
        3) "b"
        4) "a"
        127.0.0.1:6379> lrange mylist -5 -1
        1) "c"
        2) "java"
        3) "b"
        4) "a"
        
        
    • 獲取列表指定索引下標的元素

      lindex key index

      例如,當前列表最後一個元素爲a:

      127.0.0.1:6379> lindex mylist -1
      "a"
      127.0.0.1:6379> lindex mylist 0
      "c"
      127.0.0.1:6379> 
      
    • 獲取列表長度

      llen key

      例如,下面表示當前列表長度爲4

      127.0.0.1:6379> llen mylist
      (integer) 4
      127.0.0.1:6379> llen mylist2
      (integer) 0  #key值不存在返回的0
      127.0.0.1:6379> 
      
  • 刪除

    • 從列表左側彈出元素

      lpop key

      如下操作將列表最左側的元素c會被彈出(彈出後,元素被刪除),彈出後列表變爲 java、b、a:

      127.0.0.1:6379> lrange mylist 0 -1
      1) "c"
      2) "java"
      3) "b"
      4) "a"
      127.0.0.1:6379> lpop mylist
      "c"  #彈出的元素
      127.0.0.1:6379> lrange mylist 0 -1
      1) "java"
      2) "b"
      3) "a"
      
      
    • 從列表右側彈出

      rpop key

      它的使用方法和lpop是一樣的,只不過從列表右側彈出。

      127.0.0.1:6379> lrange mylist 0 -1
      1) "java"
      2) "b"
      3) "a"
      127.0.0.1:6379> RPOP mylist
      "a"
      
    • 刪除指定元素

      lrem key count value

      lrem 命令會從列表中找到等於value的元素進行刪除,根據count的不同分爲三種情況:

      • count>0,從左到右,刪除最多count個元素

      • count<0,從右到左,刪除最多count絕對值個元素

      • count=0,刪除所有

        例如,向列表從左向右插入5個a,下面操作將從列表左邊開始刪除4個爲a的元素

        127.0.0.1:6379> lpush mylist a a a a a java a 
        (integer) 7
        127.0.0.1:6379> lrange mylist 0 -1
        1) "a"
        2) "java"
        3) "a"
        4) "a"
        5) "a"
        6) "a"
        7) "a"
        127.0.0.1:6379> lrem list 4 a
        (integer) 0
        127.0.0.1:6379> lrem mylist 4 a
        (integer) 4
        127.0.0.1:6379> lrange mylist 0 -1
        1) "java"
        2) "a"
        3) "a"
        
    • 按照索引範圍修建列表

      ltrim key start end

      例如,下面操作會只保留列表mylist第2個到第4個元素

      127.0.0.1:6379> lpush mylist a a a a a java a 
      (integer) 7
      127.0.0.1:6379> lrange mylist 0 -1
      1) "a"
      2) "java"
      3) "a"
      4) "a"
      5) "a"
      6) "a"
      7) "a"
      127.0.0.1:6379> ltrim mylist 1 3
      OK
      127.0.0.1:6379> lrange mylist 0 -1
      1) "java"
      2) "a"
      3) "a"
      
  • 修改

    • 修改指定索引下標的元素

      lset key index newValue

      下面操作會將列表listkey中的第3個元素設置爲python:

      127.0.0.1:6379> lrange mylist 0 -1
      1) "java"
      2) "a"
      3) "a"
      127.0.0.1:6379> lset mylist 2 python
      OK
      127.0.0.1:6379> lrange mylist 0 -1
      1) "java"
      2) "a"
      3) "python"
      
  • 阻塞操作

    阻塞式彈出如下:

    blpop key [key ...](多個列表的鍵) timeout(阻塞時間>=0)

    brpop key [key ...] (多個列表的鍵)timeout(阻塞時間>=0)

    blpop和brpop 是 lpop 和 rpop 的阻塞版本

    • 列表爲空:如果timeout=3,那麼客服端要等到3秒後返回,如果timeout=0,那麼客戶端一直阻塞等待下去

      127.0.0.1:6379> brpop list:test 3
      (nil)
      (3.05s)
      127.0.0.1:6379> brpop list:test 0  #命令執行完成後去客戶端新增該鍵值對數據,客戶端立即返回
      1) "list:test"
      2) "ggggg"
      (34.77s)
      
      

      列表命令時間複雜度

      操作類型 命令 時間複雜度
      添加 rpush key value [value …] o(k),k是元素的個數
      lpush key value [value …] o(k),k是元素的個數
      linsert key before|after pivot value o(n),n是pivot距離列表頭或尾的距離
      查找 lrange key start end o(s+n),s是start偏移量,n是start到end的範圍
      lindex key index o(n),n是索引的偏移量
      llen key o(1)
      刪除 lpop key o(1)
      rpop key o(1)
      lrem count value o(n),n是列表的長度
      ltrim key start end o(n),n是要裁剪的元素總數
      修改 lset key index value o(n),n是索引的偏移量
      阻塞操作 blpop brpop o(1)

4.集合

集合(set)類型也是用來保存多個的字符串元素,但和列表類型不一樣的是,集合中不允許有重複元素,並且集合中的元素是無序的,不能通過索引下標獲取元素。一個集合最多可以存儲2^32-1個元素。

Redis除了支持集合內的增刪改查,同時還支持多個集合取交集、並集、差集。

命令

  • 集合內操作

    • 添加元素

      sadd key member [member ...] 返回結果爲添加成功的元素個數。

      127.0.0.1:6379> EXISTS myset
      (integer) 0
      127.0.0.1:6379> sadd myset a b c 
      (integer) 3
      127.0.0.1:6379> sadd myset a b
      (integer) 0
      
    • 刪除元素

      srem key member [member ...] 返回結果爲成功刪除元素的個數

      127.0.0.1:6379> srem myset a b c
      (integer) 3
      127.0.0.1:6379> srem myset hello
      (integer) 0
      
    • 計算元素個數

      scard key scard 的時間複查度爲O(1),它不會遍歷集合所有元素,而是直接使用 Redis 內部的變量

      127.0.0.1:6379> scard myset
      (integer) 1
      
    • 判斷元素是否在集合中

      sismember key element 如果給定元素element在集合內返回1,反之返回0

      127.0.0.1:6379> sismember myset a #不存在
      (integer) 0
      127.0.0.1:6379> sismember myset c
      (integer) 1
      127.0.0.1:6379> sismember myset1 c #不存在
      (integer) 0
      
    • 隨機從集合返回指定個數元素

      srandmember key [count] [count]是可選參數,如果不寫默認爲1

      127.0.0.1:6379> sadd myset a b c 
      (integer) 3
      127.0.0.1:6379> srandmember myset 2
      1) "c"
      2) "a"
      127.0.0.1:6379> srandmember myset 2
      1) "c"
      2) "b"
      127.0.0.1:6379> srandmember myset 2
      1) "a"
      2) "b"
      
    • 從集合隨機彈出元素

      spop key [count] spop操作可以從集合中隨機彈出一個元素

      srandmember 和 spop 都是隨機從集合中選出元素,兩者不同的是spop命令執行後,元素會從集合中刪除,而srandmember不會

    • 獲取所有元素

      smembers key

      127.0.0.1:6379> SMEMBERS myset
      1) "c"
      2) "b"
      

      smembers、lrange、hgetall都屬於比較重的命令,如果元素過多存在阻塞Redis的可能性,這時候可以使用sscan來完成。

  • 集合間操作

    • 求多個集合的交集

      sinter key [key ...]

      127.0.0.1:6379> sadd user:1:follow it music his sports
      (integer) 4
      127.0.0.1:6379> sadd user:2:follow it news ent sprots
      (integer) 4
      127.0.0.1:6379> sinter user:1:follow user:2:follow
      1) "it"
      
    • 求多個集合的並集

      sunion key [key ...]

      127.0.0.1:6379> SUNION user:1:follow user:2:follow
      1) "sports"
      2) "it"
      3) "his"
      4) "news"
      5) "ent"
      6) "music"
      7) "sprots"
      
    • 求多個集合的差集

      sdiff key [key ...]

      127.0.0.1:6379> sdiff user:1:follow user:2:follow
      1) "music"
      2) "his"
      3) "sports"
      
    • 將交集、並集、差集的結果保存

      sinterstore destination key [key ...]

      sunionstore destination key [key ...]

      sdiffstore destination key [key ...]

      127.0.0.1:6379> SINTERSTORE user:1_2:inter user:1:follow user:2:follow
      (integer) 1
      127.0.0.1:6379> type user:1_2:inter
      set
      127.0.0.1:6379> SMEMBERS user:1_2:inter
      1) "it"
      

    集合常用命令時間複雜度

    命令 時間複雜度
    sadd key member [member …] O(k),k是元素個數
    srem key member [member …] O(k),k是元素個數
    scard key O(1)
    sismember key member O(1)
    srandmember key [count] O(count)
    spop key O(1)
    smembers key O(n),n是元素總數
    sinter key [key …] || sinterstore O(m*k),k是多個集合中元素最少的個數,m是鍵個數
    sunion key [key …] || sunionstore O(k),k是多個集合元素個數和
    sdiff key [key …] || sdiffstore O(k),k是多個集合元素個數和

5.有序集合

它保留了集合不能有重複成員的特性,增加了有序集合的元素可以排序。但是它和列表使用索引下標作爲排序依據不同的是,它給每個元素設置一個分數(score)作爲培訓的依據。

列表、集合、有序集合三者的異同點

數據結構 是否允許重複元素 是否有序 有序實現方式 應用場景
列表 索引下標 時間軸、消息隊列等
集合 標籤、社交等
有序集合 分值(score) 排行榜系統、社交等

命令

  • 集合內

    • 添加成員

      zadd key score member [score member ...]

      127.0.0.1:6379> zadd user:ranking 251 tom
      (integer) 1
      127.0.0.1:6379> zadd user:ranking 251 tom
      (integer) 0 #返回結果代表成功添加成員的個數
      

      有關zadd命令有2點需要注意:

      Redis 3.2 爲 zadd 命令添加了nx、xx、ch、incr四個選項

      • nx:member必須不存在,纔可以設置成功,用於添加
      • xx:member必須存在,纔可以設置成功,用於更新
      • ch:返回此次操作後,有序集合元素和分數發生變化的個數
      • incr:對score做增加,相當於後面介紹的zincrby

      有序集合相比集合提供了排序字段,但是也產生了代價,zadd的時間複雜度爲O(log(n)),sadd的時間複雜度爲O(1)。

    • 計算成員個數

      zcard key

    • 計算某個成員的分數

      zscore key member

      127.0.0.1:6379> ZSCORE user:ranking tom
      "252"
      127.0.0.1:6379> ZSCORE user:ranking tomss
      (nil)  #如果成員不存在返回nil
      
    • 計算成員的排名

      zrank key member 分數低到高返回排名(排序從0開始計算)

      zrevrank key member 分數從高到低返回排名(排序從0開始計算)

    • 刪除成員

      zrem key member [member...]

      127.0.0.1:6379> zrem user:ranking mike
      (integer) 1 #返回結果爲成功刪除的個數
      
    • 增加成員的分數

      zincrby key increment member

      127.0.0.1:6379> zscore user:ranking tom
      "252"  #當前數據庫中的分數
      127.0.0.1:6379> zincrby user:ranking 8 tom
      "260" #增加8分後返回的結果
      
    • 返回指定排名範圍的成員

      zrange key start end [withscores]

      zrevrange key start end [withscores]

      有序集合是按照分值排名的,zrange是從低到高返回,zrevrange反之。

      如果加上 withscores選項,同時會返回成員的分數:

      127.0.0.1:6379> ZRANGE  user:ranking 0 2   #返回排名最低的3個成員
      1) "kris"
      2) "frank"
      3) "tim"
      127.0.0.1:6379> ZRANGE  user:ranking 0 2 withscores
      1) "kris"
      2) "1"
      3) "frank"
      4) "200"
      5) "tim"
      6) "220"
      127.0.0.1:6379> ZREVRANGE  user:ranking 0 2 withscores
      1) "tom"
      2) "260"
      3) "tom3"
      4) "252"
      5) "martin"
      6) "250"
      
    • 返回指定分數範圍的成員

      zrangebyscore key min max [withscores] [limit offset count]

      zrevrangebyscore key max min [withscores] [limit offset count]

      zrangebyscore 按照分數從低到高返回,zrevrangebyscore反之。

      withscores 會同時返回每個成員的分數

      limit offset count 選項可以限制輸出的起始位置和個數

      min和max 支持開區間(小括號)和閉區間(中括號),-inf 和 +inf 分別代表無限小和無限大

      127.0.0.1:6379> ZRANGEBYSCORE user:ranking 200 +inf withscores
       1) "frank"
       2) "200"
       3) "tim"
       4) "220"
       5) "martin"
       6) "250"
       7) "tom3"
       8) "252"
       9) "tom"
      10) "260"
      127.0.0.1:6379> ZRANGEBYSCORE user:ranking 200 +inf withscores limit 2 4
      1) "martin"
      2) "250"
      3) "tom3"
      4) "252"
      5) "tom"
      6) "260"
      
    • 返回指定分數範圍成員個數

      zcount key min max

    • 刪除指定排名內的升序元素

      zremrangebyrank key start end

      127.0.0.1:6379> ZREMRANGEBYRANK user:ranking 0 2
      (integer) 3  #刪除前3個元素
      
    • 刪除指定分數範圍的成員

      zremrangebyscore key min max

      127.0.0.1:6379> ZREMRANGEBYSCORE user:ranking (250 +inf  #將250分以上的成員全部刪除,返回結果爲成功刪除的個數
      (integer) 2
      
  • 集合間的操作

    • 交集

      zinterstore destination numkeys key [key ...] [weights weight] [aggregate sum|min|max]

      • destination:交集計算結果保存到這個鍵
      • numkeys:需要做交集計算鍵的個數
      • key[key…]:需要做交集計算的鍵
      • weights weight:每個鍵的權重,在做交集計算時,每個鍵中的每個member會將自己分數乘以這個權重,每個鍵的權重默認是1。
      • aggregate sum|min|max:計算成員交集後,分值按照sum(和)、min(最小值)、max(最大值)做彙總,默認值是sum。

      下面將對user:ranking:1和user:ranking:2做交集,weights和aggregate使用了默認值,可以看到目標鍵user:ranking:1_inter_2對分值做了sum操作

      127.0.0.1:6379> zadd user:ranking:1 1 kris 91 mike 200 frank 220 tim 250 martin 251 tom
      (integer) 6
      127.0.0.1:6379> zadd user:ranking:2 8 james 77 mike 625 martin 888 tom
      (integer) 4
      127.0.0.1:6379> ZINTERSTORE user:ranking:1_inter_2 2 user:ranking:1 user:ranking:2 
      (integer) 3
      127.0.0.1:6379> zrange user:ranking:1_inter_2 0 -1 withscores
      1) "mike"
      2) "168"
      3) "martin"
      4) "875"
      5) "tom"
      6) "1139"
      

      如果想讓user:ranking:2的權重變爲0.5,並且聚合效果使用max,可以執行如下操作:

      127.0.0.1:6379> ZINTERSTORE user:ranking:1_inter_2 2 user:ranking:1 user:ranking:2 weights 1 0.5 aggregate max
      (integer) 3
      127.0.0.1:6379> zrange user:ranking:1_inter_2 0 -1 withscores
      1) "mike"
      2) "91"
      3) "martin"
      4) "312.5"
      5) "tom"
      6) "444"
      
    • 並集

      zunionstore destination numkeys key [key ...] [weights weight] [aggregate sum|min|max]

    有序集合命令的時間複雜度

    命令 時間複雜度
    zadd key score member [score member …] O(kxlog(n)),k是添加成員的個數,n是當前有序集合成員個數
    zcard key O(1)
    zscore key member O(1)
    zrank/zrevrank key member O(log(n)),n是當前有序集合成員個數
    zrem key member [member …] O(k*log(n)),k是刪除成員的個數,n是當前有序集合成員個數
    zincrby key increment member O(log(n)),n是當前有序集合成員個數
    zrange/zrevrange key start end [withscores] O(log(n)+k),k是要獲取的成員個數,n是當前有序集合成員個數
    zrangebyscore/zrevrangebyscore key min/max max/min [withscores] O(log(n)+k),k是要獲取的成員個數,n是當前有序集合成員個數
    zcount key min max O(log(n)),n是當前有序集合成員個數
    zremrangebyrank key start end O(log(n)+k),k是要刪除的成員個數,n是當前有序集合成員個數
    zremrangebyscore key min max O(log(n)+k),k是要刪除的成員個數,n是當前有序集合成員個數
    zinterstore destination numkeys key [key …] O(nxk)+O(mxlog(m)),n是成員數量最小的有序集合成員個數,k是有序集合的個數,m是結果集中成員個數
    zunionstore destination numkeys key [key …] O(n)+O(mxlog(m)),n是所有有序集合成員個數和,m是結果集中成員個數
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章