Redis 基础
语法
首先,Redis 是 key - Value 键值对内存数据库,它使用五种基本数据类型来保存 Value 数据,我们先来看看 Redis 中对 Key 的相关操作,后面再来介绍这五种 Value 类型,下面我们分别来介绍。
Redis 的 Key
查找:keys、randomkey、exists、type 和 dump 命令
// keys pattern : pattern 是键的匹配模式,与正则表达式稍有差异
// pattern 允许通配符 ?(匹配一个任意字符),*(匹配任意多个任意字符),若要匹配 ?、* 等特殊字符则使用 \ 进行转义,
// 同时允许使用正则表达式中的 [] ,但不与 ?、* 同用,似也不能使用预编译的 \d ,\S 等
keys [^0-9]* // 匹配不以数字开头的所有 Key
// randomkey : 从所有的 Key 中随机返回一个
// exists Key :判断指定的 Key 是否存在
// type Key :判断指定的 Key 保存着何种类型的 Value
// dump Key : 将指定的 Key 序列化后返回
修改:rename 和 renamenx 命令
// rename old_Key new_Key :更改指定 Key(由 old_Key 指定) 的名字为 new_Key
// renamenx old_Key new_Key :更改指定 Key(由 old_Key 指定) 的名字为 new_Key,如果 new_Key 不存在的话。
// 失败返回 (integer) 0
删除:del 命令
// del Key :删除指定名称的 Key
定时操作:expire、pexpire、expireat、pexpireat、persist、ttl 和 pttl 命令
// expire Key seconds :设置此键 seconds 秒后失效,成功返回 1
// pexpire Key mills :设置此键 mills 毫秒后失效,成功返回 1
// expireat Key timestamp:设置此键在 (Unix) timestamp 这个时间点失效,以秒为单位,成功返回 1
// pexpireat Key timestamp:设置此键在 (Unix) timestamp 这个时间点失效,以毫秒为单位,成功返回 1
// persist Key :设置 Key 不会失效,成功返回 1
// ttl Key :返回此键距离失效还多长时间,以秒为单位,返回值: -2 无此键盘,-1 无失效,> 0 有效值
// pttl Key :返回此键距离失效还多长时间,以毫秒为单位,返回值: -2 无此键盘,-1 无失效,> 0 有效值
接下来,我们就来了解一下 Redis 的五种 Value 类型。
String 字符串
String 类型就是字符串类型,它是二进制安全的,也就是说字符串是以二进制流进行处理,不会对其进行其余的操作,比方说转义字符,"\\" 在其余环境下可能就是一个 "\" ,但是在 Redis 中它就是 "\\",String 类型的值最多能够存储 512 MB 的数据,接下来我们简单看一下,如何在 Redis 中保存和查找一个字符串值:
保存: set、mset、setex、psetex、setnx 和 msetnx 命令
// set String_Key String_Value: 设置一个字符串类型的 Redis 键值对
// setnx String_Key String_Value: 如果指定的键不存在就设置一个字符串类型的 Redis 键值对
set stringkey stringvalue
// set 命令一次只能设置一个 Key-Value 对,而 mset 可以同时设置多个 Key-Value 对
// mset Key_1 Value_1 [Key_2 Value_2] [...]:同时设置多个字符串类型的 Redis 键值对
// msetnx Key_1 Value_1 [Key_2 Value_2] [...]:同时设置多个字符串类型的 Redis 键值对,但是一旦出现重复全部不生效
mset key1 value1 key2 value2 key3 value3
// setex String_Key seconds String_Value :设置 String 类型的 Redis 键值对,但是在 seconds 秒后此键失效
setex key1 5 value1 // 5 秒后 key1 失效
// psetex String_Key mills String_Value :设置 String 类型的 Redis 键值对,但是在 mills 毫秒后此键失效
psetex key2 1000 value2 // 1000 毫秒后 key2 失效
查找: get、getrange、getbit、mget 和 strlen 命令
// get String_Key :获取指定 Redis 键的字符串值
get stringkey
执行结果: "stringvalue"
// getrange String_Key start end :获取指定 Redis 键的字符串值中指定索引区间 [start, end] 中的字符集合
getrange stringkey 0 -6
运行结果:"string"
为什么是 "string" 呢?那是因为 Redis 索引设置的问题,对于一个字符串,它这样规定:
顺序索引: 0 1 2 3 5 6 7 8 9 10 11
逆序索引: -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1
字符串值: s t r i n g v a l u e
可以看出规定顺序索引是从 0 开始的,而一个负数索引,比如 -6 指的是从右往左(逆序)数过来的第六位字符,所以 [0, -6] 表示从左边第一位开始到逆序数来的第六位为止,这个概念很重要,后面会重复利用到,也会再简单重复一次。
// getbit String_Key offset:获取指定 Redis 键的字符串值的二进制流中偏移开头第一位的二进制位
getbit stringkey 6 // 运行结果:(integer) 1
这个 1 是怎么来的呢?因为 getbit 是获取二进制流中的偏移二进制位,所以我们需要写出 stringkey 对应值 stringvalue 的二进制流,这里因为只偏移 6 ,而 s 的 ascii 码为 115 ,对应二进制编码为 : 01110011,而偏移 6 位就是第 7 位的二进制值,也就是 1,故得 1。
// 同理,get 只能查一个 Redis 键值对,而 mget 可以查多个
// mget String_Key1 [String_Key2] [...] : 获取多个指定 Redis 键的字符串值
mget key1 key2 key3
执行结果: 1) "value1"
2) "value2"
3) "value3"
// strlen String_Key :获取指定 Redis 键的字符串值的长度,也就是由多少个字符组成
strlen stringkey // 运行结果:(integer) 11
修改:getset、incr、incrby、incrbyfloat、decr、decrby 、append 和 setbit 命令
// getset String_Key String_Value :设置新值并返回旧值
getset stringkey string_value_new // 运行结果:"stringvalue"
// incr stringkey :将指定 Redis 键的字符串值加一,如果可以的话。返回修改后的值
// decr stringkey :将指定 Redis 键的字符串值减一,如果可以的话。返回修改后的值
setex test 60 1
incr test // 运行结果:"2"
decr test // 运行结果:"1"
// incrby / incrbyfloat stringkey increment : 将指定 Redis 键的字符串值加 increment,如果可以的话。
// 前者要为整数字符串,后者为浮点数字符串,返回修改后的值
// decrby stringkey increment : 将指定 Redis 键的字符串值减 increment,如果可以的话。
// 值要为整数字符串,返回修改后的值
setex test 60 1
incr test 3 // 运行结果:(integer) 4
decr test 3 // 运行结果:(integer) 1
// append String_Key String_Value : 在指定 Redis 键的字符串值后追加 String_Value,返回追加后的字符串长度
append stringkey _append // 运行结果:(integer) 19
// setbit String_Key offset value:设置指定 Redis 键的字符串值的二进制流中
// 偏移开头第一位的二进制位为 value(0 或 1),成功返回 1
在开始之前,我们先分析一波,stringkey 键的值现在是 string_value_append ,由前面的讨论可知,s 的二进制编码是 01110011,我们先看看运行结果:
setbit stringkey 6 0 // 运行结果:(integer) 1
get stringkey // 运行结果:"qtring_value_append"
为什么 s 会变成 q 呢?因为 01110011 偏移 6 位,就是第七位,然后将它改为 0,也就是变成了这样:
顺序索引: 0 1 2 3 5 6 7 8
原二进制: 0 1 1 1 0 0 1 1 // 115 ASCII码表示为 s
今二进制: 0 1 1 1 0 0 0 1 // 113 ASCII码表示为 q
故原字符串的 s 变为了 q。
删除:del 命令
// del Key :直接删除 Redis 中的一个 Key-Value 键值对,它可以用以删除任意 Redis Key-Value 对
del stringkey
Hash 哈希
Hash 也是 Redis 的一种值类型,而且 Hash 类型不似 String 类型,它是一个集合,最多可有 2^32 - 1 个元素,每个元素又是一个键值对。接下来介绍一下如何在 Redis 中简单保存和获取一个 Hash 类型的值:
保存: hset 和 hmset 命令
// hset Key Value_key Value_value : Key 是 Redis Key-Value 中的 Key,而 Value_key Value_value 则是 Value 集合中的一个元素
hset book bookId_1 bookName_Java
// 同理 hset 只能设置 Value 集合中的一个元素,hmset 则可同时设置多个 Value 集合元素
// hmset Key Value_key1 Value_value1 [Value_key2 Value_value2] [...]
hmset book bookId_1 bookName_Java bookId_2 bookName_C bookId_3 bookName_Python
查找:hget 、hmget、hgetall 、hexists、hlen、hkeys 和 hvals命令
// 获取指定 Key 的 Hash 集合中的指定键的值
hget book bookId_1
运行结果:"bookName_Java"
// hmget Hash_Key value_key1 [value_key2] [...] :查找集合中的指定元素(通过键指定)
hmget book bookId_1 bookId_2 bookId_3
运行结果:
1) "bookName_Java"
2) "bookName_C"
3) "bookName_Python"
// 获取指定 Key 的 Hash 集合中的所有键值对信息
hgetall book
运行结果: 1) "bookId_1"
2) "bookName_Java"
3) "bookId_2"
4) "bookName_C"
5) "bookId_3"
6) "bookName_Python"
// hexists Hash_Key value_key1: 键值对集合中是否存在指定键的元素,返回匹配的元素总数
hexists book bookId_1
运行结果:(integer) 1
// hlen Hash_Key :返回键值对集合的元素总数
hlen book
运行结果:(integer) 3
// hkeys Hash_Key :获取键值对集合中所有元素的键
hkeys book
运行结果:
1) "bookId_1"
2) "bookId_2"
3) "bookId_3"
// hvals Hash_Key :获取键值对集合中所有元素的值
hvals book
运行结果:
1) "bookName_Java"
2) "bookName_C"
3) "bookName_Python"
修改:当要修改 Value 集合中的某个已存在的元素的键值对中的值时,可以重新保存覆盖原值。
// hincrby Hash_Key value_key increment: 如果键值对集合中的指定元素的值是整型数据,
// 那么可以使用此命令使其键增减 increment,返回修改后的数值
// hincrbyfloat Hash_Key value_key increment: 如果键值对集合中的指定元素的值是浮点型数据,
// 那么可以使用此命令使其键增减 increment,返回修改后的数值
// 示例:
hmset test int 1 float 2.0
hincreby test int 5 // 运行结果:(integer) 6
hincrbyfloat test float 8 // 运行结果:"10"
删除:当要删除 Value 集合中的元素时,可以使用 hdel 命令同时删除一个或者多个元素:
// hdel Key Value_key1 [Value_key2] [...]
hdel book bookId_1 bookId_2
List 列表
List 类型也是一个集合类型,但是它允许集合中有多个相同的元素(所以严格来说它并不是集合,故而称其为列表),而 Hash 类型虽也是集合类型,但其每个元素的键都不允许重复,List 类型集合中的元素也并非键值对,而是单值的,元素数量最多为 2^32 - 1 个,同时允许以队列的形式来操作集合列表。接下来了解一下如何保存和获取一个 List 类型的值:
保存:lpush 、 rpush 和 linsert 命令
// 在集合列表左边,也就是队列头部前面顺序添加一个或多个元素
// lpush Key value_1 [value_2] [...]
lpush queue 1 2 3
列表结果: 3 2 1
// 在集合列表右边,也就是队列尾部后面顺序添加一个或多个元素
// rpush Key value_1 [value_2] [...]
rpush queue 1 2 3
列表结果:3 2 1 1 2 3
// 在指定的元素(通过值匹配而非索引)前或后插入一个元素,
// 若有多个匹配以从左到右匹配到的第一个元素为准
// linsert List_Key (before| after) pivot value
linsert queue after 2 100
列表结果:3 2 100 1 1 2 3
查找:lrange 和 lindex 命令
// 可以先用 llen 命令了解队列长度
// llen Key
llen queue
运行结果:(integer) 7
// 按照从左到右的顺序遍历队列来查找所有元素或者在指定区间 [start, stop] 内的所有元素
// 当 stop = -1 时表示遍历列表所有元素,注意 start 和 stop 都是指索引 index
// lrange Key start stop
lrange queue 0 -1
运行结果: 1) "3"
2) "2"
3) "100"
4) "1"
5) "1"
6) "2"
7) "3"
// 使用 lindex 命令可以查看列表中指定位置索引的元素值,等效于 queue[index]
// 注意 index 是从 0 开始计数的,而不是如上面的运行结果一般从 1 开始
// lindex List_Key index
lindex queue 3
运行结果:"1"
对于索引,Redis 有其自己的设定,除了大家所熟知的从前往后递增的从 0 开始的索引,还有从后往前递减的从 -1 开始的索引,暂且称其为逆序索引,所谓 -1 表示的是从后往前数列表中第一个元素,大概就是这样:
数值索引: 0 1 2 3 4 5
逆序索引: -6 -5 -4 -3 -2 -1
元素集合: 3 2 1 1 2 3
所以 lrange queue 0 -1,之所以可以遍历整个队列是因为:索引 0 表示开始元素是队列第一个元素,索引 -1 表示结束元素是队列从后往前数的第一个元素,也就是最后一个元素,如此便把整个队列都包含进了队列里。
修改: lset 命令
// lset 用来修改列表中指定索引的元素值
// lset List_Key index value
lset queue 3 1000
列表结果:3 2 100 1000 1 2 3
删除:lpop、rpop、lrem 和 ltrim 命令
// lpop List_Key :返回列表最左边的元素,即队头元素
lpop queue
运行结果:"3"
列表结果:2 100 1000 1 2 3
// rpop List_Key :返回列表最右边的元素,即队尾元素
rpop queue
运行结果:"3"
列表结果:2 100 1000 1 2
// lrem List_Key count value:移除指定数量(通过 count 指定)的指定元素(通过 value 匹配)
// count > 0 时从左往右匹配 |count| 个元素; count < 0 时从右往左匹配 |count| 个元素; count = 0 时匹配所有元素
// 返回移除的元素数量
lrem queue -1 1
运行结果:(integer) 1
列表结果:2 100 1000 2
// 又如
lrem queue -2 2
运行结果:(integer) 2
列表结果:100 1000
// ltrim key start stop :不在 [start, stop] 区间内的所有元素都删除, start < stop 时无动作
ltrim queue 0 1
列表结果:100 1000
Set 集合
List 类型允许集合中有重复的值,但是 Set 类型却不允许有重复的值,正如集合自身的定义,元素无序而唯一,元素数量同样地,不超过 2^32 - 1 个。下面简单介绍一下在 Redis 中如何保存和查找一个 Set 类型的值:
保存:sadd 命令
// sadd Set_Key value1 [value2] [...] :往一个 Set 类型集合中添加一个或多个唯一元素,
// 返回添加成功的元素数量
sadd myset 1 2 3
运行结果:(integer) 3
查找:scard 、smembers、sismember 和 srandmember 命令
// scard Set_key:获取集合元素总数
scard myset
运行结果:(integer) 3
// smembers Set_Key:获取集合中的所有元素
smembers myset
运行结果: 1) "1"
2) "2"
3) "3"
// sismember Set_Key value:询问某个值是不是集合中的元素,返回值 0 表示不是
sismember myset 5
运行结果:(integer) 0
// srandmember Set_Key [count]:count 可选的,缺省为 1,从集合中返回 count 个随机元素
srandmember myset 2
运行结果(多次执行结果会不一样): 1) "2"
2) "1"
删除:spop 、srem 和 smove 命令
// spop Set_Key : 移除集合中的一个随机元素并返回
spop myset
运行结果:"2"
// srem Set_key value1 [value2] [...]:移除集合中一个或多个指定元素,返回移除成功的元素个数
srem myset 2 3
运行结果:(integer) 1
// smove Set_Key_1 Set_Key_2 value : 将 Set_Key_1 集合中指定的元素(value)剪切到 Set_Key_2 集合中
// 返回剪切成功的元素个数,0 为剪切失败
smove myset yourset 2
运行结果:(integer) 0
集合的专属特殊操作:交、并、差运算
// 创建两个 Set 类型的集合
sadd myset 1 2 3
sadd yourset 1 5 6
// 并运算: myset 并 yourset
// sunion Set_Key_1 [Set_Key_2] [...] :返回多个集合的并集
// sunionstore destination_Set_Key Set_Key_1 [Set_Key_2] [...] :
// 将多个集合的并集结果保存到 destination_Set_Key 中,并返回并集元素总数
sunion myset yourset
运行结果:
1) "1"
2) "2"
3) "3"
4) "5"
5) "6"
// 交运算: myset 交 yourset
// sinter Set_Key_1 [Set_Key_2] [...] :返回多个集合的交集
// sinterstore destination_Set_Key Set_Key_1 [Set_Key_2] [...] :
// 将多个集合的并集结果保存到 destination_Set_Key 中,并返回交集元素总数
sinter myset yourset
运行结果:
1) "1"
// 差运算: myset - yourset
// sdiff Set_Key_1 [Set_Key_2] [...] :返回第一个集合与其他集合的差集,
// 即将第一个集合后的所有集合先并起来,再与第一个集合进行差运算或者顺序做差运算
// sdiffstore destination_Set_Key Set_Key_1 [Set_Key_2] [...] :
// 将第一个集合与其他集合的差集结果保存到 destination_Set_Key 中,并返回差集元素总数
sdiff myset yourset
运行结果:
1) "2"
2) "3"
Zset 有序集合
相比 Set 类型,它们的区别在于元素是否有序,Zset 类型的集合元素是有序的,而 Set 类型的集合元素是无序的,那它是如何确保有序的呢?答每个元素在新增时给它绑定了一个双浮点型的分数,集合中的元素就按照这个分数进行排序。同样的,我们来看一下在 Redis 中如何保存或者查找一个 Zset 类型:
保存: zadd 命令
// zadd ZSet_Key score1 value1 [score2 value2] [...] : 往一个 Zset 集合中添加一个或多个带有分数的元素,
// 返回加入成功的元素个数
zadd myzset 1.0 one 2.0 two 3.0 three 3.0 three1 3.0 three2 3.0 three3
运行结果:(integer) 6
查找:zcard、zcount、zlexcount、zrange、zrevrange、zrangebylex、zrangebyscore、zrevrangebyscore、zrank、zrevrank 和 zscore 命令
// zcard ZSet_Key: 返回集合元素总数
zcard myzset
运行结果:(integer) 6
// zcount ZSet_Key minscore maxscore : 返回分数在区间 [minscore, maxscore] 中的元素总数
zcount myzset 0.5 2
运行结果:(integer) 2
在这里要特别的讲一下,lex 是什么,它被译为字典,也就是在元素分数不一致时,按照分数顺序排,而分数一样时,按照字典顺序排,所谓字典顺序就比如 a-z, A-Z。
// zlexcount ZSet_Key min max : 当集合中的元素分数都一样时,根据字典顺序排序,
// 此命令将获取字典顺序在区间 [min, max] 中的元素总数,当下面选用 '(' 时表示开区间,
// min = '-' 或 '[ | (' + 一个字符串,max = '+' 或 '[ | (' + 一个字符串
//
// zrangebylex ZSet_Key min max [limit offset count]:根据字典顺序获取在区间 [min, max] 中的所有元素结果集,
// 此命令也只有在集合中的元素分数都一样的情况下才生效
// limit offset count 为可选字段,limit 表示限制返回结果集的数量,
// offset 表示从结果集中偏移多少个元素,
// count 表示偏移后再取几个元素作为返回值
// 示例:以一个分数全相同的 Zset 来测试
zadd testlex 0 a 0 b 0 c 0 cc 0 d 0 e
zlexcount testlex - + // - + 表示无上下限
运行结果:(integer) 6
zlexcount testlex [cc [e // 表示计算 [cc, e] 中的所有元素总数,同 C 语言字符串比较方法
运行结果:(integer) 3
zlexcount testlex [cc (e // 表示计算 [cc, e) 中的所有元素总数,同 C 语言字符串比较方法
运行结果:(integer) 2
zrangebylex testlex - + // 获取所有元素
运行结果:
1) "a"
2) "b"
3) "c"
4) "cc"
5) "d"
6) "e"
zrangebylex testlex [cc [e // 获取区间 [cc, e) 中的所有元素
运行结果:
1) "cc"
2) "d"
3) "e"
zrangebylex testlex - + limit 3 2 // 从开始位置偏移 3 个元素,再取 2 个元素作为结果集返回
运行结果:
1) "cc"
2) "d"
集中了解完这个 lex 的概念后,就回到正轨来继续介绍 zrange、zrevrange、zrangebyscore、zrevrangebyscore、zrank、zrevrank 和 zscore 命令:
// zrange ZSet_Key start stop [withscores]:获取指定下标区间 [start, stop] 的所有元素,withscores 表示是否携带分数
// start 和 stop 与在 List 类型中所了解的概念一样,是索引 index 值
// zrevrange ZSet_Key start stop [withscores]: zrevrange 相当于把这个集合倒置了,比如 zrange 是升序排列,那么 zrevrange 就是降序排列。
zrange myzset 0 -1 withscores
运行结果:
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "three1"
8) "3"
9) "three2"
10) "3"
11) "three3"
12) "3"
zrange myzset 3 -2
运行结果:
1) "three1"
2) "three2"
zrevrange myzset 3 -2
运行结果:
1) "three"
2) "two"
// zrangebyscore ZSet_Key minscore maxscore [withscores] [limit offset count]: 获取集合中指定分数区间的元素,
// 重复的字段就不再解释了,等会直接看例子
// zrevrangebyscore ZSet_Key maxscore minscore [withscores] [limit offset count]: 原理同 zrevrange,
// 注意分数区间变为了 [maxscore, minscore]
zrangebyscore myzset 2.3 3.0 withscores limit 1 3
运行结果:
1) "three1"
2) "3"
3) "three2"
4) "3"
5) "three3"
6) "3"
zrevrangebyscore myzset 3.0 2.3 withscores limit 1 3
运行结果:
1) "three2"
2) "3"
3) "three1"
4) "3"
5) "three"
6) "3"
// zrank ZSet_Key member : 返回集合中指定元素的索引,从 0 开始
// zrevrange ZSet_Key member : 同理,返回逆序排列中此元素的索引,也是从 0 开始
zrank myzset three
运行结果:(integer) 2
zrevrank myzset three
运行结果:(integer) 3
// zscore ZSet_Key member :返回集合中指定元素的分数
zscore myzset three
运行结果:"3"
修改:zincrby 命令
// zincrby ZSet_Key increment menmber : 将集合中指定元素的分数增加 increment,并返回此元素最终的分数
zincrby myzset 10.5 one
运行结果:"11.5"
删除:zrem、zremrangebylex、zremrangebyrank 和 zremrangebyscore 命令
// zrem ZSet_Key member1 [member2] [...] :移除集合中一个或多个元素,返回成功移除的个数
zrem myzset three1 three2
运行结果:(integer) 2
// zremrangebyscore ZSet_Key minscore maxscore:移除集合中指定分数闭区间内的所有元素,返回成功移除的个数
zremrangebyscore myzset 1.35 2.88
运行结果:(integer) 1
// zremrangebyrank ZSet_Key start stop :移除集合中指定索引闭区间内的所有元素,返回成功移除的个数
zremrangebyrank myzset 2 -1
运行结果:(integer) 1
// zremrangebylex ZSet_Key min max :移除集合(这个命令执行完后所有元素的分数都是 3,所以 lex 排序生效)
// 中指定字典排序闭区间内的所有元素,返回成功移除的个数
zremrangebylex myzset [three [three
运行结果:(integer) 1
集合的交并运算
首先,在原有基础上,执行以下命令,新增一个 ZSet 集合:
zadd zset 1 one 2 two
zadd myzset 1 one 2 two
然后先来看并运算:
// zunionstore destination key_num ZSet_Key_1 [ZSet_Key2] [...] [weights weight1 [weight2] [...]] [aggregate (sum | min | max)]
// destination 表示结果集存放到这里,key_num 表示指定数量的 ZSet 集合参与并运算,
// weights 后面跟着 key_num 个数字,与前面 key_num 个 ZSet 集合一一对应,表示一个集合里的所有元素在合并的时候要乘以这个因子,缺省为 1
// aggregate 表示合并时分布在不同集合中的相同元素的分数要怎么取,sum 表示累加,min 表示取最小的,max 取最大的,缺省为 sum
// 返回新集合的元素总数,示例:
zunionstore out 2 myzset zset weights 2 3 aggregate sum
运行结果:(integer) 3
zrange out 0 -1 withscores
运行结果:
1) "one"
2) "5"
3) "three3"
4) "6"
5) "two"
6) "10"
交运算同理,示例:
// zinterstore destination key_num ZSet_Key_1 [ZSet_Key2] [...] [weights weight1 [weight2] [...]] [aggregate (sum | min | max)]
zinterstore in 2 myzset zset weights 2 3 aggregate sum
运行结果:(integer) 2
zrange in 0 -1 withscores
运行结果:
1) "one"
2) "5"
3) "two"
4) "10"