Redis 實戰 —— 04. Redis 資料結構常用命令簡介

滿賦諸機發表於2021-01-23

字串 P39

Redis 的字串是一個有位元組組成的序列,可以儲存以下 3 種型別的值:位元組串(byte string)、整數、浮點數。

在需要的時候, Redis 會將整數轉換成浮點數。整數的取值範圍和系統的長整型(long)的相同,浮點數取值範圍和精度與 IEEE 754 標準下的雙精度浮點數(double)的相同。

Redis 中的自增命令和自減命令 P39
命令 格式 描述
INCR INCR key 將鍵儲存的數字值加上 1
DECR DECR key 將鍵儲存的數字值減去 1
INCRBY INCRBY key increment 將鍵儲存的數字值加上整數增量 increment
DECRBY DECRBY key decrement 將鍵儲存的數字值減去整數減量 decrement
INCRBYFLOAT INCRBYFLOAT key increment 將鍵儲存的數字值加上浮點數增量 increment

相關演示程式碼如下(mainhandleResult 定義見:01. Redis 資料結構簡介):

// 執行字串型別數字相關操作
func executeNumberOperation(conn redis.Conn) {
	// 刪除原有值
	handleResult(redis.Int(conn.Do("DEL", "number")))
	// 獲取值,輸出 -> ERROR:  redigo: nil returned
	handleResult(redis.Int(conn.Do("GET", "number")))
	// 自增 1,返回自增後的值 -> 1
	handleResult(redis.Int(conn.Do("INCR", "number")))
	// 自增 2,返回自增後的值 -> 3
	handleResult(redis.Int(conn.Do("INCRBY", "number", "2")))
	// 自減 1,返回自減後的值 -> 2
	handleResult(redis.Int(conn.Do("DECR", "number")))
	// 自減 2,返回自減後的值 -> 0
	handleResult(redis.Int(conn.Do("DECRBY", "number", "2")))
	// 自增 1.5,返回自增後的值 -> 1.5
	handleResult(redis.Float64(conn.Do("INCRBYFLOAT", "number", "1.5")))
	// 自增 -1.3,返回自增後的值 -> 0.2
	handleResult(redis.Float64(conn.Do("INCRBYFLOAT", "number", "-1.3")))
}
供 Redis 處理子串和二進位制位的命令 P40
命令 格式 描述
APPEND APPEND key value 將 value 追加到 key 當前值的末尾
GETRANGE GETRANGE key start end 返回 [start, end] 範圍內子串
SETRANGE SETRANGE key offset value 將子串 [offset, offset + len(value)) 設定為 value
GETBIT GETBIT key offset 將字串看作是二進位制位串,獲取 offset 上的位
SETBIT SETBIT key offset value 將字串看作是二進位制位串,設定 offset 上的位為 value
BITCOUNT BITCOUNT key [start end] 統計 [start, end] 範圍內子串在二進位制下有多少個 1
BITOP BITOP operation destkey key [key ...] operation 可選位運算 AND , OR , XOR , NOT ,將一個或多個二進位制位串執行的操作結果存到 destkey 中

相關演示程式碼如下:

// 執行字串型別字串相關操作
func executeStringOperation(conn redis.Conn) {
	// 刪除原有值
	handleResult(redis.Int(conn.Do("DEL", "string")))
	// 追加串,返回當前字串長度 -> 6,值變為 -> append
	handleResult(redis.Int(conn.Do("APPEND", "string", "append")))
	// 獲取子串,返回 -> en
	handleResult(redis.String(conn.Do("GETRANGE", "string", 3, 4)))
	// 設定子串,返回當前字串長度 -> 6,值變為 -> appled
	handleResult(redis.Int(conn.Do("SETRANGE", "string", 3, "le")))
	// 設定子串,返回當前字串長度 -> 11,值變為 -> application
	handleResult(redis.Int(conn.Do("SETRANGE", "string", 3, "lication")))
	// 獲取二進位制位,返回 -> 1
	// (獲取第 7/8 個字元 a 在二進位制下第 7%8 位上的二進位制位,即 0110 0001 的第 7 位 1)
	handleResult(redis.Int(conn.Do("GETBIT", "string", 7)))
	// 設定二進位制位,返回原來的二進位制位 -> 0,值變為 -> cpplication
	// (設定第 6/8 個字元 a 在二進位制下第 6%8 位上的二進位制位為1,即 0110 0001 變為 0110 0011)
	handleResult(redis.Int(conn.Do("SETBIT", "string", 6, 1)))
	// 統計二進位制位,返回 -> 7
	// (統計 [0, 1] 範圍內子串 cp 在二進位制下 0110 0011 0111 0000 二進位制位為 1 的數量)
	handleResult(redis.Int(conn.Do("BITCOUNT", "string", 0, 1)))

	handleResult(redis.String(conn.Do("SET", "aKey", "aa")))
	handleResult(redis.String(conn.Do("SET", "bKey", "b")))
	// 對 aa(0110 0001 0110 0001) 和 b(0110 0010 0000 0000) 進行 按位或,結果儲存到 cKey 中
	// 返回字串長度 -> 2,值為 ca(0110 0011 0110 0001),
	handleResult(redis.Int(conn.Do("BITOP", "OR", "cKey", "aKey", "bKey")))
}

