第 21 章: 排序¶
SORT <key> 命令的实现¶
Redis 服务器在执行 SORT number
时创建的数据结构。
![digraph {
rankdir = LR;
node [shape = record];
subgraph cluster_array {
style = invis;
array [label = " array | { <array0> array[0] \n redisSortObject | { <obj0> obj | u } } | { <array1> array[1] \n redisSortObject | { <obj1> obj | u } } | { <array2> array[2] \n redisSortObject | { <obj2> obj | u } } "];
}
label = "\n 图 21-1 命令为排序 numbers 列表而创建的数组";
}](_images/graphviz-eb7554ec6b27a6f790d2c9dd7438194c65b49865.png)
![digraph {
rankdir = LR;
node [shape = record];
subgraph cluster_numbers {
label = "numbers 链表"
style = dashed;
one [label = "StringObject \n \"1\""];
two [label = "StringObject \n \"2\""];
three [label = "StringObject \n \"3\""];
three -> one -> two;
}
subgraph cluster_array {
style = invis;
array [label = " array | { <array0> array[0] \n redisSortObject | { <obj0> obj | u } } | { <array1> array[1] \n redisSortObject | { <obj1> obj | u } } | { <array2> array[2] \n redisSortObject | { <obj2> obj | u } } "];
}
array:obj0 -> three;
array:obj1 -> one;
array:obj2 -> two;
label = "\n 图 21-2 将 obj 指针指向列表的各个项";
}](_images/graphviz-3f9cf78a6ec6a24ea581ee0d46ef5757daf26d4b.png)
![digraph {
rankdir = LR;
node [shape = record];
subgraph cluster_numbers {
label = "numbers 链表"
style = dashed;
one [label = "StringObject \n \"1\""];
two [label = "StringObject \n \"2\""];
three [label = "StringObject \n \"3\""];
three -> one -> two;
}
subgraph cluster_array {
style = invis;
array [label = " array | { <array0> array[0] \n redisSortObject | { <obj0> obj | u.score \n 3.0 } } | { <array1> array[1] \n redisSortObject | { <obj1> obj | u.score \n 1.0 } } | { <array2> array[2] \n redisSortObject | { <obj2> obj | u.score \n 2.0 } } "];
}
array:obj0 -> three;
array:obj1 -> one;
array:obj2 -> two;
label = "\n 图 21-3 设置数组项的 u.score 属性";
}](_images/graphviz-c694e0bad7d9035a88df761d3d779ad1f38372f1.png)
![digraph {
rankdir = LR;
node [shape = record];
subgraph cluster_numbers {
label = "numbers 链表"
style = dashed;
one [label = "StringObject \n \"1\""];
two [label = "StringObject \n \"2\""];
three [label = "StringObject \n \"3\""];
three -> one -> two;
}
subgraph cluster_array {
style = invis;
array [label = " array | { <array0> array[0] \n redisSortObject | { <obj0> obj | u.score \n 1.0 } } | { <array1> array[1] \n redisSortObject | { <obj1> obj | u.score \n 2.0 } } | { <array2> array[2] \n redisSortObject | { <obj2> obj | u.score \n 3.0 } } "];
}
array:obj0 -> one;
array:obj1 -> two;
array:obj2 -> three;
label = "\n 图 21-4 排序后的数组";
}](_images/graphviz-23bf735a793da7d7ea48ab58fd014e43bb9fe6b2.png)
ALPHA 选项的实现¶
服务器在执行 SORT fruits ALPHA
时创建的数据结构。
![digraph {
rankdir = LR;
node [shape = record];
subgraph cluster_fruits {
label = "fruits 集合";
style = dashed;
apple [label = "StringObject \n \"apple\""];
banana [label = "StringObject \n \"banana\""];
cherry [label = "StringObject \n \"cherry\""];
apple -> cherry -> banana [style = invis];
}
subgraph cluster_array {
style = invis;
array [label = " array | { <array0> array[0] \n redisSortObject | { <obj0> obj | u } } | { <array1> array[1] \n redisSortObject | { <obj1> obj | u } } | { <array2> array[2] \n redisSortObject | { <obj2> obj | u } } "];
}
array:obj0 -> apple;
array:obj1 -> cherry;
array:obj2 -> banana;
label = "\n 图 21-5 将 obj 指针指向集合的各个元素";
}](_images/graphviz-45ab10494eee039b45ca3b9ce0691a05ffd1357c.png)
![digraph {
rankdir = LR;
node [shape = record];
subgraph cluster_fruits {
label = "fruits 集合";
style = dashed;
apple [label = "StringObject \n \"apple\""];
banana [label = "StringObject \n \"banana\""];
cherry [label = "StringObject \n \"cherry\""];
apple -> cherry -> banana [style = invis];
}
subgraph cluster_array {
style = invis;
array [label = " array | { <array0> array[0] \n redisSortObject | { <obj0> obj | u } } | { <array1> array[1] \n redisSortObject | { <obj1> obj | u } } | { <array2> array[2] \n redisSortObject | { <obj2> obj | u } } "];
}
array:obj0 -> apple;
array:obj1 -> banana;
array:obj2 -> cherry;
label = "\n 图 21-6 按集合元素进行排序后的数组";
}](_images/graphviz-488ec57f14f447fe16b18b9c689139ffec7f2207.png)
ASC 选项和 DESC 选项的实现¶
图 21-7 展示了 SORT 命令在对 numbers
列表执行升序排序时所创建的数组。
![digraph {
rankdir = LR;
node [shape = record];
subgraph cluster_numbers {
label = "numbers 链表"
style = dashed
one [label = "StringObject \n \"1\""];
two [label = "StringObject \n \"2\""];
three [label = "StringObject \n \"3\""];
three -> one -> two;
}
subgraph cluster_array {
style = invis;
array [label = " array | { <array0> array[0] \n redisSortObject | { <obj0> obj | u.score \n 1.0 } } | { <array1> array[1] \n redisSortObject | { <obj1> obj | u.score \n 2.0 } } | { <array2> array[2] \n redisSortObject | { <obj2> obj | u.score \n 3.0 } } "];
}
array:obj0 -> one;
array:obj1 -> two;
array:obj2 -> three;
label = "\n 图 21-7 执行升序排序的数组";
}](_images/graphviz-d86a8eace41784b84e8bf50a66f0ff9a6bacae70.png)
图 21-8 展示了 SORT 命令在对 numbers
列表执行降序排序时所创建的数组。
![digraph {
rankdir = LR;
node [shape = record];
subgraph cluster_numbers {
label = "numbers 链表"
style = dashed;
one [label = "StringObject \n \"1\""];
two [label = "StringObject \n \"2\""];
three [label = "StringObject \n \"3\""];
three -> one -> two;
}
subgraph cluster_array {
style = invis;
array [label = " array | { <array0> array[0] \n redisSortObject | { <obj0> obj | u.score \n 3.0 } } | { <array1> array[1] \n redisSortObject | { <obj1> obj | u.score \n 2.0 } } | { <array2> array[2] \n redisSortObject | { <obj2> obj | u.score \n 1.0 } } "];
}
array:obj0 -> three;
array:obj1 -> two;
array:obj2 -> one;
label = "\n 图 21-8 执行降序排序的数组";
}](_images/graphviz-259078bd242eaf195b6eff7e91fb18a73939a4a5.png)
BY 选项的实现¶
服务器在执行 SORT fruits BY *-price
时创建的数据结构。
![digraph {
rankdir = LR;
node [shape = record];
subgraph cluster_fruits {
label = "fruits 集合";
style = dashed;
apple [label = "StringObject \n \"apple\""];
banana [label = "StringObject \n \"banana\""];
cherry [label = "StringObject \n \"cherry\""];
apple -> cherry -> banana [style = invis];
}
subgraph cluster_array {
style = invis;
array [label = " array | { <array0> array[0] \n redisSortObject | { <obj0> obj | u } } | { <array1> array[1] \n redisSortObject | { <obj1> obj | u } } | { <array2> array[2] \n redisSortObject | { <obj2> obj | u } } "];
}
array:obj0 -> apple;
array:obj1 -> cherry;
array:obj2 -> banana;
label = "\n 图 21-9 将 obj 指针指向集合的各个元素";
}](_images/graphviz-e7c7c36f35cd4283d7dc04133536564669afd43e.png)
![digraph {
rankdir = LR;
node [shape = record];
subgraph cluster_fruits {
label = "fruits 集合";
style = dashed;
apple [label = "StringObject \n \"apple\""];
banana [label = "StringObject \n \"banana\""];
cherry [label = "StringObject \n \"cherry\""];
apple -> cherry -> banana [style = invis];
}
subgraph cluster_array {
style = invis;
array [label = " array | { <array0> array[0] \n redisSortObject | { <obj0> obj | u.score \n 8.0 } } | { <array1> array[1] \n redisSortObject | { <obj1> obj | u.score \n 7.0 } } | { <array2> array[2] \n redisSortObject | { <obj2> obj | u.score \n 5.5 } } "];
}
array:obj0 -> apple;
array:obj1 -> cherry;
array:obj2 -> banana;
label = "\n 图 21-10 根据权重键的值设置数组项的 u.score 属性";
}](_images/graphviz-bb3601e6f4afaae42f6e250faab846704570c377.png)
![digraph {
rankdir = LR;
node [shape = record];
subgraph cluster_fruits {
label = "fruits 集合";
style = dashed;
apple [label = "StringObject \n \"apple\""];
banana [label = "StringObject \n \"banana\""];
cherry [label = "StringObject \n \"cherry\""];
apple -> cherry -> banana [style = invis];
}
subgraph cluster_array {
style = invis;
array [label = " array | { <array0> array[0] \n redisSortObject | { <obj0> obj | u.score \n 5.5 } } | { <array1> array[1] \n redisSortObject | { <obj1> obj | u.score \n 7.0 } } | { <array2> array[2] \n redisSortObject | { <obj2> obj | u.score \n 8.0 } } "];
}
array:obj0 -> banana;
array:obj1 -> cherry;
array:obj2 -> apple;
label = "\n 图 21-11 根据 u.score 属性进行排序之后的数组";
}](_images/graphviz-9e85643e0c9f24dc981add843f85417f85d93be1.png)
带有 ALPHA 选项的 BY 选项的实现¶
服务器执行 SORT fruits BY *-id ALPHA
时创建的数据结构。
![digraph {
rankdir = LR;
node [shape = record];
subgraph cluster_fruits {
label = "fruits 集合";
style = dashed;
apple [label = "StringObject \n \"apple\""];
banana [label = "StringObject \n \"banana\""];
cherry [label = "StringObject \n \"cherry\""];
apple -> cherry -> banana [style = invis];
}
subgraph cluster_array {
style = invis;
array [label = " array | { <array0> array[0] \n redisSortObject | { <obj0> obj | u } } | { <array1> array[1] \n redisSortObject | { <obj1> obj | u } } | { <array2> array[2] \n redisSortObject | { <obj2> obj | u } } "];
}
array:obj0 -> apple;
array:obj1 -> cherry;
array:obj2 -> banana;
label = "\n 图 21-12 将 obj 指针指向集合的各个元素";
}](_images/graphviz-2dd7e4cfe762830e0244c1e16aed7b0010d67df9.png)
![digraph {
rankdir = LR;
node [shape = record];
subgraph cluster_fruits {
label = "fruits 集合";
style = dashed;
apple [label = "StringObject \n \"apple\""];
banana [label = "StringObject \n \"banana\""];
cherry [label = "StringObject \n \"cherry\""];
apple -> cherry -> banana [style = invis];
}
subgraph cluster_array {
style = invis;
array [label = " array | { <array0> array[0] \n redisSortObject | { <obj0> obj | <cmpobj0> u.cmpobj } } | { <array1> array[1] \n redisSortObject | { <obj1> obj | <cmpobj1> u.cmpobj } } | { <array2> array[2] \n redisSortObject | { <obj2> obj | <cmpobj2> u.cmpobj } } "];
}
array:obj0 -> apple;
array:obj1 -> cherry;
array:obj2 -> banana;
apple_id [label = "StringObject \n \"FRUIT-25\""];
banana_id [label = "StringObject \n \"FRUIT-79\""];
cherry_id [label = "StringObject \n \"FRUIT-13\""];
array:cmpobj0 -> apple_id;
array:cmpobj1 -> cherry_id;
array:cmpobj2 -> banana_id;
label = "\n 图 21-13 将 u.cmpobj 指针指向权重键";
}](_images/graphviz-2c3cf9e606db4cb58e6f65d743e95e5efd6ed547.png)
![digraph {
rankdir = LR;
node [shape = record];
subgraph cluster_fruits {
label = "fruits 集合";
style = dashed;
apple [label = "StringObject \n \"apple\""];
banana [label = "StringObject \n \"banana\""];
cherry [label = "StringObject \n \"cherry\""];
apple -> cherry -> banana [style = invis];
}
subgraph cluster_array {
style = invis;
array [label = " array | { <array0> array[0] \n redisSortObject | { <obj0> obj | <cmpobj0> u.cmpobj } } | { <array1> array[1] \n redisSortObject | { <obj1> obj | <cmpobj1> u.cmpobj } } | { <array2> array[2] \n redisSortObject | { <obj2> obj | <cmpobj2> u.cmpobj } } "];
}
array:obj0 -> cherry;
array:obj1 -> apple;
array:obj2 -> banana;
apple_id [label = "StringObject \n \"FRUIT-25\""];
banana_id [label = "StringObject \n \"FRUIT-79\""];
cherry_id [label = "StringObject \n \"FRUIT-13\""];
array:cmpobj0 -> cherry_id;
array:cmpobj1 -> apple_id;
array:cmpobj2 -> banana_id;
label = "\n 图 21-14 按 u.cmpobj 所指向的字符串对象进行排序之后的数组";
}](_images/graphviz-b6cac9b06daff11446d3242ff680e9d3a3586292.png)
LIMIT 选项的实现¶
服务器在执行 SORT alphabet ALPHA LIMIT 0 4
时创建的数据结构。
![digraph {
rankdir = LR;
subgraph cluster_alphabet {
label = "alphabet 集合\n";
style = dashed;
node [shape = box];
a [label = "StringObject \n \"a\""];
b [label = "StringObject \n \"b\""];
c [label = "StringObject \n \"c\""];
d [label = "StringObject \n \"d\""];
e [label = "StringObject \n \"e\""];
f [label = "StringObject \n \"f\""];
edge [style = invis];
d -> c -> a;
b -> f -> e;
}
array [label = " array | { array[0] \n redisSortObject | { <obj0> obj | u } } | { array[1] \n redisSortObject | { <obj1> obj | u } } | { array[2] \n redisSortObject | { <obj2> obj | u } } | { array[3] \n redisSortObject | { <obj3> obj | u } } | { array[4] \n redisSortObject | { <obj4> obj | u } } | { array[5] \n redisSortObject | { <obj5> obj | u } } ", shape = record];
edge [minlen = 2.0];
array:obj0 -> d;
array:obj1 -> c;
array:obj2 -> a;
array:obj3 -> b;
array:obj4 -> f;
array:obj5 -> e;
label = "\n 图 21-15 将 obj 指针指向集合的各个元素";
}](_images/graphviz-22368e7bb6e0d30da1ce121e25d82607446f4737.png)
![digraph {
rankdir = LR;
subgraph cluster_alphabet {
label = "alphabet 集合\n\n";
style = dashed;
node [shape = box];
a [label = "StringObject \n \"a\""];
b [label = "StringObject \n \"b\""];
c [label = "StringObject \n \"c\""];
d [label = "StringObject \n \"d\""];
e [label = "StringObject \n \"e\""];
f [label = "StringObject \n \"f\""];
edge [style = invis];
d -> c -> a;
b -> f -> e;
}
array [label = " array | { array[0] \n redisSortObject | { <obj0> obj | u } } | { array[1] \n redisSortObject | { <obj1> obj | u } } | { array[2] \n redisSortObject | { <obj2> obj | u } } | { array[3] \n redisSortObject | { <obj3> obj | u } } | { array[4] \n redisSortObject | { <obj4> obj | u } } | { array[5] \n redisSortObject | { <obj5> obj | u } } ", shape = record];
edge [minlen = 2.0];
array:obj0 -> a;
array:obj1 -> b;
array:obj2 -> c;
array:obj3 -> d;
array:obj4 -> e;
array:obj5 -> f;
label = "\n 图 21-16 排序后的数组";
}](_images/graphviz-83e0fb431e579f08239fc5bf79c15b9912e53e0e.png)
GET 选项的实现¶
服务器在执行 SORT students ALPHA GET *-name
时创建的数据结构。
![digraph {
rankdir = LR;
subgraph cluster_students {
label = "students 集合";
style = dashed;
node [shape = box];
peter [label = "StringObject \n \"peter\""];
jack [label = "StringObject \n \"jack\""];
tom [label = "StringObject \n \"tom\""];
peter -> jack -> tom [style = invis];
}
node [shape = record];
array [label = " array | { array[0] \n redisSortObject | { <obj0> obj | u } } | { array[1] \n redisSortObject | { <obj1> obj | u } } | { array[2] \n redisSortObject | { <obj2> obj | u } } "];
array:obj0 -> peter;
array:obj1 -> jack;
array:obj2 -> tom;
label = "\n 图 21-17 排序之前的数组";
}](_images/graphviz-e8eda4fc6841d6db907e39d1aa71810410199fc5.png)
![digraph {
rankdir = LR;
subgraph cluster_students {
label = "students 集合";
style = dashed;
node [shape = box];
peter [label = "StringObject \n \"peter\""];
jack [label = "StringObject \n \"jack\""];
tom [label = "StringObject \n \"tom\""];
peter -> jack -> tom [style = invis];
}
node [shape = record];
array [label = " array | { array[0] \n redisSortObject | { <obj0> obj | u } } | { array[1] \n redisSortObject | { <obj1> obj | u } } | { array[2] \n redisSortObject | { <obj2> obj | u } } "];
array:obj0 -> jack;
array:obj1 -> peter;
array:obj2 -> tom;
label = "\n 图 21-18 排序之后的数组";
}](_images/graphviz-25d5b2b41641ef21c4b12579800b17534d30f13d.png)