1. 安装 Redis
docker pull redis:3.0-alpine
docker images
docker run --restart=always -d -p 6379:6379 -v /root/redis/data:/home/renzheng/redis/data xxx --requirepass "password"
docker exec -it xxx sh
2. 热身
2.1 使用 redis-cli,并验证密码:
renzheng@qingdao:~$ docker exec -it 813 sh
/data # redis-cli
127.0.0.1:6379> auth bP623f@dhNfb
OK
选择数据库 (Redis 命令不区分大小写)
127.0.0.1:6379> select 0
OK
127.0.0.1:6379> select 1
OK
2.2 获得符合规则的 keys 列表
-
*
:任意个字符 -
?
:一个或多个字符 -
a[a-c]
:aa、ab、ac
keys *
会遍历 Redis 中所有键,如果键的数量较多则会影响性能,生产环境不建议使用
127.0.0.1:6379[1]> incr foo
(integer) 1
127.0.0.1:6379[1]> incr fool
(integer) 1
127.0.0.1:6379[1]> keys fo*
1) "foo"
2) "fool"
设值和取值:
127.0.0.1:6379[1]> set bar 1
OK
127.0.0.1:6379[1]> get bar
"1"
2.3 判断一个键是否存在
存在返回整数类型 1,否则返回 0
127.0.0.1:6379[1]> exists bar
(integer) 1
2.4 删除键
127.0.0.1:6379[1]> del bar
(integer) 1
Redis 中的 del
命令不支持批量删除,但是我们可以凭借 Linux 的管道删除多个键:
redis-cli keys "user*" | xargs redis-cli del
2.5 获得键值的数据类型
type
命令用于获取键值的数据类型,返回值可能是 string
(字符串)、hash
(散列)、list
(列表)、set
(集合类型)、zset
(有序集合类型)。
127.0.0.1:6379[1]> set bar 1
OK
127.0.0.1:6379[1]> type bar
string
127.0.0.1:6379[1]> get bar
"1"
3. 字符串类型
字符串类型是 Redis 中最基本的数据类型,能够存储任何形式的字符串,包括二进制数据。例如,可以存储一个邮箱,JSON 序列化之后的对象,甚至是一张图片。一个字符串类型键允许存储的是数据最大容量是 512 MB。
3.1 命令
3.1.1 赋值和取值
SET key value
GET key
例如:
127.0.0.1:6379[1]> set greet "Hi!"
OK
127.0.0.1:6379[1]> get greet
"Hi!"
如果键不存在会返回空结果
127.0.0.1:6379[1]> get a
(nil)
3.1.2 递增数字
INCR num
当存储的字符串是整数形式时,Redis 提供了一个 INCR
命令,可以让当前的键值递增,并返回递增后的值,如果键不存在会默认赋值 0。例如:
127.0.0.1:6379[1]> incr foo
(integer) 1
127.0.0.1:6379[1]> incr foo
(integer) 2
127.0.0.1:6379[1]> type foo
string
127.0.0.1:6379[1]> get foo
"2"
如果键不是整数,则出现如下错误:
127.0.0.1:6379[1]> incr greet
(error) ERR value is not an integer or out of range
包括 INCR
在内的所有 Redis 命令均为原子操作,不会出现并发冲突问题。
3.2 实践
3.2.1 文章访问量统计
每次访问文章使用 INCR
命令使响应的键值递增。
键一般使用 object:id:property
的形式,例如:post:1:page.view
3.2.2 生成自增 id
每新增一个对象都使用 INCR
命令。
INCR user:count
3.2.3 存储文章数据
对象序列化(JSON,MessagePack 等方式)。以存储 id 为 1的 文章为例:
set post:1:data str
3.3 其他命令
3.3.1 增加指定的整数
INCRBY
命令可以通过 increment
参数指定一次增加的数值
INCRBY key increment
127.0.0.1:6379[1]> set foo 100
OK
127.0.0.1:6379[1]> incrby foo 100
(integer) 200
127.0.0.1:6379[1]> get foo
"200"
3.3.2 减少指定的整数
DECR
命令与 INCR
命令用法相同,区别是让数值减少。与 INCRBY
命令的相似的便是 DECRBY
命令。
3.3.3 增加指定的浮点数
INCRBYFLOAT
命令类似 INCR
命令,差别是可以增加一个双精度浮点数。
INCRBYFLOAT key increment
例如:
127.0.0.1:6379[1]> set foo 1.000001
OK
127.0.0.1:6379[1]> incrbyfloat foo 0.000000003
"1.000001003"
3.3.4 向尾部追加值
APPEND
命令用来向键值末尾追加值。如果键不存在将该键的值设置为 value
。
APPEND key value
例如:
127.0.0.1:6379[1]> set foo "Hello"
OK
127.0.0.1:6379[1]> append foo ", world!"
(integer) 13
127.0.0.1:6379[1]> get foo
"Hello, world!"
3.3.5 获取字符串长度
STRLEN key
例如:
127.0.0.1:6379[1]> strlen foo
(integer) 13
3.3.6 同时获得/设置多个键值
MSET/MGET
命令与 GET/SET
命令相似,只不过 MSET/MGET
可以设置/获取多个键值。
MGET key [key ...]
MSET key value [key value ...]
例如:
127.0.0.1:6379[1]> mset foo 1 bar 2
OK
127.0.0.1:6379[1]> mget foo bar
1) "1"
2) "2"
3.3.7 位操作
GETBIT key offset (offset 从 0 开始)
SETBIT key offset value
BITCOUNT key
BITOP operation destkey key [key ...]
将 foo 设置为 "abc"(01100001 01100010 ..
)
127.0.0.1:6379[1]> set foo abc
OK
获取第 1、6 个 bit
127.0.0.1:6379[1]> getbit foo 1
(integer) 1
127.0.0.1:6379[1]> getbit foo 6
(integer) 0
如果偏移量超出键值实际长度,则默认为 0
127.0.0.1:6379[1]> getbit foo 30
(integer) 0
BITCOUNT
命令可以获得字符串类型键中值为 1 的二进制位个数,例如:
127.0.0.1:6379[1]> bitcount foo
(integer) 10
可以通过参数限制统计的字节范围,例如只统计前两个字节:
127.0.0.1:6379[1]> bitcount foo 0 1
(integer) 6
SETBIT
命令可以设置字符串类型键指定位置的二进制位的值,返回值是该位置的旧值:
127.0.0.1:6379[1]> setbit foo 1 0
(integer) 1
127.0.0.1:6379[1]> get foo
"!bc"
如果设置一个不存在的键的指定二进制位的值,会自动将其前面的位赋值为 0:
127.0.0.1:6379[1]> setbit test 10 0
(integer) 0
127.0.0.1:6379[1]> get test
"\x00\x00"
如果指定的二进制位超过了键值的实际长度,那么会自动将中间的位全部设置为 0
127.0.0.1:6379[1]> setbit foo 31 0
(integer) 0
127.0.0.1:6379[1]> get foo
"!bc\x00"
BITOP
命令可以对多个字符串类型键进行位运算,并将结果存在 destkey
指定的键中。支持的运算操作有 AND
、OR
、XOR
、NOT
。
127.0.0.1:6379[1]> set foo bar
OK
127.0.0.1:6379[1]> set foo aaa
OK
127.0.0.1:6379[1]> set bar bbb
OK
127.0.0.1:6379[1]> bitop or res foo bar
(integer) 3
127.0.0.1:6379[1]> get res
"ccc"
4. 散列(hash)类型
散列类型(hash)的键值也是一种字典结构,其存出了字段和字段值的映射,但是字段值只能是字符串,不支持其他数据类型。一个散列类型键至多包含 2^32 -1 个字段。
散列类型适合存储对象,以 object:id
构成键名,使用字段表示对象的属性,自字段值则存储属性值,例如:
[图片上传失败...(image-cf3390-1653622114110)]
散列类型不像关系型数据库那样要求所有的记录都有同样的属性,而存在无法为单独的某条记录增加属性的问题。Redis 完全可以自由地为任何键增减字段而不影响其他键。
4.1 常用命令
4.1.1 取值与赋值
HSET key field value
HGET key field
HMSET key field value [field value ...]]
HMGET key field [field ...]
HGETALL key
例如:
127.0.0.1:6379[1]> hset car color red (不存在该字段则建立该字段,返回 1;存在则更新,返回 0)
(integer) 1
127.0.0.1:6379[1]> hset car name "BMW"
(integer) 1
127.0.0.1:6379[1]> hset car price "500000"
(integer) 1
127.0.0.1:6379[1]> hmget car color name price
1) "red"
2) "BMW"
3) "500000"
127.0.0.1:6379[1]> hgetall car
1) "color"
2) "red"
3) "name"
4) "BMW"
5) "price"
6) "500000"
127.0.0.1:6379[1]> type car
hash
4.1.2 判断字段是否存在
HEXISTS key field
例如:
127.0.0.1:6379[1]> hexists car color
(integer) 1 (存在返回 1,不存在返回 0)
4.1.3 当字段不存在时赋值
HSETNX key field value
HSETINX
命令与 HSET
命令相似,只不过 HSETNX
只有字段不存在时才赋值,字段如果存在则不执行任何操作。
127.0.0.1:6379[1]> hsetnx person age 1
(integer) 0 // 存在返回 0
127.0.0.1:6379[1]> hget person age
"20"
127.0.0.1:6379[1]> hsetnx person height 165
(integer) 1 // 字段不存在,设值,且返回 1
4.1.4 增加数字
HINCRBY key field increment
HINCRBY
命令与 INCRBY
命令相似,如果字段不存在。Hash 类型没有类似 INCR
的命令,不过可以通过执行 HINCRBY key field 1
来实现。如果键或者字段不存在,那么将自动创建键和字段,并赋值为 increment
。
例:
127.0.0.1:6379[1]> hincrby car price 1
(integer) 500001
127.0.0.1:6379[1]> hincrby person age 20
(integer) 20
127.0.0.1:6379[1]> hgetall person
1) "age"
2) "20"
4.1.5 删除字段
hdel key field
例:
127.0.0.1:6379[1]> hset person name "Renzheng"
(integer) 1
127.0.0.1:6379[1]> hgetall person
1) "age"
2) "20"
3) "name"
4) "Renzheng"
127.0.0.1:6379[1]> hdel person name
(integer) 1
127.0.0.1:6379[1]> hgetall person
1) "age"
2) "20"
4.2 实践
4.2.1 存储文章数据
[图片上传失败...(image-43c2a3-1653622114110)]
4.2.2 存储文章缩略名
使用一个的 slug.to.id
hash 类型键用于存储文章缩略名和文章 ID 的对应关系。
如果需要发布文章,伪代码如下:
// 获取文章 ID
$postId = INCR posts:count
// 判断文章缩略名 slug 是否可用,如果不可用则赋值
$isSlugAvailable = HSETNX slug.to.id $slug $postId
// 缩略名存在
if $isSlugAvailable = 0
exit
HMSET post:$postId title $title content $content slug $slug
4.3 其他命令
4.3.1 只获取字段名或字段值
127.0.0.1:6379[1]> hkeys car
1) "color"
2) "name"
3) "price"
127.0.0.1:6379[1]> hvals car
1) "red"
2) "BMW"
3) "500001"
4.3.2 获得字段数量
127.0.0.1:6379[1]> hlen car
(integer) 3
5. 列表(list)类型
List 类型可以存储一个有序的字符串列表,常用的操作是向列表两端添加元素,或者获得列表的某一个片段。list 类型内部由双向链表实现,所以向列表两端添加元素的时间复杂度为 O(1),获取越接近两端的元素越快,代价是通过索引访问元素比较慢。
场景:新鲜事(插入最新,获取最新)、日志。
借助 list 类型,Redis 还可以作为队列使用。
一个 list 类型键最多容纳 2^32 - 1 个元素。
5.1 常用命令
5.1.1 向列表两端添加元素
LPUSH key value [value ...]
RPUSH key value [value ...]
LPUSH
命令用来向列表左边添加元素,返回值为添加元素后列表的长度。
例如:
127.0.0.1:6379[1]> lpush nums 1
(integer) 1
127.0.0.1:6379[1]> lpush nums 2 3
(integer) 3
按照以上命令,nums
中元素变化如下:
[]
[1]
[3, 2, 1]
5.1.2 从列表两端弹出元素
LPOP key
RPOP key
LPOP
命令可以从列表左边弹出一个元素。该命令执行两个操作:
- 将列表左边的元素从列表中移除
- 返回被移除的元素
例如:
127.0.0.1:6379[1]> lpop nums
"3"
5.1.3 获取列表中元素的个数
LLEN key
如果 key
不存在,LLEN
命令返回 0。例如:
127.0.0.1:6379[1]> llen nums
(integer) 2
127.0.0.1:6379[1]> llen foo // foo 不存在
(integer) 0
LLEN
命令的功能类似于关系型数据库中的 select count(*) from table_name
,但是 LLEN
的时间复杂度为 O(1),使用时会直接读取现成的值,并不需要遍历一遍获得数据。
5.1.4 获得列表片段
LRANGE key start stop
LRANGE
可以获得列表中的一个片段,返回索引从 start
到 stop
之间的元素(索引从 0 开始,包括 stop
元素)。
例如:
127.0.0.1:6379[1]> lrange nums 0 1
1) "2"
2) "1"
LRANGE
命令也支持负索引,表示从右边开始计算,如 -1 表示从最右边第一个元素开始,-2 表示最右边第二个元素,依此类推。
127.0.0.1:6379[1]> lrange nums -2 -1
1) "2"
2) "1"
如果 stop
大于实际的索引范围,则会返回到列表中最右边的元素。
5.1.5 删除列表中指定的值
LREM key count value
LREM
命令将删除前 count
个值为 value
的元素,返回实际删除的元素。
例如:
127.0.0.1:6379[1]> lpush nums 1 0 1 0 1 0 1 0 1 0
(integer) 10
127.0.0.1:6379[1]> lrange nums 0 -1
1) "0"
2) "1"
3) "0"
4) "1"
5) "0"
6) "1"
7) "0"
8) "1"
9) "0"
10) "1"
127.0.0.1:6379[1]> lrem nums 3 1
(integer) 3
127.0.0.1:6379[1]> lrange nums 0 -1
1) "0"
2) "0"
3) "0"
4) "0"
5) "1"
6) "0"
7) "1"
根据 count
值的不同,LREM
命令的执行方式会略有差异:
count > 0
时,LREM
命令会从左边删除前count
个值为value
的元素;count < 0
时,LREM
命令会删除从右边开始删除前|count|
个值为value
的元素;count = 0
时,LREM
命令将删除所有值为value
的元素。
5.2 实践
5.2.1 存储文章 ID 列表
使用键 posts:list
记录文章 ID 列表。当发布新文章时,使用 LPUSH
命令把文章的 ID 加入至这个列表中,删除文章时将列表中的文章 ID 删除。可以使用 LRANGE
命令实现文章分页列表,伪代码如下:
$postPerPage = 10
$start = ($currentPage - 1) * $postsPerPage
$end = $currentPage * $postsPerPage - 1
$postIds = LRANGE posts:list $start $end
# 循环获取文章信息
for $id in $postIds
print HGET post:$id title
5.2.2 存储文章评论
将文章评论序列化之后,使用字符串的形式将评论存入形如 posts:id:comments
的列表中。
伪代码如下:
$serializedComment = serialize($author, $email, $time, $content)
LPUSH post:1:comments $serializedComment
读取时,依然使用 LRANGE
命令。
5.3 其他命令
5.3.1 获得/设置指定索引的元素值
LINDEX key index
LSET KEY index value
LINDEX
用来返回指定索引的元素,索引从 0 开始。
例如:
127.0.0.1:6379[1]> lrange nums 0 -1
1) "0"
2) "9"
3) "8"
4) "7"
5) "6"
6) "5"
7) "4"
8) "3"
9) "2"
10) "1"
127.0.0.1:6379[1]> lindex nums 0
"0"
127.0.0.1:6379[1]> lindex nums 2
"8"
LSET
命令将索引为 index
的元素设置为 value
,例如:
127.0.0.1:6379[1]> lset nums 0 99999
OK
127.0.0.1:6379[1]> lrange nums 0 -1
1) "99999"
2) "9"
3) "8"
4) "7"
5) "6"
6) "5"
7) "4"
8) "3"
9) "2"
10) "1"
5.3.2 只保留列表指定片段
LTRIM key start end
LTRIM
命令可以删除指定索引范围之外的所有元素,其指定的列表范围的方法和 LRANGE
命令相同。
例如:
127.0.0.1:6379[1]> lrange nums 0 -1
1) "99999"
2) "9"
3) "8"
4) "7"
5) "6"
6) "5"
7) "4"
8) "3"
9) "2"
10) "1"
127.0.0.1:6379[1]> ltrim nums 1 -1
OK
127.0.0.1:6379[1]> lrange nums 0 -1
1) "9"
2) "8"
3) "7"
4) "6"
5) "5"
6) "4"
7) "3"
8) "2"
9) "1"
5.3.3 向列表中插入元素
LINSERT key BEFORE|AFTER pivot value
LINSERT
命令在列表中从左到右查找值为 pivot
的元素,然后根据第二个参数是 BEFORE
还是 AFTER
决定将 value
插入到该元素的前面还是后面。LINSERT
命令的返回值为插入后列表元素的个数。
例如:
127.0.0.1:6379[1]> lrange nums 0 -1
1) "1"
2) "9"
3) "8"
4) "7"
5) "6"
6) "5"
7) "4"
8) "3"
9) "2"
10) "1"
127.0.0.1:6379[1]> linsert nums before 1 0
(integer) 11
127.0.0.1:6379[1]> lrange nums 0 -1
1) "0"
2) "1"
3) "9"
4) "8"
5) "7"
6) "6"
7) "5"
8) "4"
9) "3"
10) "2"
11) "1"
5.3.4 将元素从一个列表转移至另一个列表
RPOPLPUSH src des
RPOPLPUSH
命令会先从 src
列表的右边弹出一个元素,然后将其加入至 des
列表的左边,并返回这个元素的值。整个过程是原子的。
6. 集合(set)类型
在集合中每个元素都是不同的,而且没有顺序。一个 set 类型的键可以至多存储 2^32 - 1 个字符串。
[图片上传失败...(image-e0c4ba-1653622114110)]
集合类型在 Redis 内部是使用值为空的 Hash Table 实现的。
6.1 常用命令
6.1.1 增加/删除元素
SADD key member [member ...]
SREM key [member] [member ...]
SADD
命令用于向集合中添加一个元素或多个元素,如果键不存在则自动创建,元素已存在则忽略。返回值为成功加入元素的数量。
例如:
127.0.0.1:6379[1]> sadd foo a
(integer) 1
127.0.0.1:6379[1]> sadd foo a b c
(integer) 2
SREM
命令用于从集合中删除一个或者多个元素,返回成功删除的个数。
例如:
127.0.0.1:6379[1]> srem foo a d
(integer) 1
6.1.2 获得集合中所有元素
SMEMBERS key
SMEMBERS
命令从集合中返回所有元素。例如:
127.0.0.1:6379[1]> del foo
(integer) 1
127.0.0.1:6379[1]> sadd foo a b c
(integer) 3
127.0.0.1:6379[1]> smembers foo
1) "c"
2) "b"
3) "a"
6.1.3 判断元素是否存在于集合中
SISMEMBER key member
时间复杂度为 O(1),SISMEMBER
当值存在时返回 1,当值不存在或者键不存在时返回 0。例如:
127.0.0.1:6379[1]> sismember foo a
(integer) 1
127.0.0.1:6379[1]> sismember foo d
(integer) 0
6.1.4 集合运算
SDIFF key [key ...]
SINTER key [key ...]
SUNION key [key ...]
-
SDIFF
用来对集合之间执行差集运算。127.0.0.1:6379[1]> sadd aset a b c (integer) 3 127.0.0.1:6379[1]> sadd bset b c d (integer) 3 127.0.0.1:6379[1]> sdiff aset bset 1) "a" 127.0.0.1:6379[1]> smembers aset 1) "c" 2) "b" 3) "a"
-
SINTER
用来对多个集合执行交集运算。127.0.0.1:6379[1]> sinter aset bset 1) "c" 2) "b"
-
SUNION
用来对多个集合执行并集运算。127.0.0.1:6379[1]> sunion aset bset 1) "c" 2) "b" 3) "d" 4) "a"
6.2 实践
6.2.1 存储文章标签
一篇文章的各个标签均是不同的,而且展示时对这些标签的顺序没有要求,可以使用 set 类型键存储文章标签。对每篇文章使用形如 posts:id:tags
的键存储该篇文章的标签。
伪代码如下:
SADD post:1:tags Java Spring MyBatis
SREM post:1:tags MyBatis
// 显示所有标签
$tags = SMEMBERS post:1:tags
6.2.2 通过标签查询文章
使用形如 tag:标签:posts
的 set 类型键存储每个标签对应标签。
6.3 其他命令
6.3.1 获取集合中元素的个数
SCARD key
SCARD
命令用于获取集合中元素的个数,例如:
127.0.0.1:6379[1]> scard aset
(integer) 3
6.3.2 进行集合运算并将结果存储
SDIFFSTORE des key [key ...]
SINTERSTORE des key [key ...]
SUNIONSTORE des key [key ...]
不直接返回运算结果,而将结果存储在 des 键中。
127.0.0.1:6379[1]> sdiffstore cset aset bset
(integer) 1
127.0.0.1:6379[1]> smembers cset
1) "a"
6.3.3 随机获取集合中的元素
SRANDMEMBER key [count]
SRANDMEMBER
命令用于随机从集合中获取一个元素,例如:
127.0.0.1:6379[1]> srandmember aset
"b"
也可以传递一个 count
参数一次获得多个元素,而根据 count
参数的正负不同返回结果略有差异:
- 当
count
为正数时,SRANDMEMBER
命令将从集合中随机获得count
个不重复的元素; - 当
count
为负数时,SRANDMEMBER
命令将从集合中随机获得可能相同的|count|
个元素。
6.3.4 从集合中弹出一个元素
SPOP key
由于集合是无序的,因此 SPOP
命令会从集合中随机选择一个元素弹出。例如:
127.0.0.1:6379[1]> spop aset
"a"
127.0.0.1:6379[1]> smembers aset
1) "c"
2) "b"
7. 有序集合
有序集合(sorted set) 类型在 set 类型的基础上为集合中的每个元素都关联了一个分数,这使得我们不仅可以完成插入、删除、判断是否存在等 set 类型支持的操作,还能进行获得分数最高(最低)的前 N 个元素、获得指定分数范围内的元素等与分数相关的操作。
虽然集合中每个元素都不相同,但是分数可以相同。
7.1 命令
7.1.1 增加元素
ZADD key score member [score member]
ZADD
命令用于向 sorted set 中添加一个或多个元素及他们的分数,如果该元素已经存在,那么则会用新的分数替代旧的分数。ZADD
命令的返回值为新加入集合中的元素个数。例如:
127.0.0.1:6379[1]> zadd scoreboard 98 Tom 87 Mike 94 Mary
(integer) 3
127.0.0.1:6379[1]> zadd scoreboard 86.5 Mike
(integer) 0
127.0.0.1:6379[1]> zadd scoreboard +inf Mike // 设置分数为正无穷
(integer) 0
127.0.0.1:6379[1]> zadd scoreboard -inf Mike // 设置分数为负无穷
(integer) 0
7.1.2 获得元素的分数
ZSCORE key member
例如:
127.0.0.1:6379[1]> zscore scoreboard Mike
"86.5"
7.1.3 获得在某个排名范围内的元素列表
ZRANGE key start stop [withscores]
ZREVRANGE key start stop [withscores]
ZRANGE
命令会按照元素的分数从小到大排序返回索引从 start
到 stop
之间的所有元素(包括两端),索引方式与 LRANGE
命令相同。ZREVRANGE
命令按照分数从大到小排序。
127.0.0.1:6379[1]> zrange scoreboard 0 2
1) "Mike"
2) "Mary"
3) "Tom"
127.0.0.1:6379[1]> zrange scoreboard 0 2 withscores
1) "Mike"
2) "86.5"
3) "Mary"
4) "94"
5) "Tom"
6) "98"
127.0.0.1:6379[1]> zrevrange scoreboard 0 2 withscores
1) "Tom"
2) "98"
3) "Mary"
4) "94"
5) "Mike"
6) "86.5"
如果两个元素的分数相同,则按照字典顺序排序。
7.1.4 获取指定分数范围内的元素
ZRANGEBYSCORE key min max [withscore] [limit offset count]
ZRANGEBYSCORE
命令按照元素分数从小到大的顺序返回分数在 min
和 max
之间的元素,例如:
127.0.0.1:6379[1]> zrangebyscore scoreboard 80 90
1) "Mike"
如果希望分数不包括端点值,则可以在分数前加上 (
,例如:
127.0.0.1:6379[1]> zrangebyscore scoreboard 80 86.5
(empty list or set)
min
和 max
还支持无穷大,类似于 ZADD
命令,-inf
和 +inf
分别表示负无穷和正无穷。例如:
127.0.0.1:6379[1]> zrangebyscore scoreboard (80 +inf withscores
1) "Mike"
2) "88.5"
3) "Mary"
4) "94"
5) "Tom"
6) "98"
limit offset count
表示在获得列表的基础上,向后偏移 offset
个元素,并只获取前 count
个元素。例如:
// 获取高于 60 分并从第 2 个人开始的 3 个人
127.0.0.1:6379[1]> zrangebyscore scoreboard (60 +inf withscores limit 1 3
1) "Mary"
2) "94"
3) "Tom"
4) "98"
ZREVRANGEBYSCORE
命令命令不仅按照元素分数从大到小排序,而且该命令的 min
和 max
参数顺序和 ZRANGEBYSCORE
命令是相反的。
7.1.5 增加某个元素的分数
ZINCRBY key increment member
ZINCRBY
命令可以增加某个元素的分数,返回值为更改之后的分数。例如:
127.0.0.1:6379[1]> zincrby scoreboard 2 Mike
"88.5"
127.0.0.1:6379[1]> zrange scoreboard 0 -1 withscores
1) "Mike"
2) "88.5"
3) "Mary"
4) "94"
5) "Tom"
6) "98"
7.2 实践
7.2.1 实现文章按照访问量排序
使用键名 posts:page.view
的键记录每篇文章的 ID 和访问量,每次访客访问一篇文章,则通过 ZINCRBY posts:page.view 1 postId
更新访问量。伪代码如下:
$postsPerpage = 10
$start = $(currentPage - 1) * $postsPerPage
$end = $currentPage * $postsPerPage - 1;
$postIds = ZREVRANGE posts:page.view $start $end
foreach $id in $postIds
$title = HGET post:$id title
7.2.2 改进按照时间排序
同样采用有序集合,记录文章 ID 和 Unix 时间
7.3 其他命令
7.3.1 获得集合中元素的数量
ZCARD key
例如:
127.0.0.1:6379[1]> zcard scoreboard
(integer) 3
7.3.2 获得指定分数范围内元素个数
ZCOUNT key min max
例如:
127.0.0.1:6379[1]> zcount scoreboard 80 90
(integer) 1
7.3.3 删除一个或多个元素
ZREM key member
ZREM
返回值是成功删除元素的数量
127.0.0.1:6379[1]> zrem scoreboard Mike
(integer) 1
127.0.0.1:6379[1]> zrange scoreboard 0 -1
(empty list or set)
7.3.4 按照排名范围删除元素
ZREMRANGEBYRANK key start stop
ZREMRANGEBYRANK
命令按照元素从小(最小为 0)到大排序删除排名在指定范围内的所有元素,并返回删除元素的数量。例如:
127.0.0.1:6379[1]> zremrangebyrank scoreboard 1 3
(integer) 2
127.0.0.1:6379[1]> zrange scoreboard 0 -1
1) "Mike"
7.3.5 按照分数范围删除元素
ZREMRANGEBYSCORE key min max
ZREMRANGEBYSOCRE
会删除指定分数范围内所有的元素,参数 min
和 max
的特性和 ZRANGEBYSCORE
命令中的一样。返回值是删除元素的数量。
7.3.6 获得元素的排名
ZRANK key member
ZREVRANK key member
ZRANK
命令会按照元素分数从小到大的顺序获得指定的元素排名,从0 开始。而 ZREVRANK
命令则相反,分数最大的元素排名为 0。
7.3.6 计算有序集合的交集
ZINTERSTORE des numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
ZINTERSTORE
命令用来计算多个有序集合的交集,并将结果存储在 des
键中(同样以有序集合类型存储),返回值为 des
键中的元素个数。
des
键中元素的分数由 AGGREGATE
参数决定:
- 当
AGGREGATE
参数是SUM
(默认)时,des
键中的元素分数是每个参与计算集合中该元素分数的和; - 当
AGGREGATE
参数是MIN
(默认)时,des
键中的元素分数是每个参与计算集合中该元素分数的最小值; - 当
AGGREGATE
参数是MAX (默认)时,
des` 键中的元素分数是每个参与计算集合中该元素分数的最大值;
ZINTERSTORE
命令还能通过 WEIGHTS
参数设置每个集合的权重,每个集合在参与计算时元素的分数会被乘上该集合的权重。
另外还有一个命令 ZUNIONSTORE
计算集合并集,用法与 ZINTERSTORE
命令相同。