Redis 可以通過使用子串操作和二進位制位操作,配合 WATCHMULTIEXEC 命令(後面會初步介紹,以後將深入講解),構建任何想要的資料結構。

列表 P42

一些常用的列表命令 P42
命令 格式 描述
RPUSH RPUSH key value [value ...] 依次將一個或多個 value 從列表右端插入
LPUSH LPUSH key value [value ...] 依次將一個或多個 value 從列表左端插入
RPOP RPOP key 移除並返回列表最右端的元素
LPOP LPOP key 移除並返回列表最左端的元素
LINDEX LINDEX key offset 返回列表左端開始偏移量為 offset 的元素
LRANGE LRANGE key start end 返回列表左端開始 [start, end] 範圍內的所有元素
LTRIM LTRIM key start end 移除列表左端開始 [start, end] 範圍外的所有元素

相關演示程式碼如下:

// 執行列表型別相關操作
func executeListOperation(conn redis.Conn) {
	// 刪除原有值
	handleResult(redis.Int(conn.Do("DEL", "list")))
	// 右端插入一次插入 a, b, c,返回當前列表長度 -> 3,列表變為 -> a b c
	handleResult(redis.Int(conn.Do("RPUSH", "list", "a", "b", "c")))
	// 左端插入一次插入 d, e, f,返回當前列表長度 -> 6,列表變為 -> f e d a b c
	handleResult(redis.Int(conn.Do("LPUSH", "list", "d", "e", "f")))
	// 彈出並返回列表最右端的值,返回 -> c,列表變為 -> f e d a b
	handleResult(redis.String(conn.Do("RPOP", "list")))
	// 彈出並返回列表最左端的值,返回 -> f,列表變為 -> e d a b
	handleResult(redis.String(conn.Do("LPOP", "list")))
	// 返回左端開始下標偏移量為 offset 的值,返回 -> d
	handleResult(redis.String(conn.Do("LINDEX", "list", 1)))
	// 移除列表左端開始 [1, 2] 範圍外的所有元素,列表變為 -> d a
	handleResult(redis.String(conn.Do("LTRIM", "list", 1, 2)))
}

利用 LTRIM 命令可以原子地彈出多個元素。 P43

阻塞式的列表彈出命令以及在列表之間移動元素的命令 P43
命令 格式 描述
BLPOP BLPOP key [key ...] timeout 從第一個非空列表中彈出最左端的元素,或者在 timeout 秒內阻塞並等待可彈出的元素出現,返回被彈出的列表名及元素, timeout 為 0 表示無限等待
BRPOP BRPOP key [key ...] timeout 從第一個非空列表中彈出最右端的元素,或者在 timeout 秒內阻塞並等待可彈出的元素出現,返回被彈出的列表名及元素, timeout 為 0 表示無限等待
RPOPLPUSH RPOPLPUSH source destination 從 source 列表中彈出最右端的元素,然後將這個元素退出 destination 列表的最左端,並返回這個元素
BRPOPLPUSH BRPOPLPUSH source destination timeout 從 source 列表中彈出最右端的元素,然後將這個元素退出 destination 列表的最左端,並返回這個元素;如果 source 列表為空,則在 timeout 秒內阻塞並等待可彈出元素出現

相關演示程式碼如下:

