一、reset实现
知识点:当score相同时,按照 value 的字典序排序
1)ziplist
健值对数量小于128个,并且每一个元素长度小于64位
2)skiplist
源码数据结构的定义:
typedef struct zskiplistNode {
robj *obj; //节点数据
double score; //score对应的分数
struct zskiplistNode *backward; //后退指针
struct zskiplistLevel {
struct zskiplistNode *forward; //前向指针
unsigned int span; //表示当前指针跨越了多少个节点,用于计算排名
} level[];
} zskiplistNode;
typedef struct zskiplist {
struct zskiplistNode *header, *tail; //头指针、尾指针
unsigned long length; //链表的长度
int level; //skiplist总层数
} zskiplist;
二、使用场景:
1)延迟队列:
将 score 设置为到期时间,然后通过额外的进程,去获取到期的 score 进行分布式的消费;常见的用法:超时订单的取消
此处需要考虑的问题是:redis无ack机制,因此需要考虑消费失败的情况需要怎么去处理
2)排行榜
战力排行榜:
zadd power_ranking 20 name1 30 name2 ......
zadd power_ranking 40 name1 //更新战力
zincrby power_ranking -10 name1 //name1战力减少 10
zrange power_ranking 0 2 withscores //获取排名列表
3)滑动窗口限流
将用户ID作为key,时间戳作为 score 和 member; 然后通过 zcount key score_start score_end 获取数量;判断是否可以继续即可:
伪代码:
client_id := xxxxx;
now_time_stamp := int(time.Now().Unix())
request_time := redis.zcount(client_id, now_time_stamp - 1000, now_time_stamp)
if request_time > max_request_count {
return "max_request"
}
redis.Zadd(client_id, now_time_stamp, now_time_stamp)
参考地址:
1、redis跳表扫盲:https://juejin.cn/post/6844904164120608781#comment
2、底层结构之zset:http://t.zoukankan.com/reecelin-p-13368374.html