系列导航

  1. 如何在 Ubuntu 18.04 上安装和保护 Redis
  2. 如何连接到 Redis 数据库
  3. 如何管理 Redis 数据库和 Keys
  4. 如何在 Redis 中管理副本和客户端
  5. 如何在 Redis 中管理字符串
  6. 如何在 Redis 中管理 List
  7. 如何在 Redis 中管理 Hashes
  8. 如何在 Redis 中管理 Sets
  9. 如何在 Redis 中管理 Sorted Sets
  10. 如何在 Redis 中运行事务
  11. 如何使 Redis 中的 Key 失效
  12. 如何解决 Redis 中的故障
  13. 如何从命令行更改 Redis 的配置
  14. Redis 数据类型简介

介绍

Redis 是一个开源的内存中键值数据存储。在 Redis 中,有序集合(Sorted Sets)类似于 集合(Sets)数据类型,两者都是字符串的非重复集合。不同之处在于,有序集合中的每个成员都关联一个分值(score),从而支持按分值从低到高排序。与集合一样,有序集合中的每个成员必须是唯一的,尽管多个成员可以共享相同的分值。

本教程说明了如何创建有序集合、检索和删除其成员,以及如何从现有集合创建新的有序集合。

如何使用本指南

本指南以备有完整示例的备忘单形式编写。我们鼓励您跳至与您要完成的任务相关的任何部分。

本指南中显示的命令已在运行 Redis 版本 4.0.9 的 Ubuntu 18.04 服务器上进行了测试。要设置类似的环境,您可以按照我们的指南 如何在 Ubuntu 18.04 上安装和保护 Redis步骤 1 进行操作。我们将通过使用 Redis 命令行界面(redis-cli)运行它们来演示这些命令的行为。请注意,如果您使用其他 Redis 界面(例如 Redli),则某些命令的确切输出可能会有所不同。

另外,您可以提供一个托管的 Redis 数据库实例来测试这些命令,但是请注意,根据数据库提供者所允许的控制级别,本指南中的某些命令可能无法按所述方式工作。要配置 DigitalOcean 托管数据库,请遵循我们的 托管数据库产品文档。然后,您必须 安装 Redli 设置 TLS 隧道 才能通过 TLS 连接到托管数据库。

创建有序集合并添加成员

要创建有序集合,请使用 zadd 命令。zadd 接受将保留有序集合的键的名称作为参数,后跟要添加的成员的分值以及成员本身的值。以下命令将创建一个名为 faveGuitarists 的有序集合键,包含一个成员 "Joe Pass",分值为 1

zadd faveGuitarists 1 "Joe Pass"

zadd 将返回一个整数,该整数指示成功创建有序集合后将添加到集合中的成员数。

(integer) 1

您可以使用 zadd 将多个成员添加到有序集合中。请注意,它们的分值不必是连续的,分值之间可以有间隔,并且同一有序集合中的多个成员可以共享同一分值:

zadd faveGuitarists 4 "Stephen Malkmus" 2 "Rosetta Tharpe" 3 "Bola Sete" 3 "Doug Martsch" 8 "Elizabeth Cotten" 12 "Nancy Wilson" 4 "Memphis Minnie" 12 "Michael Houser"
(integer) 8

zadd 可以接受以下选项,您必须在键名称之后和第一个成员分值之前输入以下选项:

  • NXXX:这些选项具有相反的效果,因此您在任何 zadd 操作中都只能包括其中之一:

    • NX:告诉 zadd 更新现有成员。使用此选项,zadd 将仅添加新元素。
    • XX:告诉 zadd 更新现有的元素。使用此选项,zadd 将永远不会添加新成员。
  • CH:通常,zadd 仅返回添加到有序集合中的新元素的数量。但是,如果 zadd 包含此选项,将返回已_更改_元素的数量。这包括新添加的成员和分值已更改的成员。
  • INCR:这会使命令增加成员的分值。如果该成员还不存在,则该命令会将其添加到有序集合中,并将增量作为分值,就像其原始分值是 0 一样。如果包含 INCR,成功 zadd 将返回成员的新分值。请注意,使用此选项时,一次只能包含一个分值/成员对。

无需将 INCR 选项传递给 zadd,您可以使用 zincrby 命令,行为完全相同。zincrby 不是给有序集合成员像分数那样由分值指示的值,而是使该成员的分值增加该值。例如,下面的命令增量成员 "Stephen Malkmus" 的分值,这本来是 4,增长 59

zincrby faveGuitarists 5 "Stephen Malkmus"
"9"