// 執行列表型別阻塞相關操作
func executeListBlockOperation(conn redis.Conn) {
	// 刪除原有值
	handleResult(redis.Int(conn.Do("DEL", "source", "destination")))
	// 從第一個非空列表中彈出並返回列表最左端的值,最多等待 1秒,輸出 -> ERROR:  redigo: nil returned
	handleResult(redis.Strings(conn.Do("BLPOP", "source", "destination", 1)))

	// 初始化
	handleResult(redis.Int(conn.Do("RPUSH", "source", "a", "b", "c")))
	handleResult(redis.Int(conn.Do("RPUSH", "destination", "d", "e", "f")))
	// 從第一個非空列表中彈出並返回列表最左端的值,無限等待,返回 -> a,source 變為 -> b c,destination 變為 -> d e f
	handleResult(redis.Strings(conn.Do("BLPOP", "source", "destination", 0)))
	// 從第一個非空列表中彈出並返回列表最右端的值,無限等待,返回 -> f,source 變為 -> b c,destination 變為 -> d e
	handleResult(redis.Strings(conn.Do("BRPOP", "destination", "source", 0)))

	// 從 source 彈出最右端元素,然後推入到 destination 最左端,並返回這個元素
	// 返回 -> c,source 變為 -> b,destination 變為 -> c d e
	handleResult(redis.String(conn.Do("RPOPLPUSH", "source", "destination")))
	// 從 source 彈出最右端元素,然後推入到 destination 最左端,並返回這個元素,無限等待
	// 返回 -> b,source 變為 -> <nil>,destination 變為 -> b c d e
	handleResult(redis.String(conn.Do("BRPOPLPUSH", "source", "destination", 0)))
	// 從 source 彈出最右端元素,然後推入到 destination 最左端,並返回這個元素,最多等待 1秒
	// 輸出 -> ERROR:  redigo: nil returned,source 變為 -> <nil>,destination 變為 -> b c d e
	handleResult(redis.String(conn.Do("BRPOPLPUSH", "source", "destination", 1)))
}

對於阻塞彈出命令和彈出並推入命令,最常見的用例就是訊息傳遞(messaging)和任務佇列(task queue),將在以後對這兩個主題進行介紹。 P44

練習題:通過列表來降低記憶體佔用 P44

上篇文章中,我們使用了有序集合來記錄使用者最近瀏覽過的商品,並把使用者瀏覽這些商品時的時間戳設定為分值,從而使得程式可以在清理舊會話的過程中或是在執行完購買操作後,進行相應的資料分析。但由於儲存時間戳需要佔用相應的空間,所以如果分析操作並不需要用到時間戳的話,那麼就沒有必要使用有序集合來儲存使用者最近瀏覽過的商品了。為此,請在保證語義不變的情況下,將 UpdateToken 函式裡面是用的有序集合替換成列表。

提示:如果在解答這個問題時遇上困難的話,可以到 6.1.1 節中找找靈感。

  • 由於列表是有序的,所有最新訪問的一定在列表的左端,所以每次操作時先刪除列表中這個訪問記錄,再推入列表左端,最後修剪列表為長度為 25 即可。由於每次需要遍歷整個列表,所以時間複雜度較高,但是列表長度總共只有 25 ,時間上相差不大,但是空間可以節省很多。

    // 更新最近商品訪問列表
    func UpdateLatestViewedItem(conn redis.Conn, itemId int) {
    	// 移除列表中所有值為 itemId 的元素
    	_ = conn.Send("LREM", "latestViewedItem", 0, itemId)
    	// 將最近訪問的商品推入列表最左端
    	_ = conn.Send("LPUSH", "latestViewedItem", itemId)
    	// 修剪列表,保留最近訪問的 25 個
    	_ = conn.Send("LTRIM", "latestViewedItem", 0, 24)
    	// 執行上述命令
    	_ = conn.Flush()
    }
    

集合 P44

