Redis的SORT命令可以对列表键、集合键或者有序集合键的值进行排序。

21.1 SORT <key>命令的实现

SORT <key> 可以对一个包含数字值的键key进行排序,假设:

PRUSH numbers 3 1 2

SORT numbers

  1. 创建一个和numbers长度相同的数组,每个元素都是一个redis.h/redisSortObject结构。

  2. 遍历数组,将每个元素的obj指针指向numbers列表的各个项,构成一一对应关系。

  3. 遍历数组,将各个obj指针所指向的列表项转换为一个double类型的浮点数,并将这个浮点数保存在相应数组项的u.score属性中。

  4. 根据数组项u.score的值,对数组进行数字值排序。

  5. 遍历数组,将各个数组项的obj指针所指向的列表项作为排序结果返回给客户端。

1
2
3
4
5
6
7
8
9
10
11
12
13
typedef struct _redisSortObject {
// 被排序的值
robj *obj;

// 权重
union {
// 排序数字值时使用
double score;

// 排序带有BY选项的字符串值使用
robj *cmpobj;
} u;
} redisSortObject;

21.2 ALPHA选项的实现

SORT ALPHA

可以对包含字符串值的键进行排序,例如:

SADD fruits apple banana cherry

SORT fruits ALPHA

  1. 创建一个redisSortObject数组,长度等于fruits集合。
  2. 遍历数组,将各个元素的obj指针指向fruits集合的各个元素。
  3. 根据obj指针所指向的集合元素,对数组进行字符串排序。
  4. 遍历数组,一次将数组项的obj指针指向的元素返回给客户端。

21.3 ASCDESC选项的实现

SORT默认是升序排序,所以SORT <key>SORT <key> ASC是等价的。DESC可以降序排序。

升序和降序都是使用快速排序完成的。

21.4 BY选项的实现

默认情况下,SORT命令使用被排序键包含的元素作为排序的权重,元素本身决定了元素排序后的位置。

通过BY选项,SORT可以指定某些字符串键或某个哈希键所包含的某些域(field)作为元素的权重。

不同的是,排序用到的redisSortObject数组元素指向权重键。

21.5 带有ALPHABY选项的实现

BY选项默认权重键保存的是数字值,针对字符串值还是要配合ALPHA选型。

21.6 LIMIT选项的实现

默认情况下,SORT返回排序后的所有元素。LIMIT选项可以只返回一部分已排序的元素:

SORT ALPHA LIMIT

其中:

  • offset表示要跳过的已排序元素数量。
  • count表示跳过给定数量的已排序元素后,要返回的元素数量。

LIMIT生效,还是要排序伸个数组,最后返回元素的时候,根据offsetcount的索引。

21.7 GET选项的实现

默认情况下,SORT排序之后,总是返回被排序键所包含的元素。GET可以返回指定模式的键的值。

21.8 STORE选项的实现

默认情况下,SORT只向客户端返回结果,要保存结果,使用SORTE选项。

21.9 多个选项的执行顺序

如果按照选项来划分,SORT命令可以分为四步:

  1. 排序:使用ALPHAASCDESCBY选项。
  2. 限制结果集的长度:使用LIMIT选项。
  3. 获取外部键:使用GET选项。
  4. 保存结果集:使用STORE选项。
  5. 先客户端返回结果集。

调用SORT命令时,除了GET选项之外,改变选项的位置不会影响SORT的顺序。

导航

目录

上一章:20. Lua脚本

下一章:22. 二进制位数组