zadd 命令 INCR 选项一样,如果指定的成员不存在,则 zincrby 将使用增量值作为其分值来创建它。

检索有序集合中的成员

检索有序集合中的成员的最基本方法是使用 zrange 命令。此命令接受要检索其成员的键的名称以及其中包含的成员范围作为参数。范围由两个数字定义,这些数字表示 从零开始的 索引,0 表示代表有序集合中的第一个成员(或分值最低的成员),1 代表下一个,依此类推。

下面的示例将返回 faveGuitarists 上一部分中创建的有序集合中的前四个成员:

zrange faveGuitarists 0 3
1) "Joe Pass"
2) "Rosetta Tharpe"
3) "Bola Sete"
4) "Doug Martsch"

请注意,如果传递给 zrange 的有序集合具有两个或多个共享相同分值的元素,它将按照_字典序_(lexicographical order)或字母顺序对这些元素进行排序。

开始索引和停止索引也可以是负数,-1 代表最后一个成员,-2 代表倒数第二个,依此类推:

zrange faveGuitarists -5 -2
1) "Memphis Minnie"
2) "Elizabeth Cotten"
3) "Stephen Malkmus"
4) "Michael Houser"

zrange 可以接受 WITHSCORES 参数,当包含该参数时,该参数还将返回成员的分值:

zrange faveGuitarists 5 6 WITHSCORES
1) "Elizabeth Cotten"
2) "8"
3) "Stephen Malkmus"
4) "9"

zrange 只能以数字升序返回一系列成员。要反转它并以降序返回范围,必须使用 zrevrange 命令。可以将此命令视为暂时反转给定有序集合的顺序,然后返回属于指定范围内的成员。因此,使用 zrevrange0 将代表键中持有的最后一个成员,1 将代表倒数第二个,等等:

zrevrange faveGuitarists 0 5
1) "Nancy Wilson"
2) "Michael Houser"
3) "Stephen Malkmus"
4) "Elizabeth Cotten"
5) "Memphis Minnie"
6) "Doug Martsch"

zrevrange 也可以接受 WITHSCORES 选项。

您可以使用 zrangebyscore 命令根据其分值返回一系列成员。在下面的示例中,该命令将返回 faveGuitarists 键中分值为 2、3 或 4 的任何成员:

zrangebyscore faveGuitarists 2 4
1) "Rosetta Tharpe"
2) "Bola Sete"
3) "Doug Martsch"
4) "Memphis Minnie"

在此示例中,范围是包含范围的,这意味着它将返回分值为 2 或 4 的成员。您可以在范围的任一末端加上一个开放的括号((),以排除该范围的任何一端。以下示例将返回分值大于或等于 2,但小于 4 的每个成员:

zrangebyscore faveGuitarists 2 (4
1) "Rosetta Tharpe"
2) "Bola Sete"
3) "Doug Martsch"

zrange 一样,zrangebyscore 可以接受 WITHSCORES 参数。它还接受 LIMIT 选项,您可以使用该选项仅从 zrangebyscore 输出中检索元素的选择。此选项接受一个 offset(偏移量)) 和一个 count(计数),该 偏移量) 标记该命令将返回的范围内的第一个成员,该计数总共定义该命令将返回的成员数。例如,以下命令将查看 faveGuitarists 有序集合的前六个成员,但仅从该集合中返回 3 个成员,从该范围内的第二个成员开始,由 1 表示:

zrangebyscore faveGuitarists 0 5 LIMIT 1 3
1) "Rosetta Tharpe"
2) "Bola Sete"
3) "Doug Martsch"

zrevrangebyscore 命令根据成员的分值返回相反的范围。以下命令将返回分值在 10 到 6 之间的集合中的每个成员:

zrevrangebyscore faveGuitarists 10 6
1) "Stephen Malkmus"
2) "Elizabeth Cotten"

zrangebyscore 一样,zrevrangebyscore 可以接受 WITHSCORESLIMIT 选项。此外,您可以在范围的两端加上开放括号来排除该范围的任何一端。

有时,有序集合中的所有成员都具有相同的分值。在这种情况下,您可以使用 zrangebylex 命令强制 Redis 返回按_字典序_或字母顺序排序的元素范围。要尝试此命令,请运行以下 zadd 命令以创建一个有序集合,其中每个成员具有相同的分值:

zadd SomervilleSquares 0 Davis 0 Inman 0 Union 0 porter 0 magoun 0 ball 0 assembly

zrangebylex 后面必须跟一个键的名称,一个开始间隔和一个停止间隔。开始和停止间隔必须以圆括号(()或方括号([)开头,如下所示:

zrangebylex SomervilleSquares [a [z
1) "assembly"
2) "ball"
3) "magoun"
4) "porter"

