有序集初体验:
先来看几个后续会使用的redis命令语法:
1 2 3 4 5 6 7 8 9 10 11 |
|
更详细和完整的命令, 请点击该链接.
• 案例设计
输入5个学生的成绩(name, score), 实现top-3的查询, 修改某个同学的得分, 再次查询top-3.
1). 添加成绩记录
添加 (lucy, 61), (lily 60), (uncle wang, 10), (lilei, 98), (hanmeimei, 99) 这5人的成绩, 并假定class_rank 为sorted set的name.
2). 第一次top-3查询
3). 更新uncle wang的分数
注: zadd命令既可以添加, 也可以更新
4). 再次top-3查询
场景的设计, 以及最后输出的结果与预期符合.看来redis的sorted set满足需求, 而且特别的方便.
原理浅析:
有了前文的直观体验, 再来研究redis中的有序集合(sorted set), 究竟是何种数据结构, 它能提供什么样的接口, 以及满足什么样的需求呢?
我们来探究下它支持的功能, 首先当然就是支持按分值排序的功能. 由此可以猜测它底层是按score为key, name为value的tree结构(因为支持范围查询, 以及按分值排序). 但是该有序集又支持按name来修改score. 这样需求下, 又演变成name为key, score为value的map结构了. 单独的一种数据结构, 无法满足其需求, 两个都不可或缺. 那答案究竟是什么?
redis源码的定义如下:
1 2 3 4 5 6 |
|
这样就比较清晰了, 它采用了复合结构, 字典维护了name=>score的映射表, 而跳跃表则维护了按score排序的列表. 按name和按score的范围查询都天然支持.
具体的解读,可参考<<redis 设计和实现--有序集>>.同时引用官文文档的一张示意图: