Redis 实战 —— 04. Redis 数据结构常用命令简介
字符串 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 数据结构简介.md):
// 执行字符串类型数字相关操作
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
Redis 实战 —— 04. Redis 数据结构常用命令简介的更多相关文章
- Redis启动服务和String常用命令
Redis启动服务和String常用命令 1. 启动Redis服务 E:\redis>redis-server.exe redis.windows.conf _._ _.-``__ ''-._ ...
- Redis实战之Redis + Jedis
用Memcached,对于缓存对象大小有要求,单个对象不得大于1MB,且不支持复杂的数据类型,譬如SET 等.基于这些限制,有必要考虑Redis! 相关链接: Redis实战 Redis实战之Redi ...
- Redis实战之Redis + Jedis[转]
http://blog.csdn.net/it_man/article/details/9730605 2013-08-03 11:01 1786人阅读 评论(0) 收藏 举报 目录(?)[-] ...
- 第18章 Redis数据结构常用命令
18-1 字符串的一些基本命令 18-1 :配置Spring关于Redis字符串的运行环境 <bean id="poolConfig" class="redis.c ...
- Redis各数据结构常用命令
redis 通用API keys * 遍历所有key 一般不在生产环境中使用 redis单线程,容易阻塞其他命令执行 O(n) dbsize 计算key的总数 O(1)exists 检查key是否存在 ...
- Redis 实战 —— 05. Redis 其他命令简介
发布与订阅 P52 Redis 实现了发布与订阅(publish/subscribe)模式,又称 pub/sub 模式(与设计模式中的观察者模式类似).订阅者负责订阅频道,发送者负责向频道发送二进制字 ...
- Redis入门,Jedis和常用命令
一.Redis简介 1.关于关系型数据库和nosql数据库 关系型数据库是基于关系表的数据库,最终会将数据持久化到磁盘上,而nosql数据 库是基于特殊的结构,并将数据存储到内存的数据库.从性 ...
- redis五种数据类型和常用命令及适用场景
一.redis的5种数据类型: 1.基础理解: string 字符串(可以为整形.浮点型和字符串,统称为元素) list 列表(实现队列,元素不唯一,先入先出原则) set 集合(各不相同的元素) h ...
- Redis实战之Redis命令
阅读目录 1. 字符串命令 2. 列表命令 3. 集合命令 4. 散列命令 5. 有序集合命令 6. 发布与订阅命令 7. 小试牛刀 Redis可以存储键与5种不同数据结构类型之间的映射,这5种数据结 ...
随机推荐
- 关于Java Integer和Long直接比较
Integer和Long不能直接equals比较会返回False Long.class源码 ` public boolean equals(Object obj) { if (obj instance ...
- 最全总结 | 聊聊 Python 办公自动化之 PDF(上)
1. 前言 自动化办公,非 Python 莫属! 从本篇文章开始,我们继续聊聊自动化办公中另外一个常用系列:PPT 2. 准备一下 Python 操作 PPT 最强大的依赖库是:python-pptx ...
- css进阶 06-CSS开发积累
06-CSS开发积累 #让flex盒子中的子元素们,居中 flex布局常用的三行代码: display: flex; justify-content: center; // 子元素在横轴的对齐方式 ( ...
- 分析《令人心动的offer2》网友们都在吐槽什么?
综艺,是我们劳累了一天的放松方式,也是我们饭后的谈资.看着自己喜欢的综艺,时光足够美.而<令人心动的offer >,就是一个不错的综艺选择.有人说它让自己更自卑了,而我觉得挺有意思. &l ...
- Java基础进阶:时间类要点摘要,时间Date类实现格式化与解析源码实现详解,LocalDateTime时间类格式化与解析源码实现详解,Period,Duration获取时间间隔与源码实现,程序异常解析与处理方式
要点摘要 课堂笔记 日期相关 JDK7 日期类-Date 概述 表示一个时间点对象,这个时间点是以1970年1月1日为参考点; 作用 可以通过该类的对象,表示一个时间,并面向对象操作时间; 构造方法 ...
- C# 锁与死锁
什么是死锁: 所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进. 因此我们举个例子来描述,如果此时有一个线程A,按照先锁a再 ...
- CentOS7离线安装mysql5.6
下载mysql5.6,系统选择redhat,版本选择RHEL7,下载RPM Bundle后得到一个tar文件.这里得到文件MySQL-5.6.44-1.el7.x86_64.rpm-bundle.ta ...
- 安装Yii2框架
一.Windows安装Yii2 1.安装Composer Composer 需要 PHP 5.3.2+ 以上版本,且需要开启 openssl,打开 php 目录下的 php.ini,将 extensi ...
- niceyoo的2020年终总结-2021年Flag
碎碎念,向本命年说再见! 又到了一年一度立 Flag 的时间了,怎么样,去年的 Flag 大家实现的怎么样?还有信心立下 2021 年的 Flag 吗~ 今年我算比较背的,年初的一次小意外,直接在床上 ...
- python之scrapy篇(三)
一.创建工程(cmd) scrapy startproject xxxx 二.编写item文件 # -*- coding: utf-8 -*- # Define here the models for ...