请注意,即使该命令查找的范围是从 az,该示例也仅返回集合中八个成员中的四个。这是因为 Redis 值区分大小写,因此以大写字母开头的成员将从其输出中排除。要返回这些值,可以运行以下命令:

zrangebylex SomervilleSquares [A [z
1) "Davis"
2) "Inman"
3) "Union"
4) "assembly"
5) "ball"
6) "magoun"
7) "porter"

zrangebylex 还接受特殊字符 -,它们代表负无穷大,而 + 代表正无穷大。因此,以下命令语法还将返回有序集合中的每个成员:

zrangebylex SomervilleSquares - +

请注意,zrangebylex 不能以相反的字典顺序(字母升序)返回有序集合成员。为此,请使用 zrevrangebylex

zrevrangebylex SomervilleSquares + -
1) "porter"
2) "magoun"
3) "ball"
4) "assembly"
5) "Union"
6) "Inman"
7) "Davis"

因为它适用于每个成员都具有相同分值的有序集合,zrangebylex 接受 WITHSCORES 选项。但是,它确实接受 LIMIT 选项。

获取有序集合的信息

要查找给定有序集合中有多少个成员(或者换句话说,确定其 基数),请使用 zcard 命令。以下示例显示了 faveGuitarists 本指南第一部分中键中拥有多少成员:

zcard faveGuitarists
(integer) 9

zcount 可以告诉您在给定的有序集合中有多少个元素落在分值范围内。键后面的第一个数字是范围的开始,第二个数字是范围的结束:

zcount faveGuitarists 3 8
(integer) 4

zscore 输出有序集合中指定成员的分值:

zscore faveGuitarists "Bola Sete"
"3"

如果指定的成员或键都不存在,zscore 将返回 (nil)

zrankzscore 相似,但不返回给定成员的分值,而是返回其排名。在 Redis 中,_排名_ 是有序集合成员的从零开始的索引,按其分值排序。例如,"Joe Pass" 分值为 1,但是由于这是键中所有成员的最低分值,因此其排名为 0

zrank faveGuitarists "Joe Pass"
(integer) 0

调用了另一个 Redis 命令 zrevrank,该命令执行与 zrank 相同的功能,但取而代之的是反转集合中成员的排名。在以下示例中,该成员 "Joe Pass" 的分值最低,因此其反向排名最高:

zrevrank faveGuitarists "Joe Pass"
(integer) 8

成员的分值与其排名之间的唯一关系是其分值相对于其他成员的分值所处的位置。如果两个连续成员之间存在分值差距,则该分值差距不会反映在他们的排名中。请注意,如果两个成员的分值相同,则按字母顺序排在第一位的成员将具有较低的排名。

类似于 zscore,如果键或成员不存在,zrankzrevrank 将返回 (nil)

zlexcount 可以告诉您在词典范围之间的有序集合中有多少个成员。下面的示例使用上一节中的 SomervilleSquares 有序集合:

zlexcount SomervilleSquares [M [t
(integer) 5

该命令的语法与 zrangebylex 命令相同,因此,请参见 上一节 以获取有关如何定义字符串范围的详细信息。

从有序集合中删除成员

zrem 命令可以从有序集合中删除一个或多个成员:

zrem faveGuitarists "Doug Martsch" "Bola Sete"

zrem 将返回一个整数,指示从有序集合中删除了多少个成员:

(integer) 2

有三个 Redis 命令,可让您根据范围删除有序集合中的成员。例如,如果有序集合中的每个成员都具有相同的分值,则可以使用 zremrangebylex 来根据词典范围删除成员。此命令使用与 zrangebylex 相同的语法。以下示例将从上一节中创建的 SomervilleSquares 键中删除所有以大写字母开头的成员:

zremrangebylex SomervilleSquares [A [Z

zremrangebylex 将输出一个整数,指示已删除的成员数:

(integer) 3

您还可以使用 zremrangebyscore 命令,使用与 zrangebyscore 命令相同的语法,根据分值范围删除成员。以下示例将删除 faveGuitarists 分值为 4、5 或 6 的每个成员:

zremrangebyscore faveGuitarists 4 6
(integer) 1

您可以从基于一系列与队伍的一组删除成员 zremrangebyrank 的命令,它使用相同的语法 zrangebyrank。以下命令将删除排名最低的有序集合中的三个成员,这些成员由一系列从零开始的索引定义:

zremrangebyrank faveGuitarists 0 2
(integer) 3

请注意,传递给 zremrangebyrank 的数字也可以为负,-1 代表最高排名,-2 代表次高排名,依此类推。

从现有集合创建新的有序集合

Redis 包含两个命令,它们允许您比较多个有序集合的成员并基于这些比较创建新的:zinterstorezunionstore。要试验这些命令,请运行以下 zadd 命令以创建一些示例有序集合:

zadd NewKids 1 "Jonathan" 2 "Jordan" 3 "Joey" 4 "Donnie" 5 "Danny"
zadd Nsync 1 "Justin" 2 "Chris" 3 "Joey" 4 "Lance" 5 "JC"

zinterstore 查找两个或多个有序集合(它们的交集)共享的成员,并生成仅包含那些成员的新有序集合。此命令必须依次包括相交成员将以有序集合存储的目标键的名称,要传递给 zinterstore 的键的数量以及要分析的键的名称:

zinterstore BoyBands 2 NewKids Nsync

zinterstore 将返回一个整数,该整数显示存储到目标有序集合中的元素数。因为 NewKidsNsync 仅共享一个成员 "Joey",所以该命令将返回 1

(integer) 1

请注意,如果目标键已经存在,zinterstore 将覆盖其内容。

zunionstore 将创建一个新的有序集合,其中包含传递给它的每个键成员。此命令使用与 zinterstore 相同的语法,并且需要目标键的名称,传递给该命令的键的数量以及键的名称:

zunionstore SuperGroup 2 NewKids Nsync

zinterstore 一样,zunionstore 将返回一个整数,显示存储在目标键中的元素数。即使两个原始有序集合都包含五个成员,但由于有序集合不能包含重复成员,并且每个键都有一个名为 "Joey" 的成员,因此所得的整数将为 9

(integer) 9

zinterstore 一样,如果目标键已经存在,zunionstore 将覆盖目标键的内容。

为了在使用 zinterstorezunionstore 创建新的有序集合时更好地控制成员分值,这两个命令都接受 WEIGHTSAGGREGATE 选项。

对于 WEIGHTS 该命令中包含的每个有序集合,此选项后均带有一个数字,该数字_加权_或乘以每个成员的分值。WEIGHTS 选项后的第一个数字对传递给命令的第一个键的分值加权,第二个数字对第二个键的加权加权,依此类推。

以下示例创建一个新的有序集合,其中包含来自 NewKidsNsync 有序集合的相交键。它将 NewKids 键中的分值加权三倍,并将 Nsync 键中的分值加权七倍:

zinterstore BoyBandsWeighted 2 NewKids Nsync WEIGHTS 3 7

如果 WEIGHTS 选项未包括在内,权重默认为 1(对于 zinterstorezunionstore 均如此)。

AGGREGATE 接受三个子选项。其中的第一个,SUM,通过添加组合集中匹配成员的分值来实现 zinterstorezunionstore 的默认行为。

如果在共享一个成员的两个有序集合上运行 zinterstorezunionstore 运算,但是该成员在每个集合中具有不同的分值,则可以使用 MIN 子选项强制操作在新集合中分配两个分值中的较低者:

zinterstore BoyBandsWeightedMin 2 NewKids Nsync WEIGHTS 3 7 AGGREGATE MIN

由于这两个有序集合只有一个具有相同分值(3)的匹配成员,因此此命令将创建一个新集合,其成员具有两个加权分值中的较低者:

zscore BoyBandsWeightedMin "Joey"
"9"

同样,AGGREGATE 可以使用 MAX 选项强制 zinterstorezunionstore 分配两个分值中的较高者:

zinterstore BoyBandsWeightedMax 2 NewKids Nsync WEIGHTS 3 7 AGGREGATE MAX

此命令创建一个新集合,其中有一个成员 "Joey" 具有两个加权分值中的较高者:

zscore BoyBandsWeightedMax "Joey"
"21"

WEIGHTS 视为在分析成员之前临时操纵其分值的一种方式可能会有所帮助。同样,将 AGGREGATE 选项视为在将成员添加到新集中之前决定如何控制其分值的一种方式也很有帮助。

总结

本指南详细介绍了用于在 Redis 中创建和管理有序集合的许多命令。如果您想在本指南中概述其他相关的命令、参数或过程,请在下面的评论中提出疑问或提出建议。

有关 Redis 命令的更多信息,请参阅关于 如何管理 Redis 数据库的 系列教程。

说明:本教程基于 Redis 4.0.9 版本编写(测试环境为 Ubuntu 18.04)。虽然大部分命令在更新的 Redis 版本中仍然兼容,但部分行为或默认参数可能有所调整。建议在生产环境中参考官方最新文档以确认命令的适用性。