一些常用的集合命令 P45
命令 格式 描述
SADD SADD key member [member ...] 將一個或多個元素新增到集合中,返回新增到集合中的新元素的數量(不包括已存在的元素)
SREM SREM keymember [member ...] 將一個或多個元素從集合中刪除,返回成功從集合中刪除的元素(不包括不存在的元素)
SISMEMBER SISMEMBER key member 判斷元素 member 是否在集合 key 中
SCARD SCARD key 返回結合中元素的數量
SMEMBERS SMEMBERS key 返回集合的所有元素
SRANDMEMBER SRANDMEMBER key [count] 隨機返回集合中一個或多個元素。count 為正數時,返回 count 個各不相同的元素(最多返回整個集合);count 為負數時,返回 |count| 個可能會重複的元素,無最長限制。
SPOP SPOP key 隨機移除並返回集合中的一個元素
SMOVE SMOVE source destination member 將元素 member 從集合 source 移動到集合 destination 中

相關演示程式碼如下:

// 執行集合型別相關操作
func executeSetOperation(conn redis.Conn) {
	// 刪除原有值
	handleResult(redis.Int(conn.Do("DEL", "source", "destination")))
	// 集合中新增三個元素,輸出 -> 6,source 變為 -> 1 2 3 4 5 6 7
	handleResult(redis.Int(conn.Do("SADD", "source", 1, 2, 3, 4, 5, 6, 7, 1)))
	// 從集合中刪除兩個元素: 1 2,輸出 -> 2,source 變為 -> 3 4 5 6 7
	handleResult(redis.Int(conn.Do("SREM", "source", 1, 2)))
	// 判斷集合是否含有元素 3,輸出 -> 1
	handleResult(redis.Int(conn.Do("SISMEMBER", "source", 3)))
	// 返回集合的元素個數,輸出 -> 5
	handleResult(redis.Int(conn.Do("SCARD", "source")))
	// 返回集合的所有元素,輸出 -> [3 4 5 6 7]
	handleResult(redis.Ints(conn.Do("SMEMBERS", "source")))
	// 隨機返回集合中不同的 3 個元素,輸出 -> [6 5 3] (隨機結果可能存在不同,以實際為準)
	handleResult(redis.Ints(conn.Do("SRANDMEMBER", "source", 3)))
	// 隨機返回集合中可重複的 6 個元素,輸出 -> [7 5 6 3 7 6] (隨機結果可能存在不同,以實際為準)
	handleResult(redis.Ints(conn.Do("SRANDMEMBER", "source", -6)))
	// 隨機刪除集合中的 1 個元素,輸出 -> 3 ,source 變為 -> 4 5 6 7(隨機結果可能存在不同,以實際為準)
	handleResult(redis.Int(conn.Do("SPOP", "source")))
	// 移動 source 集合中的元素 7 到 destination 集合中(由於前面存在隨機,結果可能存在不同,以實際為準)
	// 輸出 -> 1 ,source 變為 -> 4 5 6 ,destination 變為 -> 7
	handleResult(redis.Int(conn.Do("SMOVE", "source", "destination", 7)))
}
用於組合和處理多個集合的命令 P45
命令 格式 描述
SDIFF SDIFF key [key ...] 返回存在於第一個集合,而不存在於其他集合的元素(差集)
SDIFFSTORE SDIFFSTORE destination key [key ...] 將存在於第一個集合,而不存在於其他集合的元素(差集)儲存到 destination 中,返回差集大小
SINTER SINTER key [key ...] 返回同時存在於所有集合中的元素(交集)
SINTERSTORE SINTERSTORE destination key [key ...] 將同時存在於所有集合中的元素(交集)儲存到 destination 中,返回交集大小
SUNION SUNIONkey [key ...] 返回至少存在於一個集合中的元素(並集)
SUNIONSTORE SUNIONSTORE destination key [key ...] 將至少存在於一個集合中的元素(並集)儲存到 destination 中,返回並集大小

相關演示程式碼如下:

// 執行集合型別多個集合相關操作
func executeSetMutiOperation(conn redis.Conn) {
	// 刪除原有值
	handleResult(redis.Int(conn.Do("DEL", "source_1", "source_2", "source_3", "destination")))
	// 初始化
	handleResult(redis.Int(conn.Do("SADD", "source_1", 1, 2, 4, 8)))
	handleResult(redis.Int(conn.Do("SADD", "source_2", 2, 3, 4, 5)))
	handleResult(redis.Int(conn.Do("SADD", "source_3", 5, 6, 7, 8)))
	// 返回三個集合的差集,輸出 -> [1]
	handleResult(redis.Ints(conn.Do("SDIFF", "source_1", "source_2", "source_3")))
	// 將三個集合的差集儲存到 destination 中,輸出 -> 1,destination 變為 -> 1
	handleResult(redis.Int(conn.Do("SDIFFSTORE", "destination", "source_1", "source_2", "source_3")))
	// 返回兩個集合的交集,輸出 -> [2 4]
	handleResult(redis.Ints(conn.Do("SINTER", "source_1", "source_2")))
	// 將兩個集合的交集儲存到 destination 中,輸出 -> 2,destination 變為 -> 2 4
	handleResult(redis.Int(conn.Do("SINTERSTORE", "destination", "source_1", "source_2")))
	// 返回三個集合的並集,輸出 -> [1 2 3 4 5 6 7 8]
	handleResult(redis.Ints(conn.Do("SUNION", "source_1", "source_2", "source_3")))
	// 將三個集合的並集儲存到 destination 中,輸出 -> 8,destination 變為 -> 1 2 3 4 5 6 7 8
	handleResult(redis.Int(conn.Do("SUNIONSTORE", "destination", "source_1", "source_2", "source_3")))
}

雜湊表 P46

用於新增和刪除鍵值對的雜湊操作 P47
命令 格式 描述
HMGET HMGET key field [field ...] 從雜湊表中獲取一個或多個 field 的值
HMSET HMSET key field value [field value ...] 向雜湊表中設定一個或多個 field 的值
HDEL HDEL key field [field ...] 從雜湊表中刪除一個或多個 field 的值
HLEN HLEN key 返回雜湊表中包含的 field 的數量

相關演示程式碼如下:

// 執行雜湊表型別相關操作
func executeHashOperation(conn redis.Conn) {
	// 刪除原有值
	handleResult(redis.Int(conn.Do("DEL", "hash")))
	// 向雜湊表中設定一個或多個 field 的值,輸出 -> OK,hash 變為 -> {field_1: value_1, field_2: value_2, field_3: value_3}
	handleResult(redis.String(conn.Do("HMSET", "hash", "field_1", "value_1", "field_2", "value_2", "field_3", "value_3")))
	// 從雜湊表中獲取一個或多個 field 的值,輸出 -> [value_1 value_3 value_2]
	handleResult(redis.Strings(conn.Do("HMGET", "hash", "field_1", "field_3", "field_2")))
	// 從雜湊表中刪除一個或多個 field 的值,輸出 -> 2,hash 變為 -> field_2: value_2}
	handleResult(redis.Int(conn.Do("HDEL", "hash", "field_1", "field_3")))
	// 返回雜湊表中包含的 field 的數量,輸出 -> 1
	handleResult(redis.Int(conn.Do("HLEN", "hash")))
}
雜湊表的更高階特性 P47
命令 格式 描述
HEXISTS HEXISTS key field 判斷 field 是否存在於雜湊表中
HKEYS HKEYS key 返回雜湊表中所有的 field
HVALS HVALS key 返回雜湊表中所有 field 的值
HGETALL HGETALL key 返回雜湊表中所有的 field 及其值
HINCRBY HINCRBY key field increment 將雜湊表中 field 的值增加整數 increment
HINCRBYFLOAT HINCRBYFLOAT key field increment 將雜湊表中 field 的值增加浮點數 increment

相關演示程式碼如下:

// 執行雜湊表型別高階特性相關操作
func executeHashFeatureOperation(conn redis.Conn) {
	// 刪除原有值
	handleResult(redis.Int(conn.Do("DEL", "hash")))
	// 初始化
	handleResult(redis.String(conn.Do("HMSET", "hash", "field_1", "value_1", "field_2", "value_2", "field_3", "3")))
	// 判斷 field 是否存在於雜湊表中,輸出 -> 1
	handleResult(redis.Int(conn.Do("HEXISTS", "hash", "field_1")))
	// 返回雜湊表中所有的 field,輸出 -> [field_1 field_2 3]
	handleResult(redis.Strings(conn.Do("HKEYS", "hash")))
	// 返回雜湊表中所有 field 的值,輸出 -> [value_1 value_2 value_3]
	handleResult(redis.Strings(conn.Do("HVALS", "hash")))
	// 返回雜湊表中所有的 field 及其值,輸出 -> map[field_1:value_1 field_2:value_2 field_3:3]
	handleResult(redis.StringMap(conn.Do("HGETALL", "hash")))
	// 將雜湊表中 field 的值增加 1,輸出 -> 4,field_3 的值變為 -> 4
	handleResult(redis.Int(conn.Do("HINCRBY", "hash", "field_3", 1)))
	// 將雜湊表中 field 的值增加 -1.5,輸出 -> 2.5,field_3 的值變為 -> 2.5
	handleResult(redis.Float64(conn.Do("HINCRBYFLOAT", "hash", "field_3", -1.5)))
}

