字串 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 |
相關演示程式碼如下(main
及 handleResult
定義見: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 可以通過使用子串操作和二進位制位操作,配合 WATCH
、MULTI
和 EXEC
命令(後面會初步介紹,以後將深入講解),構建任何想要的資料結構。
列表 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