如果雜湊表包含的值非常大,可以先使用 HKEYS 取出所有的 field,然後再使用 HGET 取出值,防止一次取出多個大體積的值而導致伺服器阻塞。 P48

有序集合 P48

一些常用的有序集合命令 P49
命令 格式 描述
ZADD ZADD key socre member [score member ...] 向有序集合中新增一個或多個元素及其分值
ZREM ZREM key member [member ...] 從有序集合中刪除一個或多個元素及其分值
ZCARD ZCARD key 返回有序集合中元素的個數
ZINCRBY ZINCRBY key increment member 給有序集合中的元素的分值增加 increment
ZCOUNT ZCOUNT key min max 返回分值在 [min, max] 範圍內的元素的數量
ZRANK ZRANK key member 返回元素的升序排名(升序,從 0 開始)
ZREVRANK ZREVRANK key member 返回元素的降序排名(降序,從 0 開始)
ZSCORE ZSCORE key member 返回元素的排名的分值
ZRANGE ZRANGE key start stop [WITHSCORES] 返回升序排名在 [start, stop] 範圍內的元素,WITHSCORES 選項會同時在相應的元素後返回分值
ZRANRANGE ZRANGE key start stop [WITHSCORES] 返回降序排名在 [start, stop] 範圍內的元素,WITHSCORES 選項會同時在相應的元素後返回分值

相關演示程式碼如下:

// 執行有序集合相關操作
func executeZsetOperation(conn redis.Conn) {
	// 刪除原有值
	handleResult(redis.Int(conn.Do("DEL", "zset")))
	// 有序集合中新增 5 個元素及其分值,輸出 -> 5,zset 變為 -> ["a":1, "b":2, "c":3, "d":4, "e":5]
	handleResult(redis.Int(conn.Do("ZADD", "zset", 1, "a", 2, "b", 3, "c", 4, "d", 5, "e")))
	// 有序集合中刪除 3 個元素及其分值,輸出 -> 2,zset 變為 -> ["a":1, "b":2, "c":3]
	handleResult(redis.Int(conn.Do("ZREM", "zset", "d", "e", "f")))
	// 返回有序集合的元素個數,輸出 -> 3
	handleResult(redis.Int(conn.Do("ZCARD", "zset")))
	// 給有序集合中的元素的分值增加 0.5,輸出 -> 1.5,a 的值變為 -> 1.5
	handleResult(redis.Int(conn.Do("ZINCRBY", "zset", 1, "a")))
	// 給有序集合中的元素的分值增加 -1.5,輸出 -> 0.5,a 的值變為 -> 0.5
	handleResult(redis.Float64(conn.Do("ZINCRBY", "zset", -1.5, "a")))
	// 返回分值在 [1, 3] 範圍內的元素的數量,輸出 -> 2
	handleResult(redis.Int(conn.Do("ZCOUNT", "zset", 1, 3)))
	// 返回元素的升序排名(升序,從 0 開始),輸出 -> 0
	handleResult(redis.Int(conn.Do("ZRANK", "zset", "a")))
	// 返回元素的降序排名(降序,從 0 開始),輸出 -> 2
	handleResult(redis.Int(conn.Do("ZREVRANK", "zset", "a")))
	// 返回元素的排名的分值,輸出 -> 0.5
	handleResult(redis.Float64(conn.Do("ZSCORE", "zset", "a")))
	// 返回升序排名在 [1, 2] 範圍內的元素,並且返回分值,輸出 -> map[b:2 c:3]
	handleResult(redis.StringMap(conn.Do("ZRANGE", "zset", "1", "2", "WITHSCORES")))
	// 返回降序排名在 [1, 2] 範圍內的元素,並且返回分值,輸出 -> map[a:0.5 b:2]
	handleResult(redis.StringMap(conn.Do("ZREVRANGE", "zset", "1", "2", "WITHSCORES")))
}
有序集合的範圍性命令及並交集命令 P50
命令 格式 描述
ZRANGEBYSCORE ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] 返回升序分值在 [min, max] 範圍內的元素,WITHSCORES 選項會同時在相應的元素後返回分值
ZREVRANGEBYSCORE ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count] 返回降序分值在 [max, min] 範圍內的元素,WITHSCORES 選項會同時在相應的元素後返回分值
ZREMRANGEBYRANK ZREMRANGEBYRANK key start stop 移除升序排名在 [start, stop] 範圍內的元素
ZREMRANGEBYSCORE ZREMRANGEBYSCORE key min max 移除升序分值在 [min, max] 範圍內的元素
ZINTERSTORE ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]]  [AGGREGATE SUM|MIN|MAX] 求一個或多個(有序)集合的交集,並儲存到 destination 中,WEIGHTS 權重存在時,weight 數量必須等於 numkeys(集合預設分值為 1)
ZUNIONSTORE ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]]  [AGGREGATE SUM|MIN|MAX] 求一個或多個(有序)集合的並集,並儲存到 destination 中,WEIGHTS 權重存在時,weight 數量必須等於 numkeys(集合預設分值為 1)

相關演示程式碼如下:

// 執行有序集合範圍及交併集相關操作
func executeZsetMutiOperation(conn redis.Conn) {
	// 刪除原有值
	handleResult(redis.Int(conn.Do("DEL", "zset_1", "zset_2", "destination")))
	// 初始化
	handleResult(redis.Int(conn.Do("ZADD", "zset_1", 1, "a", 2, "b", 3, "c")))
	handleResult(redis.Int(conn.Do("ZADD", "zset_2", 2, "b", 3, "c", 4, "d")))
	// 返回升序分值在 [1, 2] 範圍內的元素,並且返回分值,輸出 -> map[a:1 b:2]
	handleResult(redis.StringMap(conn.Do("ZRANGEBYSCORE", "zset_1", "1", "2", "WITHSCORES")))
	// 返回降序分值在 [4, 3] 範圍內的元素,並且返回分值,輸出 -> map[c:3 d:4]
	handleResult(redis.StringMap(conn.Do("ZREVRANGEBYSCORE", "zset_2", "4", "3", "WITHSCORES")))
	// 移除升序排名在 [1, 1] 範圍內的元素,輸出 -> 1,zset_1 變為 -> ["b":2, "c":3]
	handleResult(redis.Int(conn.Do("ZREMRANGEBYRANK", "zset_1", "1", "1")))
	// 移除降序排名在 [2, 2] 範圍內的元素,輸出 -> 1,zset_2 變為 -> ["c":3, "d":4]
	handleResult(redis.Int(conn.Do("ZREMRANGEBYSCORE", "zset_2", "2", "2")))
	// 求 2 個有序集合的交集,權重分別為 2, 3,分值預設採用加法
	// 並儲存到 destination 中,輸出 -> 1,destination 變為 ->
	handleResult(redis.Int(conn.Do("ZINTERSTORE", "destination", 2, "zset_1", "zset_2", "WEIGHTS", 2, 3)))
	// 求 2 個有序集合的並集,權重分別為 2, 3,分值指定採用最大值
	// 並儲存到 destination 中,輸出 -> 3,destination 變為 -> ["a":2, "c":9, "d":12]
	handleResult(redis.Int(conn.Do("ZUNIONSTORE", "destination", 2, "zset_1", "zset_2", "WEIGHTS", 2, 3, "AGGREGATE", "MAX")))
}

所思所想

  • 這一章又是比較枯燥的命令介紹,不過還是堅持看下來了,發現還是挺有用的,有很多平常沒接觸的命令,也沒想到 Redis 竟然這麼強大。

  • 即使時比較精細地閱讀,也不需要全部閱讀,可以快速瀏覽已經知道的基礎,重點還是要放在不知道的地方,帶著思考去閱讀,先想然後用實踐驗證。

本文首發於公眾號:滿賦諸機(點選檢視原文) 開源在 GitHub :reading-notes/redis-in-action

相關文章